diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh
new file mode 100755
index 0000000000..b22ad95310
--- /dev/null
+++ b/.ci/linux-build.sh
@@ -0,0 +1,244 @@
+#!/bin/bash
+
+set -o errexit
+set -x
+
+CFLAGS_FOR_OVS="-g -O2"
+SPARSE_FLAGS=""
+EXTRA_OPTS="--enable-Werror"
+TARGET="x86_64-native-linuxapp-gcc"
+
+function install_kernel()
+{
+    if [[ "$1" =~ ^5.* ]]; then
+        PREFIX="v5.x"
+    elif [[ "$1" =~ ^4.* ]]; then
+        PREFIX="v4.x"
+    elif [[ "$1" =~ ^3.* ]]; then
+        PREFIX="v3.x"
+    else
+        PREFIX="v2.6/longterm/v2.6.32"
+    fi
+
+    base_url="https://cdn.kernel.org/pub/linux/kernel/${PREFIX}"
+    # Download page with list of all available kernel versions.
+    wget ${base_url}/
+    # Uncompress in case server returned gzipped page.
+    (file index* | grep ASCII) || (mv index* index.new.gz && gunzip index*)
+    # Get version of the latest stable release.
+    hi_ver=$(echo ${1} | sed 's/\./\\\./')
+    lo_ver=$(cat ./index* | grep -P -o "${hi_ver}\.[0-9]+" | \
+             sed 's/.*\..*\.\(.*\)/\1/' | sort -h | tail -1)
+    version="${1}.${lo_ver}"
+
+    rm -rf index* linux-*
+
+    url="${base_url}/linux-${version}.tar.xz"
+    # Download kernel sources. Try direct link on CDN failure.
+    wget ${url} ||
+    (rm -f linux-${version}.tar.xz && wget ${url}) ||
+    (rm -f linux-${version}.tar.xz && wget ${url/cdn/www})
+
+    tar xvf linux-${version}.tar.xz > /dev/null
+    pushd linux-${version}
+    make allmodconfig
+
+    # Cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is not supported by compiler
+    sed -i 's/CONFIG_KCOV=y/CONFIG_KCOV=n/' .config
+
+    # stack validation depends on tools/objtool, but objtool does not compile on travis.
+    # It is giving following error.
+    #  >>> GEN      arch/x86/insn/inat-tables.c
+    #  >>> Semantic error at 40: Unknown imm opnd: AL
+    # So for now disable stack-validation for the build.
+
+    sed -i 's/CONFIG_STACK_VALIDATION=y/CONFIG_STACK_VALIDATION=n/' .config
+    make oldconfig
+
+    # Older kernels do not include openvswitch
+    if [ -d "net/openvswitch" ]; then
+        make net/openvswitch/
+    else
+        make net/bridge/
+    fi
+
+    if [ "$AFXDP" ]; then
+        sudo make headers_install INSTALL_HDR_PATH=/usr
+        pushd tools/lib/bpf/
+        # Bulding with gcc because there are some issues in make files
+        # that breaks building libbpf with clang on Travis.
+        CC=gcc sudo make install
+        CC=gcc sudo make install_headers
+        sudo ldconfig
+        popd
+        # The Linux kernel defines __always_inline in stddef.h (283d7573), and
+        # sys/cdefs.h tries to re-define it.  Older libc-dev package in xenial
+        # doesn't have a fix for this issue.  Applying it manually.
+        sudo sed -i '/^# define __always_inline .*/i # undef __always_inline' \
+                    /usr/include/x86_64-linux-gnu/sys/cdefs.h || true
+        EXTRA_OPTS="${EXTRA_OPTS} --enable-afxdp"
+    else
+        EXTRA_OPTS="${EXTRA_OPTS} --with-linux=$(pwd)"
+        echo "Installed kernel source in $(pwd)"
+    fi
+    popd
+}
+
+function install_dpdk()
+{
+    local DPDK_VER=$1
+    local VERSION_FILE="dpdk-dir/travis-dpdk-cache-version"
+
+    if [ "${DPDK_VER##refs/*/}" != "${DPDK_VER}" ]; then
+        # Avoid using cache for git tree build.
+        rm -rf dpdk-dir
+
+        DPDK_GIT=${DPDK_GIT:-https://dpdk.org/git/dpdk}
+        git clone --single-branch $DPDK_GIT dpdk-dir -b "${DPDK_VER##refs/*/}"
+        pushd dpdk-dir
+        git log -1 --oneline
+    else
+        if [ -f "${VERSION_FILE}" ]; then
+            VER=$(cat ${VERSION_FILE})
+            if [ "${VER}" = "${DPDK_VER}" ]; then
+                EXTRA_OPTS="${EXTRA_OPTS} --with-dpdk=$(pwd)/dpdk-dir/build"
+                echo "Found cached DPDK ${VER} build in $(pwd)/dpdk-dir"
+                return
+            fi
+        fi
+        # No cache or version mismatch.
+        rm -rf dpdk-dir
+        wget https://fast.dpdk.org/rel/dpdk-$1.tar.xz
+        tar xvf dpdk-$1.tar.xz > /dev/null
+        DIR_NAME=$(tar -tf dpdk-$1.tar.xz | head -1 | cut -f1 -d"/")
+        mv ${DIR_NAME} dpdk-dir
+        pushd dpdk-dir
+    fi
+
+    make config CC=gcc T=$TARGET
+
+    if [ "$DPDK_SHARED" ]; then
+        sed -i '/CONFIG_RTE_BUILD_SHARED_LIB=n/s/=n/=y/' build/.config
+        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/$TARGET/lib
+    fi
+
+    # Disable building DPDK kernel modules. Not needed for OVS build or tests.
+    sed -i '/CONFIG_RTE_EAL_IGB_UIO=y/s/=y/=n/' build/.config
+    sed -i '/CONFIG_RTE_KNI_KMOD=y/s/=y/=n/' build/.config
+
+    # Enable pdump support in DPDK.
+    sed -i '/CONFIG_RTE_LIBRTE_PMD_PCAP=n/s/=n/=y/' build/.config
+    sed -i '/CONFIG_RTE_LIBRTE_PDUMP=n/s/=n/=y/' build/.config
+
+    # Switching to 'default' machine to make dpdk-dir cache usable on different
+    # CPUs.  We can't be sure that all CI machines are exactly same.
+    sed -i '/CONFIG_RTE_MACHINE="native"/s/="native"/="default"/' build/.config
+
+    make -j4 CC=gcc EXTRA_CFLAGS='-fPIC'
+    EXTRA_OPTS="$EXTRA_OPTS --with-dpdk=$(pwd)/build"
+    echo "Installed DPDK source in $(pwd)"
+    popd
+    echo "${DPDK_VER}" > ${VERSION_FILE}
+}
+
+function configure_ovs()
+{
+    ./boot.sh
+    ./configure CFLAGS="${CFLAGS_FOR_OVS}" $* || { cat config.log; exit 1; }
+}
+
+function build_ovs()
+{
+    local KERNEL=$1
+
+    configure_ovs $OPTS
+    make selinux-policy
+
+    # Only build datapath if we are testing kernel w/o running testsuite and
+    # AF_XDP support.
+    if [ "${KERNEL}" ] && ! [ "$AFXDP" ]; then
+        pushd datapath
+        make -j4
+        popd
+    else
+        make -j4 || { cat config.log; exit 1; }
+    fi
+}
+
+if [ "$DEB_PACKAGE" ]; then
+    mk-build-deps --install --root-cmd sudo --remove debian/control
+    dpkg-checkbuilddeps
+    DEB_BUILD_OPTIONS='parallel=4 nocheck' fakeroot debian/rules binary
+    # Not trying to install ipsec package as there are issues with system-wide
+    # installed python3-openvswitch package and the pyenv used by Travis.
+    packages=$(ls $(pwd)/../*.deb | grep -v ipsec)
+    sudo apt install ${packages}
+    exit 0
+fi
+
+if [ "$KERNEL" ]; then
+    install_kernel $KERNEL
+fi
+
+if [ "$DPDK" ] || [ "$DPDK_SHARED" ]; then
+    if [ -z "$DPDK_VER" ]; then
+        DPDK_VER="19.11.8"
+    fi
+    install_dpdk $DPDK_VER
+    # Enable pdump support in OVS.
+    EXTRA_OPTS="${EXTRA_OPTS} --enable-dpdk-pdump"
+    if [ "$CC" = "clang" ]; then
+        # Disregard cast alignment errors until DPDK is fixed
+        CFLAGS_FOR_OVS="${CFLAGS_FOR_OVS} -Wno-cast-align"
+    fi
+fi
+
+if [ "$CC" = "clang" ]; then
+    CFLAGS_FOR_OVS="${CFLAGS_FOR_OVS} -Wno-error=unused-command-line-argument"
+elif [ "$M32" ]; then
+    # Not using sparse for 32bit builds on 64bit machine.
+    # Adding m32 flag directly to CC to avoid any posiible issues with API/ABI
+    # difference on 'configure' and 'make' stages.
+    export CC="$CC -m32"
+else
+    OPTS="--enable-sparse"
+    if [ "$AFXDP" ]; then
+        # netdev-afxdp uses memset for 64M for umem initialization.
+        SPARSE_FLAGS="${SPARSE_FLAGS} -Wno-memcpy-max-count"
+    fi
+    CFLAGS_FOR_OVS="${CFLAGS_FOR_OVS} ${SPARSE_FLAGS}"
+fi
+
+save_OPTS="${OPTS} $*"
+OPTS="${EXTRA_OPTS} ${save_OPTS}"
+
+if [ "$TESTSUITE" ]; then
+    # 'distcheck' will reconfigure with required options.
+    # Now we only need to prepare the Makefile without sparse-wrapped CC.
+    configure_ovs
+
+    export DISTCHECK_CONFIGURE_FLAGS="$OPTS"
+    if ! make distcheck -j4 CFLAGS="${CFLAGS_FOR_OVS}" \
+         TESTSUITEFLAGS=-j4 RECHECK=yes; then
+        # testsuite.log is necessary for debugging.
+        cat */_build/sub/tests/testsuite.log
+        exit 1
+    fi
+else
+    if [ -z "${KERNEL_LIST}" ]; then build_ovs ${KERNEL};
+    else
+        save_EXTRA_OPTS="${EXTRA_OPTS}"
+        for KERNEL in ${KERNEL_LIST}; do
+            echo "=============================="
+            echo "Building with kernel ${KERNEL}"
+            echo "=============================="
+            EXTRA_OPTS="${save_EXTRA_OPTS}"
+            install_kernel ${KERNEL}
+            OPTS="${EXTRA_OPTS} ${save_OPTS}"
+            build_ovs ${KERNEL}
+            make distclean
+        done
+    fi
+fi
+
+exit 0
diff --git a/.ci/linux-prepare.sh b/.ci/linux-prepare.sh
new file mode 100755
index 0000000000..fea905a830
--- /dev/null
+++ b/.ci/linux-prepare.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+set -ev
+
+if [ "$DEB_PACKAGE" ]; then
+    # We're not using sparse for debian packages, tests are skipped and
+    # all extra dependencies tracked by mk-build-deps.
+    exit 0
+fi
+
+# Build and install sparse.
+#
+# Explicitly disable sparse support for llvm because some travis
+# environments claim to have LLVM (llvm-config exists and works) but
+# linking against it fails.
+# Disabling sqlite support because sindex build fails and we don't
+# really need this utility being installed.
+git clone git://git.kernel.org/pub/scm/devel/sparse/sparse.git
+cd sparse
+make -j4 HAVE_LLVM= HAVE_SQLITE= install
+cd ..
+
+pip3 install --disable-pip-version-check --user flake8 hacking
+pip3 install --user --upgrade docutils
+
+if [ "$M32" ]; then
+    # Installing 32-bit libraries.
+    pkgs="gcc-multilib"
+    if [ -z "$GITHUB_WORKFLOW" ]; then
+        # 32-bit and 64-bit libunwind can not be installed at the same time.
+        # This will remove the 64-bit libunwind and install 32-bit version.
+        # GitHub Actions doesn't have 32-bit versions of these libs.
+        pkgs=$pkgs" libunwind-dev:i386 libunbound-dev:i386"
+    fi
+
+    sudo apt-get install -y $pkgs
+fi
+
+# IPv6 is supported by kernel but disabled in TravisCI images:
+#   https://github.com/travis-ci/travis-ci/issues/8891
+# Enable it to avoid skipping of IPv6 related tests.
+sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
diff --git a/.ci/osx-build.sh b/.ci/osx-build.sh
new file mode 100755
index 0000000000..bf2c13fa3c
--- /dev/null
+++ b/.ci/osx-build.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -o errexit
+
+CFLAGS="-Werror $CFLAGS"
+EXTRA_OPTS=""
+
+function configure_ovs()
+{
+    ./boot.sh && ./configure $*
+}
+
+configure_ovs $EXTRA_OPTS $*
+
+if [ "$CC" = "clang" ]; then
+    set make CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument"
+else
+    set make CFLAGS="$CFLAGS $BUILD_ENV"
+fi
+if ! "$@"; then
+    cat config.log
+    exit 1
+fi
+if [ "$TESTSUITE" ] && [ "$CC" != "clang" ]; then
+    if ! make distcheck RECHECK=yes; then
+        # testsuite.log is necessary for debugging.
+        cat */_build/sub/tests/testsuite.log
+        exit 1
+    fi
+fi
+
+exit 0
diff --git a/.ci/osx-prepare.sh b/.ci/osx-prepare.sh
new file mode 100755
index 0000000000..b6447aba1b
--- /dev/null
+++ b/.ci/osx-prepare.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+set -ev
+pip3 install --user --upgrade docutils
diff --git a/.cirrus.yml b/.cirrus.yml
index 1b32f55d65..480fea2421 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -2,21 +2,23 @@ freebsd_build_task:
 
   freebsd_instance:
     matrix:
-      image_family: freebsd-12-1-snap
-      image_family: freebsd-11-3-snap
+      image_family: freebsd-12-2-snap
+      image_family: freebsd-11-4-snap
     cpu: 4
-    memory: 8G
+    memory: 4G
 
   env:
-    DEPENDENCIES: automake libtool gmake gcc wget openssl
-                  python3 py37-openssl py37-sphinx
+    DEPENDENCIES: automake libtool gmake gcc wget openssl python3
+    PY_DEPS:      sphinx|openssl
     matrix:
       COMPILER: gcc
       COMPILER: clang
 
   prepare_script:
     - sysctl -w kern.coredump=0
+    - pkg update -f
     - pkg install -y ${DEPENDENCIES}
+        $(pkg search -xq "^py3[0-9]+-(${PY_DEPS})-[0-9]+" | xargs)
 
   configure_script:
     - ./boot.sh
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
new file mode 100644
index 0000000000..c1b88264c2
--- /dev/null
+++ b/.github/workflows/build-and-test.yml
@@ -0,0 +1,211 @@
+name: Build and Test
+
+on: [push, pull_request]
+
+jobs:
+  build-linux:
+    env:
+      dependencies: |
+        automake libtool gcc bc libjemalloc1 libjemalloc-dev    \
+        libssl-dev llvm-dev libelf-dev libnuma-dev libpcap-dev  \
+        python3-openssl python3-pip python3-sphinx              \
+        selinux-policy-dev
+      deb_dependencies: |
+        linux-headers-$(uname -r) build-essential fakeroot devscripts equivs
+      AFXDP:       ${{ matrix.afxdp }}
+      CC:          ${{ matrix.compiler }}
+      DEB_PACKAGE: ${{ matrix.deb_package }}
+      DPDK:        ${{ matrix.dpdk }}
+      DPDK_SHARED: ${{ matrix.dpdk_shared }}
+      KERNEL:      ${{ matrix.kernel }}
+      KERNEL_LIST: ${{ matrix.kernel_list }}
+      LIBS:        ${{ matrix.libs }}
+      M32:         ${{ matrix.m32 }}
+      OPTS:        ${{ matrix.opts }}
+      TESTSUITE:   ${{ matrix.testsuite }}
+
+    name: linux ${{ join(matrix.*, ' ') }}
+    runs-on: ubuntu-18.04
+    timeout-minutes: 30
+
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - compiler:     gcc
+            opts:         --disable-ssl
+          - compiler:     clang
+            opts:         --disable-ssl
+
+          - compiler:     gcc
+            testsuite:    test
+            kernel:       3.16
+          - compiler:     clang
+            testsuite:    test
+            kernel:       3.16
+
+          - compiler:     gcc
+            testsuite:    test
+            opts:         --enable-shared
+          - compiler:     clang
+            testsuite:    test
+            opts:         --enable-shared
+
+          - compiler:     gcc
+            testsuite:    test
+            dpdk:         dpdk
+          - compiler:     clang
+            testsuite:    test
+            dpdk:         dpdk
+
+          - compiler:     gcc
+            testsuite:    test
+            libs:         -ljemalloc
+          - compiler:     clang
+            testsuite:    test
+            libs:         -ljemalloc
+
+          - compiler:     gcc
+            kernel_list:  5.0 4.20 4.19 4.18 4.17 4.16
+          - compiler:     clang
+            kernel_list:  5.0 4.20 4.19 4.18 4.17 4.16
+
+          - compiler:     gcc
+            kernel_list:  4.15 4.14 4.9 4.4 3.16
+          - compiler:     clang
+            kernel_list:  4.15 4.14 4.9 4.4 3.16
+
+          - compiler:     gcc
+            afxdp:        afxdp
+            kernel:       5.3
+          - compiler:     clang
+            afxdp:        afxdp
+            kernel:       5.3
+
+          - compiler:     gcc
+            dpdk:         dpdk
+            opts:         --enable-shared
+          - compiler:     clang
+            dpdk:         dpdk
+            opts:         --enable-shared
+
+          - compiler:     gcc
+            dpdk_shared:  dpdk-shared
+          - compiler:     clang
+            dpdk_shared:  dpdk-shared
+
+          - compiler:     gcc
+            dpdk_shared:  dpdk-shared
+            opts:         --enable-shared
+          - compiler:     clang
+            dpdk_shared:  dpdk-shared
+            opts:         --enable-shared
+
+          - compiler:     gcc
+            m32:          m32
+            opts:         --disable-ssl
+
+          - compiler:     gcc
+            deb_package:  deb
+
+    steps:
+    - name: checkout
+      uses: actions/checkout@v2
+
+    - name: fix up /etc/hosts
+      # https://github.com/actions/virtual-environments/issues/3353
+      run:  |
+        cat /etc/hosts
+        sudo sed -i "/don't remove this line/d" /etc/hosts || true
+
+    - name: create ci signature file for the dpdk cache key
+      if:   matrix.dpdk != '' || matrix.dpdk_shared != ''
+      # This will collect most of DPDK related lines, so hash will be different
+      # if something changed in a way we're building DPDK including DPDK_VER.
+      # This also allows us to use cache from any branch as long as version
+      # and a way we're building DPDK stays the same.
+      run:  |
+        grep -irE 'RTE_|DPDK|meson|ninja' -r .ci/ > dpdk-ci-signature
+        cat dpdk-ci-signature
+
+    - name: cache
+      if:   matrix.dpdk != '' || matrix.dpdk_shared != ''
+      uses: actions/cache@v2
+      env:
+        matrix_key: ${{ matrix.dpdk }}${{ matrix.dpdk_shared }}
+        ci_key:     ${{ hashFiles('dpdk-ci-signature') }}
+      with:
+        path: dpdk-dir
+        key:  ${{ env.matrix_key }}-${{ env.ci_key }}
+
+    - name: update APT cache
+      run:  sudo apt update || true
+    - name: install common dependencies
+      if:   matrix.deb_package == ''
+      run:  sudo apt install -y ${{ env.dependencies }}
+    - name: install dependencies for debian packages
+      if:   matrix.deb_package != ''
+      run:  sudo apt install -y ${{ env.deb_dependencies }}
+    - name: install libunbound libunwind
+      if:   matrix.m32 == ''
+      run:  sudo apt install -y libunbound-dev libunwind-dev
+
+    - name: prepare
+      run:  ./.ci/linux-prepare.sh
+
+    - name: build
+      run:  PATH="$PATH:$HOME/bin" ./.ci/linux-build.sh
+
+    - name: upload deb packages
+      if:   matrix.deb_package != ''
+      uses: actions/upload-artifact@v2
+      with:
+        name: deb-packages
+        path: '/home/runner/work/ovs/*.deb'
+
+    - name: copy logs on failure
+      if: failure() || cancelled()
+      run: |
+        # upload-artifact@v2 throws exceptions if it tries to upload socket
+        # files and we could have some socket files in testsuite.dir.
+        # Also, upload-artifact@v2 doesn't work well enough with wildcards.
+        # So, we're just archiving everything here to avoid any issues.
+        mkdir logs
+        cp config.log ./logs/
+        cp -r ./*/_build/sub/tests/testsuite.* ./logs/ || true
+        tar -czvf logs.tgz logs/
+
+    - name: upload logs on failure
+      if: failure() || cancelled()
+      uses: actions/upload-artifact@v2
+      with:
+        name: logs-linux-${{ join(matrix.*, '-') }}
+        path: logs.tgz
+
+  build-osx:
+    env:
+      CC:    clang
+      OPTS:  --disable-ssl
+
+    name:    osx clang --disable-ssl
+    runs-on: macos-latest
+    timeout-minutes: 30
+
+    strategy:
+      fail-fast: false
+
+    steps:
+    - name: checkout
+      uses: actions/checkout@v2
+    - name: install dependencies
+      run:  brew install automake libtool
+    - name: prepare
+      run:  ./.ci/osx-prepare.sh
+    - name: build
+      run:  PATH="$PATH:$HOME/bin" ./.ci/osx-build.sh
+    - name: upload logs on failure
+      if: failure()
+      uses: actions/upload-artifact@v2
+      with:
+        name: logs-osx-clang---disable-ssl
+        path: config.log
diff --git a/AUTHORS.rst b/AUTHORS.rst
index fe3935fca2..4c8772f63a 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -419,6 +419,7 @@ Zhenyu Gao                         sysugaozhenyu@gmail.com
 ZhiPeng Lu                         luzhipeng@uniudc.com
 Zhou Yangchao                      1028519445@qq.com
 aginwala                           amginwal@gmail.com
+lzhecheng                          lzhecheng@vmware.com
 parameswaran krishnamurthy         parkrish@gmail.com
 solomon                            liwei.solomon@gmail.com
 wenxu                              wenxu@ucloud.cn
@@ -496,6 +497,7 @@ Edwin Chiu                      echiu@vmware.com
 Eivind Bulie Haanaes
 Enas Ahmad                      enas.ahmad@kaust.edu.sa
 Eric Lopez
+Frank Wang (王培辉)             wangpeihui@inspur.com
 Frido Roose                     fr.roose@gmail.com
 Gaetano Catalli                 gaetano.catalli@gmail.com
 Gavin Remaley                   gavin_remaley@selinc.com
@@ -558,6 +560,7 @@ Krishna Miriyala                miriyalak@vmware.com
 Krishna Mohan Elluru            elluru.kri.mohan@hpe.com
 László Sürü                     laszlo.suru@ericsson.com
 Len Gao                         leng@vmware.com
+Linhaifeng                      haifeng.lin@huawei.com
 Logan Rosen                     logatronico@gmail.com
 Luca Falavigna                  dktrkranz@debian.org
 Luiz Henrique Ozaki             luiz.ozaki@gmail.com
@@ -655,6 +658,7 @@ Ying Chen                       yingchen@vmware.com
 Yongqiang Liu                   liuyq7809@gmail.com
 ZHANG Zhiming                   zhangzhiming@yunshan.net.cn
 Zhangguanghui                   zhang.guanghui@h3c.com
+Zheng Jingzhou                  glovejmm@163.com
 Ziyou Wang                      ziyouw@vmware.com
 ankur dwivedi                   ankurengg2003@gmail.com
 chen zhang                      3zhangchen9211@gmail.com
diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 22976a3cd6..f46ec988a3 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -217,8 +217,13 @@ install-man-rst: docs-check
 	    $(extract_stem_and_section); \
 	    echo " $(MKDIR_P) '$(DESTDIR)'\"$$mandir\""; \
 	    $(MKDIR_P) '$(DESTDIR)'"$$mandir"; \
-	    echo " $(INSTALL_DATA) $(SPHINXBUILDDIR)/man/$$stem.$$section '$(DESTDIR)'\"$$mandir/$$stem.$$section\""; \
-	    $(INSTALL_DATA) $(SPHINXBUILDDIR)/man/$$stem.$$section '$(DESTDIR)'"$$mandir/$$stem.$$section"; \
+	    if test -f $(SPHINXBUILDDIR)/man/$$stem.$$section; then \
+	        filepath=$(SPHINXBUILDDIR)/man/$$stem.$$section; \
+	    else \
+	        filepath=$(SPHINXBUILDDIR)/man/$$section/$$stem.$$section; \
+	    fi; \
+	    echo " $(INSTALL_DATA) $$filepath '$(DESTDIR)'\"$$mandir/$$stem.$$section\""; \
+	    $(INSTALL_DATA) $$filepath '$(DESTDIR)'"$$mandir/$$stem.$$section"; \
 	done
 else
 install-man-rst:
diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst
index 6702c58a2b..70a0e9b221 100644
--- a/Documentation/faq/releases.rst
+++ b/Documentation/faq/releases.rst
@@ -67,9 +67,10 @@ Q: What Linux kernel versions does each Open vSwitch release work with?
     2.7.x        3.10 to 4.9
     2.8.x        3.10 to 4.12
     2.9.x        3.10 to 4.13
-    2.10.x       3.10 to 4.17
-    2.11.x       3.10 to 4.18
-    2.12.x       3.10 to 5.0
+    2.10.x       3.16 to 4.17
+    2.11.x       3.16 to 4.18
+    2.12.x       3.16 to 5.0
+    2.13.x       3.16 to 5.0
     ============ ==============
 
     Open vSwitch userspace should also work with the Linux kernel module built
@@ -78,6 +79,10 @@ Q: What Linux kernel versions does each Open vSwitch release work with?
     Open vSwitch userspace is not sensitive to the Linux kernel version.  It
     should build against almost any kernel, certainly against 2.6.32 and later.
 
+    Open vSwitch branches 2.10 through 2.13 will still compile against the
+    RHEL and CentOS 7 3.10 based kernels since they have diverged from the
+    Linux kernel.org 3.10 kernels.
+
 Q: Are all features available with all datapaths?
 
     A: Open vSwitch supports different datapaths on different platforms.  Each
@@ -173,9 +178,9 @@ Q: What DPDK version does each Open vSwitch release work with?
     A: The following table lists the DPDK version against which the given
     versions of Open vSwitch will successfully build.
 
-    ============ =======
+    ============ ========
     Open vSwitch DPDK
-    ============ =======
+    ============ ========
     2.2.x        1.6
     2.3.x        1.6
     2.4.x        2.0
@@ -183,11 +188,12 @@ Q: What DPDK version does each Open vSwitch release work with?
     2.6.x        16.07.2
     2.7.x        16.11.9
     2.8.x        17.05.2
-    2.9.x        17.11.4
-    2.10.x       17.11.4
-    2.11.x       18.11.5
-    2.12.x       18.11.5
-    ============ =======
+    2.9.x        17.11.10
+    2.10.x       17.11.10
+    2.11.x       18.11.11
+    2.12.x       18.11.11
+    2.13.x       19.11.8
+    ============ ========
 
 Q: Are all the DPDK releases that OVS versions work with maintained?
 
diff --git a/Documentation/internals/contributing/submitting-patches.rst b/Documentation/internals/contributing/submitting-patches.rst
index 5a314cc60a..f2039595e7 100644
--- a/Documentation/internals/contributing/submitting-patches.rst
+++ b/Documentation/internals/contributing/submitting-patches.rst
@@ -68,11 +68,9 @@ Testing is also important:
   feature.  A bug fix patch should preferably add a test that would
   fail if the bug recurs.
 
-If you are using GitHub, then you may utilize the travis-ci.org CI build system
-by linking your GitHub repository to it. This will run some of the above tests
-automatically when you push changes to your repository.  See the "Continuous
-Integration with Travis-CI" in :doc:`/topics/testing` for details on how to set
-it up.
+If you are using GitHub, then you may utilize the GitHub Actions CI build
+system.  It will run some of the above tests automatically when you push
+changes to your repository.
 
 Email Subject
 -------------
diff --git a/Documentation/intro/install/dpdk.rst b/Documentation/intro/install/dpdk.rst
index dbf88ec43f..b603b6f0b0 100644
--- a/Documentation/intro/install/dpdk.rst
+++ b/Documentation/intro/install/dpdk.rst
@@ -42,7 +42,7 @@ Build requirements
 In addition to the requirements described in :doc:`general`, building Open
 vSwitch with DPDK will require the following:
 
-- DPDK 19.11
+- DPDK 19.11.8
 
 - A `DPDK supported NIC`_
 
@@ -71,9 +71,9 @@ Install DPDK
 #. Download the `DPDK sources`_, extract the file and set ``DPDK_DIR``::
 
        $ cd /usr/src/
-       $ wget https://fast.dpdk.org/rel/dpdk-19.11.tar.xz
-       $ tar xf dpdk-19.11.tar.xz
-       $ export DPDK_DIR=/usr/src/dpdk-19.11
+       $ wget https://fast.dpdk.org/rel/dpdk-19.11.8.tar.xz
+       $ tar xf dpdk-19.11.8.tar.xz
+       $ export DPDK_DIR=/usr/src/dpdk-stable-19.11.8
        $ cd $DPDK_DIR
 
 #. (Optional) Configure DPDK as a shared library
@@ -687,6 +687,15 @@ Limitations
   around is temporary and is expected to be removed once a method is provided
   by DPDK to query the upper bound MTU value for a given device.
 
+- Flow Control: When using i40e devices (Intel(R) 700 Series) it is recommended
+  to set Link State Change detection to interrupt mode. Otherwise it has been
+  observed that using the default polling mode, flow control changes may not be
+  applied, and flow control states will not be reflected correctly.
+  The issue is under investigation, this is a temporary work around.
+
+  For information about setting Link State Change detection, refer to
+  :ref:`lsc-detection`.
+
 Reporting Bugs
 --------------
 
diff --git a/Documentation/topics/dpdk/phy.rst b/Documentation/topics/dpdk/phy.rst
index 38e52c8deb..55a98e2b0e 100644
--- a/Documentation/topics/dpdk/phy.rst
+++ b/Documentation/topics/dpdk/phy.rst
@@ -385,6 +385,8 @@ Jumbo Frames
 DPDK physical ports can be configured to use Jumbo Frames. For more
 information, refer to :doc:`jumbo-frames`.
 
+.. _lsc-detection:
+
 Link State Change (LSC) detection configuration
 -----------------------------------------------
 
diff --git a/Documentation/topics/dpdk/pmd.rst b/Documentation/topics/dpdk/pmd.rst
index 6f1fdcbc6f..b017b84f6a 100644
--- a/Documentation/topics/dpdk/pmd.rst
+++ b/Documentation/topics/dpdk/pmd.rst
@@ -224,7 +224,9 @@ load then the actual reassignment will be performed.
 
     PMD Auto Load Balancing doesn't currently work if queues are assigned
     cross NUMA as actual processing load could get worse after assignment
-    as compared to what dry run predicts.
+    as compared to what dry run predicts. The only exception is when all
+    PMD threads are running on cores from a single NUMA node.  In this case
+    Auto Load Balancing is still possible.
 
 The minimum time between 2 consecutive PMD auto load balancing iterations can
 also be configured by::
diff --git a/Documentation/topics/dpdk/qos.rst b/Documentation/topics/dpdk/qos.rst
index 103495415a..a98ec672fc 100644
--- a/Documentation/topics/dpdk/qos.rst
+++ b/Documentation/topics/dpdk/qos.rst
@@ -69,22 +69,24 @@ to prioritize certain traffic over others at a port level.
 
 For example, the following configuration will limit the traffic rate at a
 port level to a maximum of 2000 packets a second (64 bytes IPv4 packets).
-100pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess
-Information Rate). High priority traffic is routed to queue 10, which marks
+1000pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess
+Information Rate). CIR and EIR are measured in bytes without Ethernet header.
+As a result, 1000pps means (64-byte - 14-byte) * 1000 = 50,000 in the
+configuration below. High priority traffic is routed to queue 10, which marks
 all traffic as CIR, i.e. Green. All low priority traffic, queue 20, is
 marked as EIR, i.e. Yellow::
 
     $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \
         --id=@myqos create qos type=trtcm-policer \
-        other-config:cir=52000 other-config:cbs=2048 \
-        other-config:eir=52000 other-config:ebs=2048  \
+        other-config:cir=50000 other-config:cbs=2048 \
+        other-config:eir=50000 other-config:ebs=2048  \
         queues:10=@dpdk1Q10 queues:20=@dpdk1Q20 -- \
          --id=@dpdk1Q10 create queue \
-          other-config:cir=41600000 other-config:cbs=2048 \
+          other-config:cir=100000 other-config:cbs=2048 \
           other-config:eir=0 other-config:ebs=0 -- \
          --id=@dpdk1Q20 create queue \
            other-config:cir=0 other-config:cbs=0 \
-           other-config:eir=41600000 other-config:ebs=2048 \
+           other-config:eir=50000 other-config:ebs=2048
 
 This configuration accomplishes that the high priority traffic has a
 guaranteed bandwidth egressing the ports at CIR (1000pps), but it can also
diff --git a/Documentation/topics/dpdk/vhost-user.rst b/Documentation/topics/dpdk/vhost-user.rst
index c6c6fd8bde..b10daa53e3 100644
--- a/Documentation/topics/dpdk/vhost-user.rst
+++ b/Documentation/topics/dpdk/vhost-user.rst
@@ -392,9 +392,9 @@ To begin, instantiate a guest as described in :ref:`dpdk-vhost-user` or
 DPDK sources to VM and build DPDK::
 
     $ cd /root/dpdk/
-    $ wget https://fast.dpdk.org/rel/dpdk-19.11.tar.xz
-    $ tar xf dpdk-19.11.tar.xz
-    $ export DPDK_DIR=/root/dpdk/dpdk-19.11
+    $ wget https://fast.dpdk.org/rel/dpdk-19.11.8.tar.xz
+    $ tar xf dpdk-19.11.8.tar.xz
+    $ export DPDK_DIR=/root/dpdk/dpdk-stable-19.11.8
     $ export DPDK_TARGET=x86_64-native-linuxapp-gcc
     $ export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
     $ cd $DPDK_DIR
diff --git a/Documentation/topics/testing.rst b/Documentation/topics/testing.rst
index 161e9d442e..fb1cbdf25e 100644
--- a/Documentation/topics/testing.rst
+++ b/Documentation/topics/testing.rst
@@ -405,45 +405,17 @@ You should invoke scan-view to view analysis results. The last line of output
 from ``clang-analyze`` will list the command (containing results directory)
 that you should invoke to view the results on a browser.
 
-Continuous Integration with Travis CI
--------------------------------------
+Continuous Integration with GitHub Actions
+------------------------------------------
 
-A .travis.yml file is provided to automatically build Open vSwitch with various
-build configurations and run the testsuite using Travis CI. Builds will be
-performed with gcc, sparse and clang with the -Werror compiler flag included,
-therefore the build will fail if a new warning has been introduced.
+A ``.github/workflows/*.yml`` files provided to automatically build
+Open vSwitch with various build configurations and run the testsuite using
+GitHub Actions. Builds will be performed with gcc, sparse and clang with the
+-Werror compiler flag included, therefore the build will fail if a new warning
+has been introduced.
 
 The CI build is triggered via git push (regardless of the specific branch) or
-pull request against any Open vSwitch GitHub repository that is linked to
-travis-ci.
-
-Instructions to setup travis-ci for your GitHub repository:
-
-1. Go to https://travis-ci.org/ and sign in using your GitHub ID.
-2. Go to the "Repositories" tab and enable the ovs repository. You may disable
-   builds for pushes or pull requests.
-3. In order to avoid forks sending build failures to the upstream mailing list,
-   the notification email recipient is encrypted. If you want to receive email
-   notification for build failures, replace the encrypted string:
-
-   1. Install the travis-ci CLI (Requires ruby >=2.0): gem install travis
-   2. In your Open vSwitch repository: travis encrypt mylist@mydomain.org
-   3. Add/replace the notifications section in .travis.yml and fill in the
-      secure string as returned by travis encrypt::
-
-          notifications:
-            email:
-              recipients:
-                - secure: "....."
-
-  .. note::
-    You may remove/omit the notifications section to fall back to default
-    notification behaviour which is to send an email directly to the author and
-    committer of the failing commit. Note that the email is only sent if the
-    author/committer have commit rights for the particular GitHub repository.
-
-4. Pushing a commit to the repository which breaks the build or the
-   testsuite will now trigger a email sent to mylist@mydomain.org
+pull request against any Open vSwitch GitHub repository.
 
 vsperf
 ------
diff --git a/Documentation/topics/userspace-tso.rst b/Documentation/topics/userspace-tso.rst
index 94eddc0b2f..f7b6b2639a 100644
--- a/Documentation/topics/userspace-tso.rst
+++ b/Documentation/topics/userspace-tso.rst
@@ -91,20 +91,24 @@ The current OvS userspace `TSO` implementation supports flat and VLAN networks
 only (i.e. no support for `TSO` over tunneled connection [VxLAN, GRE, IPinIP,
 etc.]).
 
+The NIC driver must support and advertise checksum offload for TCP and UDP.
+However, SCTP is not mandatory because very few drivers advertised support
+and it wasn't a widely used protocol at the moment this feature was introduced
+in Open vSwitch. Currently, if the NIC supports that, then the feature is
+enabled, otherwise TSO can still be enabled but SCTP packets sent to the NIC
+will be dropped.
+
 There is no software implementation of TSO, so all ports attached to the
 datapath must support TSO or packets using that feature will be dropped
 on ports without TSO support.  That also means guests using vhost-user
 in client mode will receive TSO packet regardless of TSO being enabled
 or disabled within the guest.
 
-When the NIC performing the segmentation is using the i40e DPDK PMD, a fix
-must be included in the DPDK build, otherwise TSO will not work. The fix can
-be found on `DPDK patchwork`__.
-
-__ https://patches.dpdk.org/patch/64136/
-
-This fix is expected to be included in the 19.11.1 release. When OVS migrates
-to this DPDK release, this limitation can be removed.
+All kernel devices that use the raw socket interface (veth, for example)
+require the kernel commit 9d2f67e43b73 ("net/packet: fix packet drop as of
+virtio gso") in order to work properly. This commit was merged in upstream
+kernel 4.19-rc7, so make sure your kernel is either newer or contains the
+backport.
 
 ~~~~~~~~~~~~~~~~~~
 Performance Tuning
diff --git a/Documentation/tutorials/ipsec.rst b/Documentation/tutorials/ipsec.rst
index b4c3235132..d7c56d5fcf 100644
--- a/Documentation/tutorials/ipsec.rst
+++ b/Documentation/tutorials/ipsec.rst
@@ -298,6 +298,7 @@ For example::
                                              Otherwise, error message will
                                              be provided
    Tunnel Type:    gre
+   Local IP:       %defaultroute
    Remote IP:      2.2.2.2
    SKB mark:       None
    Local cert:     None
diff --git a/Makefile.am b/Makefile.am
index b279303d18..b3b56cd50e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -46,7 +46,7 @@ AM_CPPFLAGS += -DNDEBUG
 AM_CFLAGS += -fomit-frame-pointer
 endif
 
-AM_CTAGSFLAGS = $(OVS_CTAGS_IDENTIFIERS_LIST)
+AM_CTAGSFLAGS = -I "$(OVS_CTAGS_IDENTIFIERS_LIST)"
 
 if WIN32
 psep=";"
@@ -76,12 +76,12 @@ EXTRA_DIST = \
 	MAINTAINERS.rst \
 	README.rst \
 	NOTICE \
+	.ci/linux-build.sh \
+	.ci/linux-prepare.sh \
+	.ci/osx-build.sh \
+	.ci/osx-prepare.sh \
 	.cirrus.yml \
-	.travis.yml \
-	.travis/linux-build.sh \
-	.travis/linux-prepare.sh \
-	.travis/osx-build.sh \
-	.travis/osx-prepare.sh \
+	.github/workflows/build-and-test.yml \
 	appveyor.yml \
 	boot.sh \
 	poc/builders/Vagrantfile \
diff --git a/NEWS b/NEWS
index dab94e924d..0ae1076ee1 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,56 @@
+v2.13.5 - xx xxx xxxx
+---------------------
+   - OVS now reports the datapath capability 'ct_zero_snat', which reflects
+     whether the SNAT with all-zero IP address is supported.
+     See ovs-vswitchd.conf.db(5) for details.
+
+v2.13.4 - 01 Jul 2021
+---------------------
+   - Bug fixes
+   - DPDK:
+     * OVS validated with DPDK 19.11.8. It is recommended to use this version
+       until further releases.
+   - ovs-ctl:
+     * New option '--no-record-hostname' to disable hostname configuration
+       in ovsdb on startup.
+     * New command 'record-hostname-if-not-set' to update hostname in ovsdb.
+
+v2.13.3 - 10 Feb 2021
+---------------------
+   - Bug fixes
+   - Security:
+     * Fixed packet parsing vulnerability CVE-2020-35498.
+
+v2.13.2 - 13 Jan 2021
+---------------------
+   - Bug fixes
+   - LLDP:
+     * Security fixes for CVE-2015-8011 and CVE-2020-27827.
+   - IPsec:
+     * Fixed support of strongswan 5.7+ in ovs-monitor-ipsec.
+     * Add option '--no-cleanup' to allow ovs-monitor-ipsec to stop without
+       tearing down IPsec tunnels.
+     * Add option '--no-restart-ike-daemon' to allow ovs-monitor-ipsec to start
+       without restarting ipsec daemon.
+   - OVSDB:
+     * New unixctl command 'ovsdb-server/memory-trim-on-compaction on|off'.
+       If turned on, ovsdb-server will try to reclaim all the unused memory
+       after every DB compaction back to OS.  Disabled by default.
+     * Maximum backlog on RAFT connections limited to 500 messages or 4GB.
+       Once threshold reached, connection is dropped (and re-established).
+       Use the 'cluster/set-backlog-threshold' command to change limits.
+     * Fixed SHA-1 hash computation for databases larger than 512 MB.
+   - DPDK:
+     * Fixed support of 'net_virtio' devices.
+
+v2.13.1 - 30 Jul 2020
+---------------------
+   - Bug fixes
+   - DPDK:
+     * OVS validated with DPDK 19.11.2, due to the inclusion of fixes for
+       CVE-2020-10722, CVE-2020-10723, CVE-2020-10724, CVE-2020-10725 and
+       CVE-2020-10726, this DPDK version is strongly recommended to be used.
+
 v2.13.0 - 14 Feb 2020
 ---------------------
    - OVN:
@@ -43,6 +96,9 @@ v2.13.0 - 14 Feb 2020
    - 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for
      partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and
      type filter supports new filters: "dpdk" and "partially-offloaded".
+   - Add new argument '--offload-stats' for command
+     'ovs-appctl bridge/dump-flows',
+     so it can display offloaded packets statistics.
 
 v2.12.0 - 03 Sep 2019
 ---------------------
@@ -117,9 +173,6 @@ v2.12.0 - 03 Sep 2019
      * Add support for conntrack zone-based timeout policy.
    - 'ovs-dpctl dump-flows' is no longer suitable for dumping offloaded flows.
      'ovs-appctl dpctl/dump-flows' should be used instead.
-   - Add new argument '--offload-stats' for command
-     'ovs-appctl bridge/dump-flows',
-     so it can display offloaded packets statistics.
    - Add L2 GRE tunnel over IPv6 support.
 
 v2.11.0 - 19 Feb 2019
diff --git a/README.rst b/README.rst
index e06ddf2671..8e64d74aee 100644
--- a/README.rst
+++ b/README.rst
@@ -6,8 +6,8 @@
 Open vSwitch
 ============
 
-.. image:: https://travis-ci.org/openvswitch/ovs.png
-    :target: https://travis-ci.org/openvswitch/ovs
+.. image:: https://github.com/openvswitch/ovs/workflows/Build%20and%20Test/badge.svg
+    :target: https://github.com/openvswitch/ovs/actions
 .. image:: https://ci.appveyor.com/api/projects/status/github/openvswitch/ovs?branch=master&svg=true&retina=true
     :target: https://ci.appveyor.com/project/blp/ovs/history
 .. image:: https://api.cirrus-ci.com/github/openvswitch/ovs.svg
diff --git a/acinclude.m4 b/acinclude.m4
index c1470ccc6b..914e27b932 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -192,10 +192,10 @@ dnl Configure Linux tc compat.
 AC_DEFUN([OVS_CHECK_LINUX_TC], [
   AC_COMPILE_IFELSE([
     AC_LANG_PROGRAM([#include <linux/pkt_cls.h>], [
-        int x = TCA_ACT_FLAGS;
+        int x = TCA_FLOWER_KEY_CT_FLAGS_REPLY;
     ])],
-    [AC_DEFINE([HAVE_TCA_ACT_FLAGS], [1],
-               [Define to 1 if TCA_ACT_FLAGS is available.])])
+    [AC_DEFINE([HAVE_TCA_FLOWER_KEY_CT_FLAGS_REPLY], [1],
+               [Define to 1 if TCA_FLOWER_KEY_CT_FLAGS_REPLY is available.])])
 
   AC_CHECK_MEMBERS([struct tcf_t.firstuse], [], [], [#include <linux/pkt_cls.h>])
 
@@ -250,6 +250,18 @@ AC_DEFUN([OVS_CHECK_LINUX_SCTP_CT], [
                [Define to 1 if SCTP_CONNTRACK_HEARTBEAT_SENT is available.])])
 ])
 
+dnl OVS_CHECK_LINUX_VIRTIO_TYPES
+dnl
+dnl Checks for kernels that need virtio_types definition.
+AC_DEFUN([OVS_CHECK_LINUX_VIRTIO_TYPES], [
+  AC_COMPILE_IFELSE([
+    AC_LANG_PROGRAM([#include <linux/virtio_types.h>], [
+        __virtio16 x =  0;
+    ])],
+    [AC_DEFINE([HAVE_VIRTIO_TYPES], [1],
+    [Define to 1 if __virtio16 is available.])])
+])
+
 dnl OVS_FIND_DEPENDENCY(FUNCTION, SEARCH_LIBS, NAME_TO_PRINT)
 dnl
 dnl Check for a function in a library list.
@@ -379,7 +391,6 @@ AC_DEFUN([OVS_CHECK_DPDK], [
       [AC_MSG_RESULT([no])])
 
     AC_CHECK_DECL([RTE_LIBRTE_MLX5_PMD], [dnl found
-      OVS_FIND_DEPENDENCY([mnl_attr_put], [mnl], [libmnl])
       AC_CHECK_DECL([RTE_IBVERBS_LINK_DLOPEN], [], [dnl not found
         OVS_FIND_DEPENDENCY([mlx5dv_create_wq], [mlx5], [libmlx5])
         OVS_FIND_DEPENDENCY([verbs_init_cq], [ibverbs], [libibverbs])
@@ -420,6 +431,16 @@ AC_DEFUN([OVS_CHECK_DPDK], [
     if test "$DPDK_AUTO_DISCOVER" = "false"; then
       OVS_LDFLAGS="$OVS_LDFLAGS -L$DPDK_LIB_DIR"
     fi
+    # Stripping out possible instruction set specific configuration that DPDK
+    # forces in pkg-config since this could override user-specified options.
+    # It's enough to have -mssse3 to build with DPDK headers.
+    DPDK_INCLUDE=$(echo "$DPDK_INCLUDE" | sed 's/-march=[[^ ]]*//g')
+    # Also stripping out '-mno-avx512f'.  Support for AVX512 will be disabled
+    # if OVS will detect that it's broken.  OVS could be built with a
+    # completely different toolchain that correctly supports AVX512, flags
+    # forced by DPDK only breaks our feature detection mechanism and leads to
+    # build failures: https://github.com/openvswitch/ovs-issues/issues/201
+    DPDK_INCLUDE=$(echo "$DPDK_INCLUDE" | sed 's/-mno-avx512f//g')
     OVS_CFLAGS="$OVS_CFLAGS $DPDK_INCLUDE"
     OVS_ENABLE_OPTION([-mssse3])
 
@@ -567,9 +588,14 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
   OVS_GREP_IFELSE([$KSRC/include/net/ip6_fib.h], [rt6_get_cookie],
                   [OVS_DEFINE([HAVE_RT6_GET_COOKIE])])
 
+  OVS_FIND_FIELD_IFELSE([$KSRC/include/net/addrconf.h], [ipv6_stub],
+                        [dst_entry])
   OVS_GREP_IFELSE([$KSRC/include/net/addrconf.h], [ipv6_dst_lookup.*net],
                   [OVS_DEFINE([HAVE_IPV6_DST_LOOKUP_NET])])
+  OVS_GREP_IFELSE([$KSRC/include/net/addrconf.h], [ipv6_dst_lookup_flow.*net],
+                  [OVS_DEFINE([HAVE_IPV6_DST_LOOKUP_FLOW_NET])])
   OVS_GREP_IFELSE([$KSRC/include/net/addrconf.h], [ipv6_stub])
+  OVS_GREP_IFELSE([$KSRC/include/net/addrconf.h], [ipv6_dst_lookup_flow])
 
   OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [ERR_CAST])
   OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [IS_ERR_OR_NULL])
@@ -765,6 +791,10 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
                   [prandom_u32[[\(]]],
                   [OVS_DEFINE([HAVE_PRANDOM_U32])])
   OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32_max])
+  OVS_GREP_IFELSE([$KSRC/include/linux/prandom.h],
+                  [prandom_u32[[\(]]],
+                  [OVS_DEFINE([HAVE_PRANDOM_U32])])
+  OVS_GREP_IFELSE([$KSRC/include/linux/prandom.h], [prandom_u32_max])
 
   OVS_GREP_IFELSE([$KSRC/include/net/rtnetlink.h], [get_link_net])
   OVS_GREP_IFELSE([$KSRC/include/net/rtnetlink.h], [name_assign_type])
@@ -918,8 +948,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
 
   OVS_GREP_IFELSE([$KSRC/include/net/sock.h], [sk_no_check_tx])
   OVS_GREP_IFELSE([$KSRC/include/linux/udp.h], [no_check6_tx])
-  OVS_GREP_IFELSE([$KSRC/include/linux/utsrelease.h], [el6],
-                  [OVS_DEFINE([HAVE_RHEL6_PER_CPU])])
   OVS_FIND_PARAM_IFELSE([$KSRC/include/net/protocol.h],
                         [udp_add_offload], [net],
                         [OVS_DEFINE([HAVE_UDP_ADD_OFFLOAD_TAKES_NET])])
@@ -1294,11 +1322,11 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
 
 dnl OVS_CTAGS_IDENTIFIERS
 dnl
-dnl ctags ignores symbols with extras identifiers. This builds a list of
-dnl specially handled identifiers to be ignored.
+dnl ctags ignores symbols with extras identifiers. This is a list of
+dnl specially handled identifiers to be ignored. [ctags(1) -I <list>].
 AC_DEFUN([OVS_CTAGS_IDENTIFIERS],
     AC_SUBST([OVS_CTAGS_IDENTIFIERS_LIST],
-           [`printf %s '-I "'; sed -n 's/^#define \(OVS_[A-Z_]\+\)(\.\.\.)$/\1+/p' ${srcdir}/include/openvswitch/compiler.h  | tr \\\n ' ' ; printf '"'`] ))
+           ["OVS_LOCKABLE OVS_NO_THREAD_SAFETY_ANALYSIS OVS_REQ_RDLOCK+ OVS_ACQ_RDLOCK+ OVS_REQ_WRLOCK+ OVS_ACQ_WRLOCK+ OVS_REQUIRES+ OVS_ACQUIRES+ OVS_TRY_WRLOCK+ OVS_TRY_RDLOCK+ OVS_TRY_LOCK+ OVS_GUARDED_BY+ OVS_EXCLUDED+ OVS_RELEASES+ OVS_ACQ_BEFORE+ OVS_ACQ_AFTER+"]))
 
 dnl OVS_PTHREAD_SET_NAME
 dnl
diff --git a/build-aux/dist-docs b/build-aux/dist-docs
index f6b88ca2d0..9429702db9 100755
--- a/build-aux/dist-docs
+++ b/build-aux/dist-docs
@@ -43,7 +43,7 @@ rm -rf $distdir
 mkdir $distdir
 
 # Install manpages.
-${MAKE-make} install-man mandir="$abs_distdir"/man
+${MAKE-make} install-man install-man-rst mandir="$abs_distdir"/man
 (cd $distdir && mv `find man -type f` . && rm -rf man)
 manpages=`cd $distdir && echo *`
 
diff --git a/configure.ac b/configure.ac
index 92b52f6712..0dc2a7dbca 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 AC_PREREQ(2.63)
-AC_INIT(openvswitch, 2.13.0, bugs@openvswitch.org)
+AC_INIT(openvswitch, 2.13.5, bugs@openvswitch.org)
 AC_CONFIG_SRCDIR([datapath/datapath.c])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_AUX_DIR([build-aux])
@@ -100,6 +100,7 @@ OVS_CHECK_IF_DL
 OVS_CHECK_STRTOK_R
 OVS_CHECK_LINUX_AF_XDP
 AC_CHECK_DECLS([sys_siglist], [], [], [[#include <signal.h>]])
+AC_CHECK_DECLS([malloc_trim], [], [], [[#include <malloc.h>]])
 AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec],
   [], [], [[#include <sys/stat.h>]])
 AC_CHECK_MEMBERS([struct ifreq.ifr_flagshigh], [], [], [[#include <net/if.h>]])
@@ -188,6 +189,7 @@ OVS_CHECK_LINUX
 OVS_CHECK_LINUX_NETLINK
 OVS_CHECK_LINUX_TC
 OVS_CHECK_LINUX_SCTP_CT
+OVS_CHECK_LINUX_VIRTIO_TYPES
 OVS_CHECK_DPDK
 OVS_CHECK_PRAGMA_MESSAGE
 AC_SUBST([OVS_CFLAGS])
diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index 5c9b5c3a0c..b49243006f 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -1112,9 +1112,9 @@ OvsPopFieldInPacketBuf(OvsForwardingContext *ovsFwdCtx,
      * should split the function and refactor. */
     if (!bufferData) {
         EthHdr *ethHdr = (EthHdr *)bufferStart;
-        /* If the frame is not VLAN make it a no op */
         if (ethHdr->Type != ETH_TYPE_802_1PQ_NBO) {
-            return NDIS_STATUS_SUCCESS;
+            OVS_LOG_ERROR("Invalid ethHdr type %u, nbl %p", ethHdr->Type, ovsFwdCtx->curNbl);
+            return NDIS_STATUS_INVALID_PACKET;
         }
     }
     RtlMoveMemory(bufferStart + shiftLength, bufferStart, shiftOffset);
@@ -1137,6 +1137,9 @@ OvsPopFieldInPacketBuf(OvsForwardingContext *ovsFwdCtx,
 static __inline NDIS_STATUS
 OvsPopVlanInPktBuf(OvsForwardingContext *ovsFwdCtx)
 {
+    NDIS_STATUS status;
+    OVS_PACKET_HDR_INFO* layers = &ovsFwdCtx->layers;
+
     /*
      * Declare a dummy vlanTag structure since we need to compute the size
      * of shiftLength. The NDIS one is a unionized structure.
@@ -1145,7 +1148,15 @@ OvsPopVlanInPktBuf(OvsForwardingContext *ovsFwdCtx)
     UINT32 shiftLength = sizeof(vlanTag.TagHeader);
     UINT32 shiftOffset = sizeof(DL_EUI48) + sizeof(DL_EUI48);
 
-    return OvsPopFieldInPacketBuf(ovsFwdCtx, shiftOffset, shiftLength, NULL);
+    status = OvsPopFieldInPacketBuf(ovsFwdCtx, shiftOffset, shiftLength,
+                                    NULL);
+
+    if (status == NDIS_STATUS_SUCCESS) {
+        layers->l3Offset -= (UINT16) shiftLength;
+        layers->l4Offset -= (UINT16) shiftLength;
+    }
+
+    return status;
 }
 
 
@@ -1259,6 +1270,7 @@ OvsActionMplsPush(OvsForwardingContext *ovsFwdCtx,
  */
 static __inline NDIS_STATUS
 OvsUpdateEthHeader(OvsForwardingContext *ovsFwdCtx,
+                   OvsFlowKey *key,
                    const struct ovs_key_ethernet *ethAttr)
 {
     PNET_BUFFER curNb;
@@ -1285,9 +1297,11 @@ OvsUpdateEthHeader(OvsForwardingContext *ovsFwdCtx,
     }
     ethHdr = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(curNb));
 
-    RtlCopyMemory(ethHdr->Destination, ethAttr->eth_dst,
-                   sizeof ethHdr->Destination);
-    RtlCopyMemory(ethHdr->Source, ethAttr->eth_src, sizeof ethHdr->Source);
+    RtlCopyMemory(ethHdr->Destination, ethAttr->eth_dst, ETH_ADDR_LENGTH);
+    RtlCopyMemory(ethHdr->Source, ethAttr->eth_src, ETH_ADDR_LENGTH);
+    /* Update l2 flow key */
+    RtlCopyMemory(key->l2.dlDst, ethAttr->eth_dst, ETH_ADDR_LENGTH);
+    RtlCopyMemory(key->l2.dlSrc, ethAttr->eth_src, ETH_ADDR_LENGTH);
 
     return NDIS_STATUS_SUCCESS;
 }
@@ -1376,6 +1390,7 @@ PUINT8 OvsGetHeaderBySize(OvsForwardingContext *ovsFwdCtx,
  */
 NDIS_STATUS
 OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx,
+                  OvsFlowKey *key,
                   const struct ovs_key_udp *udpAttr)
 {
     PUINT8 bufferStart;
@@ -1400,15 +1415,19 @@ OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx,
             udpHdr->check = ChecksumUpdate16(udpHdr->check, udpHdr->source,
                                              udpAttr->udp_src);
             udpHdr->source = udpAttr->udp_src;
+            key->ipKey.l4.tpSrc = udpAttr->udp_src;
         }
         if (udpHdr->dest != udpAttr->udp_dst) {
             udpHdr->check = ChecksumUpdate16(udpHdr->check, udpHdr->dest,
                                              udpAttr->udp_dst);
             udpHdr->dest = udpAttr->udp_dst;
+            key->ipKey.l4.tpDst = udpAttr->udp_dst;
         }
     } else {
         udpHdr->source = udpAttr->udp_src;
+        key->ipKey.l4.tpSrc = udpAttr->udp_src;
         udpHdr->dest = udpAttr->udp_dst;
+        key->ipKey.l4.tpDst = udpAttr->udp_dst;
     }
 
     return NDIS_STATUS_SUCCESS;
@@ -1423,6 +1442,7 @@ OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx,
  */
 NDIS_STATUS
 OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx,
+                  OvsFlowKey *key,
                   const struct ovs_key_tcp *tcpAttr)
 {
     PUINT8 bufferStart;
@@ -1447,11 +1467,13 @@ OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx,
         tcpHdr->check = ChecksumUpdate16(tcpHdr->check, tcpHdr->source,
                                          tcpAttr->tcp_src);
         tcpHdr->source = tcpAttr->tcp_src;
+        key->ipKey.l4.tpSrc = tcpAttr->tcp_src;
     }
     if (tcpHdr->dest != tcpAttr->tcp_dst) {
         tcpHdr->check = ChecksumUpdate16(tcpHdr->check, tcpHdr->dest,
                                          tcpAttr->tcp_dst);
         tcpHdr->dest = tcpAttr->tcp_dst;
+        key->ipKey.l4.tpDst = tcpAttr->tcp_dst;
     }
 
     return NDIS_STATUS_SUCCESS;
@@ -1539,9 +1561,21 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
         if (tcpHdr) {
             portField = &tcpHdr->dest;
             checkField = &tcpHdr->check;
+            l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.TcpChecksum :
+                        ((BOOLEAN)csumInfo.Receive.TcpChecksumSucceeded ||
+                         (BOOLEAN)csumInfo.Receive.TcpChecksumFailed);
         } else if (udpHdr) {
             portField = &udpHdr->dest;
             checkField = &udpHdr->check;
+            l4Offload = isTx ? (BOOLEAN)csumInfo.Transmit.UdpChecksum :
+                        ((BOOLEAN)csumInfo.Receive.UdpChecksumSucceeded ||
+                         (BOOLEAN)csumInfo.Receive.UdpChecksumFailed);
+        }
+
+       if (l4Offload) {
+            *checkField = IPPseudoChecksum(&ipHdr->saddr, &newAddr,
+                tcpHdr ? IPPROTO_TCP : IPPROTO_UDP,
+                ntohs(ipHdr->tot_len) - ipHdr->ihl * 4);
         }
     }
 
@@ -1579,6 +1613,7 @@ OvsUpdateAddressAndPort(OvsForwardingContext *ovsFwdCtx,
  */
 NDIS_STATUS
 OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,
+                    OvsFlowKey *key,
                     const struct ovs_key_ipv4 *ipAttr)
 {
     PUINT8 bufferStart;
@@ -1632,6 +1667,7 @@ OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,
                                             ipAttr->ipv4_src);
         }
         ipHdr->saddr = ipAttr->ipv4_src;
+        key->ipKey.nwSrc = ipAttr->ipv4_src;
     }
     if (ipHdr->daddr != ipAttr->ipv4_dst) {
         if (tcpHdr) {
@@ -1647,6 +1683,7 @@ OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,
                                             ipAttr->ipv4_dst);
         }
         ipHdr->daddr = ipAttr->ipv4_dst;
+        key->ipKey.nwDst = ipAttr->ipv4_dst;
     }
     if (ipHdr->protocol != ipAttr->ipv4_proto) {
         UINT16 oldProto = (ipHdr->protocol << 16) & 0xff00;
@@ -1661,6 +1698,7 @@ OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,
             ipHdr->check = ChecksumUpdate16(ipHdr->check, oldProto, newProto);
         }
         ipHdr->protocol = ipAttr->ipv4_proto;
+        key->ipKey.nwProto = ipAttr->ipv4_proto;
     }
     if (ipHdr->ttl != ipAttr->ipv4_ttl) {
         UINT16 oldTtl = (ipHdr->ttl) & 0xff;
@@ -1669,6 +1707,7 @@ OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,
             ipHdr->check = ChecksumUpdate16(ipHdr->check, oldTtl, newTtl);
         }
         ipHdr->ttl = ipAttr->ipv4_ttl;
+        key->ipKey.nwTtl = ipAttr->ipv4_ttl;
     }
 
     return NDIS_STATUS_SUCCESS;
@@ -1691,12 +1730,12 @@ OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx,
 
     switch (type) {
     case OVS_KEY_ATTR_ETHERNET:
-        status = OvsUpdateEthHeader(ovsFwdCtx,
+        status = OvsUpdateEthHeader(ovsFwdCtx, key,
             NlAttrGetUnspec(a, sizeof(struct ovs_key_ethernet)));
         break;
 
     case OVS_KEY_ATTR_IPV4:
-        status = OvsUpdateIPv4Header(ovsFwdCtx,
+        status = OvsUpdateIPv4Header(ovsFwdCtx, key,
             NlAttrGetUnspec(a, sizeof(struct ovs_key_ipv4)));
         break;
 
@@ -1709,16 +1748,17 @@ OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx,
         status = SUCCEEDED(convertStatus) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_FAILURE;
         ASSERT(status == NDIS_STATUS_SUCCESS);
         RtlCopyMemory(&ovsFwdCtx->tunKey, &tunKey, sizeof ovsFwdCtx->tunKey);
+        RtlCopyMemory(&key->tunKey, &tunKey, sizeof key->tunKey);
         break;
     }
 
     case OVS_KEY_ATTR_UDP:
-        status = OvsUpdateUdpPorts(ovsFwdCtx,
+        status = OvsUpdateUdpPorts(ovsFwdCtx, key,
             NlAttrGetUnspec(a, sizeof(struct ovs_key_udp)));
         break;
 
     case OVS_KEY_ATTR_TCP:
-        status = OvsUpdateTcpPorts(ovsFwdCtx,
+        status = OvsUpdateTcpPorts(ovsFwdCtx, key,
             NlAttrGetUnspec(a, sizeof(struct ovs_key_tcp)));
         break;
 
@@ -1763,9 +1803,11 @@ OvsExecuteRecirc(OvsForwardingContext *ovsFwdCtx,
     }
 
     if (newNbl) {
-        deferredAction = OvsAddDeferredActions(newNbl, key, NULL);
+        deferredAction = OvsAddDeferredActions(newNbl, key, &(ovsFwdCtx->layers),
+                                               NULL);
     } else {
-        deferredAction = OvsAddDeferredActions(ovsFwdCtx->curNbl, key, NULL);
+        deferredAction = OvsAddDeferredActions(ovsFwdCtx->curNbl, key,
+                                              &(ovsFwdCtx->layers), NULL);
     }
 
     if (deferredAction) {
@@ -1917,7 +1959,7 @@ OvsExecuteSampleAction(OvsForwardingContext *ovsFwdCtx,
         return STATUS_SUCCESS;
     }
 
-    if (!OvsAddDeferredActions(newNbl, key, a)) {
+    if (!OvsAddDeferredActions(newNbl, key, &(ovsFwdCtx->layers), a)) {
         OVS_LOG_INFO(
             "Deferred actions limit reached, dropping sample action.");
         OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE);
@@ -2053,6 +2095,7 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
                  */
                 status = OvsPopVlanInPktBuf(&ovsFwdCtx);
                 if (status != NDIS_STATUS_SUCCESS) {
+                    OVS_LOG_ERROR("OVS-pop vlan action failed status = %lu", status);
                     dropReason = L"OVS-pop vlan action failed";
                     goto dropit;
                 }
@@ -2302,7 +2345,7 @@ OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext,
 
     if (status == STATUS_SUCCESS) {
         status = OvsProcessDeferredActions(switchContext, completionList,
-                                           portNo, sendFlags, layers);
+                                           portNo, sendFlags, NULL);
     }
 
     return status;
diff --git a/datapath-windows/ovsext/Actions.h b/datapath-windows/ovsext/Actions.h
index fd050d5dd8..bc12e1166d 100644
--- a/datapath-windows/ovsext/Actions.h
+++ b/datapath-windows/ovsext/Actions.h
@@ -115,14 +115,17 @@ PUINT8 OvsGetHeaderBySize(OvsForwardingContext *ovsFwdCtx,
 
 NDIS_STATUS
 OvsUpdateUdpPorts(OvsForwardingContext *ovsFwdCtx,
+                  OvsFlowKey *key,
                   const struct ovs_key_udp *udpAttr);
 
 NDIS_STATUS
 OvsUpdateTcpPorts(OvsForwardingContext *ovsFwdCtx,
+                  OvsFlowKey *key,
                   const struct ovs_key_tcp *tcpAttr);
 
 NDIS_STATUS
 OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx,
+                    OvsFlowKey *key,
                     const struct ovs_key_ipv4 *ipAttr);
 
 NDIS_STATUS
diff --git a/datapath-windows/ovsext/Conntrack-other.c b/datapath-windows/ovsext/Conntrack-other.c
index 962cc8ac65..8580415a6b 100644
--- a/datapath-windows/ovsext/Conntrack-other.c
+++ b/datapath-windows/ovsext/Conntrack-other.c
@@ -49,17 +49,19 @@ OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
 {
     ASSERT(conn_);
     struct conn_other *conn = OvsCastConntrackEntryToOtherEntry(conn_);
+    enum CT_UPDATE_RES ret = CT_UPDATE_VALID;
 
     if (reply && conn->state != OTHERS_BIDIR) {
         conn->state = OTHERS_BIDIR;
     } else if (conn->state == OTHERS_FIRST) {
         conn->state = OTHERS_MULTIPLE;
+        ret = CT_UPDATE_VALID_NEW;
     }
 
     OvsConntrackUpdateExpiration(&conn->up, now,
                                  other_timeouts[conn->state]);
 
-    return CT_UPDATE_VALID;
+    return ret;
 }
 
 OVS_CT_ENTRY *
diff --git a/datapath-windows/ovsext/Conntrack-tcp.c b/datapath-windows/ovsext/Conntrack-tcp.c
index eda42ac823..a468c3e6bc 100644
--- a/datapath-windows/ovsext/Conntrack-tcp.c
+++ b/datapath-windows/ovsext/Conntrack-tcp.c
@@ -213,11 +213,17 @@ OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,
         return CT_UPDATE_INVALID;
     }
 
-    if (((tcp_flags & (TCP_SYN|TCP_ACK)) == TCP_SYN)
-            && dst->state >= CT_DPIF_TCPS_FIN_WAIT_2
+    if ((tcp_flags & (TCP_SYN|TCP_ACK)) == TCP_SYN) {
+        if (dst->state >= CT_DPIF_TCPS_FIN_WAIT_2
             && src->state >= CT_DPIF_TCPS_FIN_WAIT_2) {
-        src->state = dst->state = CT_DPIF_TCPS_CLOSED;
-        return CT_UPDATE_NEW;
+            src->state = dst->state = CT_DPIF_TCPS_CLOSED;
+            return CT_UPDATE_NEW;
+        } else if (src->state <= CT_DPIF_TCPS_SYN_SENT) {
+            src->state = CT_DPIF_TCPS_SYN_SENT;
+            OvsConntrackUpdateExpiration(&conn->up, now,
+                                         30 * CT_INTERVAL_SEC);
+            return CT_UPDATE_VALID_NEW;
+        }
     }
 
     if (src->wscale & CT_WSCALE_FLAG
diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index ba5611697a..55917c43ff 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -753,6 +753,9 @@ OvsProcessConntrackEntry(OvsForwardingContext *fwdCtx,
                 return NULL;
             }
             break;
+        case CT_UPDATE_VALID_NEW:
+            state |= OVS_CS_F_NEW;
+            break;
         }
     }
     if (entry) {
diff --git a/datapath-windows/ovsext/Conntrack.h b/datapath-windows/ovsext/Conntrack.h
index bc6580d708..b0932186af 100644
--- a/datapath-windows/ovsext/Conntrack.h
+++ b/datapath-windows/ovsext/Conntrack.h
@@ -56,6 +56,7 @@ typedef enum CT_UPDATE_RES {
     CT_UPDATE_INVALID,
     CT_UPDATE_VALID,
     CT_UPDATE_NEW,
+    CT_UPDATE_VALID_NEW,
 } CT_UPDATE_RES;
 
 /* Metadata mark for masked write to conntrack mark */
diff --git a/datapath-windows/ovsext/Recirc.c b/datapath-windows/ovsext/Recirc.c
index 2febf060dd..a32b75352b 100644
--- a/datapath-windows/ovsext/Recirc.c
+++ b/datapath-windows/ovsext/Recirc.c
@@ -277,16 +277,23 @@ OvsDeferredActionsQueuePush(POVS_DEFERRED_ACTION_QUEUE queue)
 POVS_DEFERRED_ACTION
 OvsAddDeferredActions(PNET_BUFFER_LIST nbl,
                       OvsFlowKey *key,
+                      POVS_PACKET_HDR_INFO layers,
                       const PNL_ATTR actions)
 {
     POVS_DEFERRED_ACTION_QUEUE queue = OvsDeferredActionsQueueGet();
     POVS_DEFERRED_ACTION deferredAction = NULL;
+    OVS_PACKET_HDR_INFO layersInit = { 0 };
 
     deferredAction = OvsDeferredActionsQueuePush(queue);
     if (deferredAction) {
         deferredAction->nbl = nbl;
         deferredAction->actions = actions;
         deferredAction->key = *key;
+        if (layers) {
+            deferredAction->layers = *layers;
+        } else {
+            deferredAction->layers = layersInit;
+        }
     }
 
     return deferredAction;
@@ -309,9 +316,16 @@ OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,
     NDIS_STATUS status = NDIS_STATUS_SUCCESS;
     POVS_DEFERRED_ACTION_QUEUE queue = OvsDeferredActionsQueueGet();
     POVS_DEFERRED_ACTION deferredAction = NULL;
+    POVS_PACKET_HDR_INFO layersDeferred = NULL;
 
     /* Process all deferred actions. */
     while ((deferredAction = OvsDeferredActionsQueuePop(queue)) != NULL) {
+        if (layers) {
+            layersDeferred = layers;
+         } else {
+            layersDeferred = &(deferredAction->layers);
+         }
+
         if (deferredAction->actions) {
             status = OvsDoExecuteActions(switchContext,
                                          completionList,
@@ -319,7 +333,7 @@ OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,
                                          portNo,
                                          sendFlags,
                                          &deferredAction->key, NULL,
-                                         layers, deferredAction->actions,
+                                         layersDeferred, deferredAction->actions,
                                          NlAttrGetSize(deferredAction->actions));
         } else {
             status = OvsDoRecirc(switchContext,
@@ -327,7 +341,7 @@ OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,
                                  deferredAction->nbl,
                                  &deferredAction->key,
                                  portNo,
-                                 layers);
+                                 layersDeferred);
         }
     }
 
diff --git a/datapath-windows/ovsext/Recirc.h b/datapath-windows/ovsext/Recirc.h
index 2b314ce274..74130a4600 100644
--- a/datapath-windows/ovsext/Recirc.h
+++ b/datapath-windows/ovsext/Recirc.h
@@ -18,6 +18,7 @@
 #define __RECIRC_H_ 1
 
 #include "Actions.h"
+#include "NetProto.h"
 
 #define DEFERRED_ACTION_QUEUE_SIZE          10
 #define DEFERRED_ACTION_EXEC_LEVEL           4
@@ -26,6 +27,7 @@ typedef struct _OVS_DEFERRED_ACTION {
     PNET_BUFFER_LIST    nbl;
     PNL_ATTR            actions;
     OvsFlowKey          key;
+    OVS_PACKET_HDR_INFO layers;
 } OVS_DEFERRED_ACTION, *POVS_DEFERRED_ACTION;
 
 /*
@@ -52,6 +54,7 @@ OvsProcessDeferredActions(POVS_SWITCH_CONTEXT switchContext,
 POVS_DEFERRED_ACTION
 OvsAddDeferredActions(PNET_BUFFER_LIST packet,
                       OvsFlowKey *key,
+                      POVS_PACKET_HDR_INFO layers,
                       const PNL_ATTR actions);
 
 /*
diff --git a/datapath-windows/ovsext/ovsext.vcxproj b/datapath-windows/ovsext/ovsext.vcxproj
index d50a126b43..18f884f41b 100644
--- a/datapath-windows/ovsext/ovsext.vcxproj
+++ b/datapath-windows/ovsext/ovsext.vcxproj
@@ -192,22 +192,39 @@
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Release|x64'">
     <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10 Debug|x64'">
     <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win10Analyze|x64'">
     <Inf2CatUseLocalTime>true</Inf2CatUseLocalTime>
     <CodeAnalysisRuleSet>..\misc\DriverRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <RunCodeAnalysis>true</RunCodeAnalysis>
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8.1Analyze|x64'">
     <RunCodeAnalysis>true</RunCodeAnalysis>
     <CodeAnalysisRuleSet>..\misc\DriverRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8Analyze|x64'">
     <RunCodeAnalysis>true</RunCodeAnalysis>
     <CodeAnalysisRuleSet>..\misc\DriverRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Debug|x64'">
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8.1 Debug|x64'">
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Win8.1 Release|x64'">
+    <ExternalIncludePath>$(CRT_IncludePath);$(KM_IncludePath);</ExternalIncludePath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Win8 Release|x64'">
     <ClCompile>
diff --git a/datapath/conntrack.c b/datapath/conntrack.c
index 838cf63c90..67e0628703 100644
--- a/datapath/conntrack.c
+++ b/datapath/conntrack.c
@@ -1972,7 +1972,8 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
 		struct hlist_head *head = &info->limits[i];
 		struct ovs_ct_limit *ct_limit;
 
-		hlist_for_each_entry_rcu(ct_limit, head, hlist_node)
+		hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
+					 lockdep_ovsl_is_held())
 			kfree_rcu(ct_limit, rcu);
 	}
 	kfree(ovs_net->ct_limit_info->limits);
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 853bfb5af1..3dbdb5b59c 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -2437,8 +2437,10 @@ static void __net_exit ovs_exit_net(struct net *dnet)
 
 	ovs_netns_frags6_exit(dnet);
 	ovs_netns_frags_exit(dnet);
-	ovs_ct_exit(dnet);
 	ovs_lock();
+
+	ovs_ct_exit(dnet);
+
 	list_for_each_entry_safe(dp, dp_next, &ovs_net->dps, list_node)
 		__dp_destroy(dp);
 
diff --git a/datapath/linux/compat/geneve.c b/datapath/linux/compat/geneve.c
index c044b14896..bf995aa83a 100644
--- a/datapath/linux/compat/geneve.c
+++ b/datapath/linux/compat/geneve.c
@@ -962,14 +962,26 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb,
 			return dst;
 	}
 
-#ifdef HAVE_IPV6_DST_LOOKUP_NET
-	if (ipv6_stub->ipv6_dst_lookup(geneve->net, gs6->sock->sk, &dst, fl6)) {
+#if defined(HAVE_IPV6_STUB_WITH_DST_ENTRY) && defined(HAVE_IPV6_DST_LOOKUP_FLOW)
+#ifdef HAVE_IPV6_DST_LOOKUP_FLOW_NET
+	dst = ipv6_stub->ipv6_dst_lookup_flow(geneve->net, gs6->sock->sk, fl6,
+					      NULL);
 #else
-#ifdef HAVE_IPV6_STUB
+	dst = ipv6_stub->ipv6_dst_lookup_flow(gs6->sock->sk, fl6,
+					      NULL);
+#endif
+	if (IS_ERR(dst)) {
+#elif defined(HAVE_IPV6_DST_LOOKUP_FLOW_NET)
+	if (ipv6_stub->ipv6_dst_lookup_flow(geneve->net, gs6->sock->sk, &dst,
+                                            fl6)) {
+#elif defined(HAVE_IPV6_DST_LOOKUP_FLOW)
+	if (ipv6_stub->ipv6_dst_lookup_flow(gs6->sock->sk, &dst, fl6)) {
+#elif defined(HAVE_IPV6_DST_LOOKUP_NET)
+	if (ipv6_stub->ipv6_dst_lookup(geneve->net, gs6->sock->sk, &dst, fl6)) {
+#elif defined(HAVE_IPV6_STUB)
 	if (ipv6_stub->ipv6_dst_lookup(gs6->sock->sk, &dst, fl6)) {
 #else
 	if (ip6_dst_lookup(gs6->sock->sk, &dst, fl6)) {
-#endif
 #endif
 		netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr);
 		return ERR_PTR(-ENETUNREACH);
diff --git a/datapath/linux/compat/include/linux/percpu.h b/datapath/linux/compat/include/linux/percpu.h
index 7c346aa31a..a039142e22 100644
--- a/datapath/linux/compat/include/linux/percpu.h
+++ b/datapath/linux/compat/include/linux/percpu.h
@@ -7,12 +7,6 @@
 #define this_cpu_ptr(ptr) per_cpu_ptr(ptr, smp_processor_id())
 #endif
 
-#ifdef HAVE_RHEL6_PER_CPU
-#undef this_cpu_read
-#undef this_cpu_inc
-#undef this_cpu_dec
-#endif
-
 #if !defined this_cpu_read
 #define this_cpu_read(ptr) percpu_read(ptr)
 #endif
diff --git a/datapath/linux/compat/include/linux/rculist.h b/datapath/linux/compat/include/linux/rculist.h
index 8df8ad8a27..40fd5e1710 100644
--- a/datapath/linux/compat/include/linux/rculist.h
+++ b/datapath/linux/compat/include/linux/rculist.h
@@ -9,9 +9,28 @@
 #define hlist_pprev_rcu(node)   (*((struct hlist_node __rcu **)((node)->pprev)))
 #endif
 
+/*
+ * Check during list traversal that we are within an RCU reader
+ */
+
+#define check_arg_count_one(dummy)
+
+#ifdef CONFIG_PROVE_RCU_LIST
+#define __list_check_rcu(dummy, cond, extra...)				\
+	({								\
+	check_arg_count_one(extra);					\
+	RCU_LOCKDEP_WARN(!cond && !rcu_read_lock_any_held(),		\
+			 "RCU-list traversed in non-reader section!");	\
+	 })
+#else
+#define __list_check_rcu(dummy, cond, extra...)				\
+	({ check_arg_count_one(extra); })
+#endif
+
 #undef hlist_for_each_entry_rcu
-#define hlist_for_each_entry_rcu(pos, head, member)			\
-	for (pos = hlist_entry_safe (rcu_dereference_raw(hlist_first_rcu(head)),\
+#define hlist_for_each_entry_rcu(pos, head, member, cond...)		\
+	for (__list_check_rcu(dummy, ## cond, 0),			\
+	     pos = hlist_entry_safe(rcu_dereference_raw(hlist_first_rcu(head)),\
 			typeof(*(pos)), member);			\
 		pos;							\
 		pos = hlist_entry_safe(rcu_dereference_raw(hlist_next_rcu(\
diff --git a/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h
index 63972891bf..f276898b20 100644
--- a/datapath/linux/compat/include/linux/skbuff.h
+++ b/datapath/linux/compat/include/linux/skbuff.h
@@ -278,7 +278,7 @@ static inline void skb_clear_hash(struct sk_buff *skb)
 #ifdef HAVE_RXHASH
 	skb->rxhash = 0;
 #endif
-#if defined(HAVE_L4_RXHASH) && !defined(HAVE_RHEL_OVS_HOOK)
+#if defined(HAVE_L4_RXHASH)
 	skb->l4_rxhash = 0;
 #endif
 }
diff --git a/datapath/linux/compat/nf_conntrack_reasm.c b/datapath/linux/compat/nf_conntrack_reasm.c
index ced9fba98b..77b4b25485 100644
--- a/datapath/linux/compat/nf_conntrack_reasm.c
+++ b/datapath/linux/compat/nf_conntrack_reasm.c
@@ -57,10 +57,13 @@
 #include <net/netns/generic.h>
 #include "datapath.h"
 
-#ifdef OVS_NF_DEFRAG6_BACKPORT
+#if defined(HAVE_INET_FRAGS_WITH_FRAGS_WORK) || !defined(HAVE_INET_FRAGS_RND)
 
 static const char nf_frags_cache_name[] = "ovs-frag6";
 
+#endif
+
+#ifdef OVS_NF_DEFRAG6_BACKPORT
 struct nf_ct_frag6_skb_cb
 {
 	struct inet6_skb_parm	h;
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
index 23118e8b63..05ccfb9288 100644
--- a/datapath/linux/compat/vxlan.c
+++ b/datapath/linux/compat/vxlan.c
@@ -967,7 +967,10 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
 	bool use_cache = (dst_cache && ip_tunnel_dst_cache_usable(skb, info));
 	struct dst_entry *ndst;
 	struct flowi6 fl6;
+#if !defined(HAVE_IPV6_STUB_WITH_DST_ENTRY) || \
+    !defined(HAVE_IPV6_DST_LOOKUP_FLOW)
 	int err;
+#endif
 
 	if (!sock6)
 		return ERR_PTR(-EIO);
@@ -990,20 +993,35 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
 	fl6.fl6_dport = dport;
 	fl6.fl6_sport = sport;
 
-#ifdef HAVE_IPV6_DST_LOOKUP_NET
-	err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
-					 sock6->sock->sk,
-					 &ndst, &fl6);
+#if defined(HAVE_IPV6_STUB_WITH_DST_ENTRY) && defined(HAVE_IPV6_DST_LOOKUP_FLOW)
+#ifdef HAVE_IPV6_DST_LOOKUP_FLOW_NET
+	ndst = ipv6_stub->ipv6_dst_lookup_flow(vxlan->net, sock6->sock->sk,
+					       &fl6, NULL);
 #else
-#ifdef HAVE_IPV6_STUB
+	ndst = ipv6_stub->ipv6_dst_lookup_flow(sock6->sock->sk, &fl6, NULL);
+#endif
+	if (unlikely(IS_ERR(ndst))) {
+#elif defined(HAVE_IPV6_DST_LOOKUP_FLOW_NET)
+	err = ipv6_stub->ipv6_dst_lookup_flow(vxlan->net, sock6->sock->sk,
+					      &ndst, &fl6);
+#elif defined(HAVE_IPV6_DST_LOOKUP_FLOW)
+	err = ipv6_stub->ipv6_dst_lookup_flow(sock6->sock->sk, &ndst, &fl6);
+#elif defined(HAVE_IPV6_DST_LOOKUP_NET)
+	err = ipv6_stub->ipv6_dst_lookup(vxlan->net, sock6->sock->sk,
+					 &ndst, &fl6);
+#elif defined(HAVE_IPV6_STUB)
 	err = ipv6_stub->ipv6_dst_lookup(vxlan->vn6_sock->sock->sk,
 					 &ndst, &fl6);
 #else
 	err = ip6_dst_lookup(vxlan->vn6_sock->sock->sk, &ndst, &fl6);
 #endif
-#endif
+#if defined(HAVE_IPV6_STUB_WITH_DST_ENTRY) && defined(HAVE_IPV6_DST_LOOKUP_FLOW)
+		return ERR_PTR(-ENETUNREACH);
+	}
+#else
 	if (err < 0)
 		return ERR_PTR(err);
+#endif
 
 	*saddr = fl6.saddr;
 	if (use_cache)
diff --git a/debian/changelog b/debian/changelog
index 8e075bc98b..05025442a6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,33 @@
+openvswitch (2.13.5-1) unstable; urgency=low
+   [ Open vSwitch team ]
+   * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org>  Thu, 01 Jul 2021 20:17:41 +0200
+
+openvswitch (2.13.4-1) unstable; urgency=low
+   [ Open vSwitch team ]
+   * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org>  Thu, 01 Jul 2021 20:17:41 +0200
+
+openvswitch (2.13.3-1) unstable; urgency=low
+   [ Open vSwitch team ]
+   * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org>  Wed, 10 Feb 2021 16:07:28 +0100
+
+openvswitch (2.13.2-1) unstable; urgency=low
+   [ Open vSwitch team ]
+   * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org>  Wed, 13 Jan 2021 11:26:36 -0500
+
+openvswitch (2.13.1-1) unstable; urgency=low
+   [ Open vSwitch team]
+   * New upstream version
+
+ -- Open vSwitch team <dev@openvswitch.org>  Thu, 30 Jul 2020 00:25:23 +0200
+
 openvswitch (2.13.0-1) unstable; urgency=low
    [ Open vSwitch team]
    * New upstream version
diff --git a/debian/control b/debian/control
index a50e97249f..6420b9d3e2 100644
--- a/debian/control
+++ b/debian/control
@@ -14,8 +14,9 @@ Build-Depends: graphviz,
                openssl,
                procps,
                python3-all,
-               python3-twisted-conch,
-               python3-zopeinterface,
+               python3-sphinx,
+               python3-twisted,
+               python3-zope.interface,
                libunbound-dev,
                libunwind-dev
 Standards-Version: 3.9.3
@@ -187,7 +188,7 @@ Description: Python bindings for Open vSwitch
 Package: openvswitch-test
 Architecture: all
 Depends: python3,
-         python3-twisted-web,
+         python3-twisted,
          ${misc:Depends},
          ${python3:Depends}
 Description: Open vSwitch test package
diff --git a/debian/openvswitch-common.manpages b/debian/openvswitch-common.manpages
index 9ac6a1dd6d..95004122cc 100644
--- a/debian/openvswitch-common.manpages
+++ b/debian/openvswitch-common.manpages
@@ -1,7 +1,7 @@
 ovsdb/ovsdb-client.1
 ovsdb/ovsdb-tool.1
 utilities/bugtool/ovs-bugtool.8
-utilities/ovs-appctl.8
+debian/tmp/usr/share/man/man8/ovs-appctl.8
 utilities/ovs-ofctl.8
-utilities/ovs-parse-backtrace.8
-utilities/ovs-pki.8
+debian/tmp/usr/share/man/man8/ovs-parse-backtrace.8
+debian/tmp/usr/share/man/man8/ovs-pki.8
diff --git a/debian/openvswitch-switch.manpages b/debian/openvswitch-switch.manpages
index 1161cfda77..7fd7bc55da 100644
--- a/debian/openvswitch-switch.manpages
+++ b/debian/openvswitch-switch.manpages
@@ -1,12 +1,12 @@
 ovsdb/ovsdb-server.1
 ovsdb/ovsdb-server.5
-utilities/ovs-ctl.8
+debian/tmp/usr/share/man/man8/ovs-ctl.8
 utilities/ovs-dpctl-top.8
 utilities/ovs-dpctl.8
 utilities/ovs-kmod-ctl.8
 utilities/ovs-pcap.1
-utilities/ovs-tcpdump.8
-utilities/ovs-tcpundump.1
+debian/tmp/usr/share/man/man8/ovs-tcpdump.8
+debian/tmp/usr/share/man/man1/ovs-tcpundump.1
 utilities/ovs-vsctl.8
 vswitchd/ovs-vswitchd.8
 vswitchd/ovs-vswitchd.conf.db.5
diff --git a/debian/openvswitch-test.manpages b/debian/openvswitch-test.manpages
index 3f71858691..eb3a561d01 100644
--- a/debian/openvswitch-test.manpages
+++ b/debian/openvswitch-test.manpages
@@ -1 +1 @@
-utilities/ovs-l3ping.8
+debian/tmp/usr/share/man/man8/ovs-l3ping.8
diff --git a/dpdk/.ci/linux-setup.sh b/dpdk/.ci/linux-setup.sh
index dfb9d4a206..38bb88e15c 100755
--- a/dpdk/.ci/linux-setup.sh
+++ b/dpdk/.ci/linux-setup.sh
@@ -1,7 +1,7 @@
 #!/bin/sh -xe
 
 # need to install as 'root' since some of the unit tests won't run without it
-sudo python3 -m pip install --upgrade meson
+sudo python3 -m pip install --upgrade 'meson==0.47.1'
 
 # setup hugepages
 cat /proc/meminfo
diff --git a/dpdk/.travis.yml b/dpdk/.travis.yml
index 8f90d06f28..77ac26dd85 100644
--- a/dpdk/.travis.yml
+++ b/dpdk/.travis.yml
@@ -15,19 +15,19 @@ addons:
     packages: &required_packages
       - [libnuma-dev, linux-headers-$(uname -r), python3-setuptools, python3-wheel, python3-pip, ninja-build]
 
-aarch64_packages: &aarch64_packages
+_aarch64_packages: &aarch64_packages
   - *required_packages
   - [gcc-aarch64-linux-gnu, libc6-dev-arm64-cross, pkg-config-aarch64-linux-gnu]
 
-extra_packages: &extra_packages
+_extra_packages: &extra_packages
   - *required_packages
-  - [libbsd-dev, libpcap-dev, libcrypto++-dev, libjansson4]
+  - [libbsd-dev, libpcap-dev, libcrypto++-dev, libjansson-dev]
 
-build_32b_packages: &build_32b_packages
+_build_32b_packages: &build_32b_packages
   - *required_packages
   - [gcc-multilib]
 
-doc_packages: &doc_packages
+_doc_packages: &doc_packages
   - [doxygen, graphviz, python3-sphinx]
 
 before_install: ./.ci/${TRAVIS_OS_NAME}-setup.sh
@@ -39,7 +39,7 @@ env:
   - DEF_LIB="shared" OPTS="-Denable_kmods=false"
   - DEF_LIB="shared" RUN_TESTS=1
 
-matrix:
+jobs:
   include:
   - env: DEF_LIB="static" BUILD_32BIT=1
     compiler: gcc
diff --git a/dpdk/MAINTAINERS b/dpdk/MAINTAINERS
index 4395d8df14..952ded7b00 100644
--- a/dpdk/MAINTAINERS
+++ b/dpdk/MAINTAINERS
@@ -46,7 +46,7 @@ M: Jerin Jacob <jerinj@marvell.com>
 T: git://dpdk.org/next/dpdk-next-net-mrvl
 
 Next-net-mlx Tree
-M: Raslan Darawsheh <rasland@mellanox.com>
+M: Raslan Darawsheh <rasland@nvidia.com>
 T: git://dpdk.org/next/dpdk-next-net-mlx
 
 Next-virtio Tree
@@ -128,8 +128,11 @@ F: meson.build
 F: lib/librte_eal/freebsd/BSDmakefile.meson
 F: meson_options.txt
 F: config/rte_config.h
+F: buildtools/call-sphinx-build.py
 F: buildtools/gen-pmdinfo-cfile.sh
 F: buildtools/map_to_def.py
+F: buildtools/list-dir-globs.py
+F: buildtools/pkg-config/
 F: buildtools/symlink-drivers-solibs.sh
 
 Public CI
@@ -370,7 +373,7 @@ F: devtools/test-null.sh
 F: doc/guides/prog_guide/switch_representation.rst
 
 Flow API
-M: Adrien Mazarguil <adrien.mazarguil@6wind.com>
+M: Ori Kam <orika@nvidia.com>
 T: git://dpdk.org/next/dpdk-next-net
 F: app/test-pmd/cmdline_flow.c
 F: doc/guides/prog_guide/rte_flow.rst
@@ -456,8 +459,8 @@ F: lib/librte_eventdev/*crypto_adapter*
 F: app/test/test_event_crypto_adapter.c
 F: doc/guides/prog_guide/event_crypto_adapter.rst
 
-Raw device API - EXPERIMENTAL
-M: Shreyansh Jain <shreyansh.jain@nxp.com>
+Raw device API
+M: Nipun Gupta <nipun.gupta@nxp.com>
 M: Hemant Agrawal <hemant.agrawal@nxp.com>
 F: lib/librte_rawdev/
 F: drivers/raw/skeleton/
@@ -728,17 +731,17 @@ F: doc/guides/nics/features/octeontx2*.ini
 F: doc/guides/nics/octeontx2.rst
 
 Mellanox mlx4
-M: Matan Azrad <matan@mellanox.com>
-M: Shahaf Shuler <shahafs@mellanox.com>
+M: Matan Azrad <matan@nvidia.com>
+M: Shahaf Shuler <shahafs@nvidia.com>
 T: git://dpdk.org/next/dpdk-next-net-mlx
 F: drivers/net/mlx4/
 F: doc/guides/nics/mlx4.rst
 F: doc/guides/nics/features/mlx4.ini
 
 Mellanox mlx5
-M: Matan Azrad <matan@mellanox.com>
-M: Shahaf Shuler <shahafs@mellanox.com>
-M: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
+M: Matan Azrad <matan@nvidia.com>
+M: Shahaf Shuler <shahafs@nvidia.com>
+M: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
 T: git://dpdk.org/next/dpdk-next-net-mlx
 F: drivers/net/mlx5/
 F: buildtools/options-ibverbs-static.sh
@@ -746,7 +749,7 @@ F: doc/guides/nics/mlx5.rst
 F: doc/guides/nics/features/mlx5.ini
 
 Microsoft vdev_netvsc - EXPERIMENTAL
-M: Matan Azrad <matan@mellanox.com>
+M: Matan Azrad <matan@nvidia.com>
 F: drivers/net/vdev_netvsc/
 F: doc/guides/nics/vdev_netvsc.rst
 F: doc/guides/nics/features/vdev_netvsc.ini
@@ -910,7 +913,7 @@ F: drivers/net/null/
 F: doc/guides/nics/features/null.ini
 
 Fail-safe PMD
-M: Gaetan Rivet <gaetan.rivet@6wind.com>
+M: Gaetan Rivet <grive@u256.net>
 F: drivers/net/failsafe/
 F: doc/guides/nics/fail_safe.rst
 F: doc/guides/nics/features/failsafe.ini
@@ -1373,7 +1376,7 @@ F: app/test/test_rcu*
 F: doc/guides/prog_guide/rcu_lib.rst
 
 PCI
-M: Gaetan Rivet <gaetan.rivet@6wind.com>
+M: Gaetan Rivet <grive@u256.net>
 F: lib/librte_pci/
 
 Power management
@@ -1434,6 +1437,7 @@ Unit tests framework
 F: app/test/Makefile
 F: app/test/autotest*
 F: app/test/commands.c
+F: app/test/get-coremask.sh
 F: app/test/packet_burst_generator.c
 F: app/test/packet_burst_generator.h
 F: app/test/process.h
@@ -1490,7 +1494,7 @@ M: Marko Kovacevic <marko.kovacevic@intel.com>
 F: examples/fips_validation/
 F: doc/guides/sample_app_ug/fips_validation.rst
 
-M: Ori Kam <orika@mellanox.com>
+M: Ori Kam <orika@nvidia.com>
 F: examples/flow_filtering/
 F: doc/guides/sample_app_ug/flow_filtering.rst
 
diff --git a/dpdk/VERSION b/dpdk/VERSION
index 22131b00aa..8bda73742f 100644
--- a/dpdk/VERSION
+++ b/dpdk/VERSION
@@ -1 +1 @@
-19.11.0
+19.11.7
diff --git a/dpdk/app/meson.build b/dpdk/app/meson.build
index 71109cc422..c7f689eb79 100644
--- a/dpdk/app/meson.build
+++ b/dpdk/app/meson.build
@@ -22,6 +22,10 @@ apps = [
 lib_execinfo = cc.find_library('execinfo', required: false)
 
 default_cflags = machine_args
+default_ldflags = []
+if get_option('default_library') == 'static' and not is_windows
+	default_ldflags += ['-Wl,--export-dynamic']
+endif
 
 foreach app:apps
 	build = true
@@ -30,6 +34,7 @@ foreach app:apps
 	sources = []
 	includes = []
 	cflags = default_cflags
+	ldflags = default_ldflags
 	objs = [] # other object files to link against, used e.g. for
 	          # instruction-set optimized versions of code
 
@@ -60,8 +65,10 @@ foreach app:apps
 		executable('dpdk-' + name,
 				sources,
 				c_args: cflags,
+				link_args: ldflags,
 				link_whole: link_libs,
 				dependencies: dep_objs,
+				include_directories: includes,
 				install_rpath: join_paths(get_option('prefix'),
 						 driver_install_path),
 				install: true)
diff --git a/dpdk/app/pdump/main.c b/dpdk/app/pdump/main.c
index 903d02f482..c38c53719e 100644
--- a/dpdk/app/pdump/main.c
+++ b/dpdk/app/pdump/main.c
@@ -151,7 +151,7 @@ static uint8_t multiple_core_capture;
 static void
 pdump_usage(const char *prgname)
 {
-	printf("usage: %s [EAL options]"
+	printf("usage: %s [EAL options] --"
 			" --["CMD_LINE_OPT_MULTI"]\n"
 			" --"CMD_LINE_OPT_PDUMP" "
 			"'(port=<port id> | device_id=<pci id or vdev name>),"
@@ -595,7 +595,7 @@ configure_vdev(uint16_t port_id)
 	if (ret != 0)
 		rte_exit(EXIT_FAILURE, "dev config failed\n");
 
-	 for (q = 0; q < txRings; q++) {
+	for (q = 0; q < txRings; q++) {
 		ret = rte_eth_tx_queue_setup(port_id, q, TX_DESC_PER_QUEUE,
 				rte_eth_dev_socket_id(port_id), NULL);
 		if (ret < 0)
diff --git a/dpdk/app/proc-info/main.c b/dpdk/app/proc-info/main.c
index abeca4aab4..f6d19cdac2 100644
--- a/dpdk/app/proc-info/main.c
+++ b/dpdk/app/proc-info/main.c
@@ -310,14 +310,13 @@ proc_info_parse_args(int argc, char **argv)
 			} else if (!strncmp(long_option[option_index].name,
 					"xstats-ids",
 					MAX_LONG_OPT_SZ))	{
-				nb_xstats_ids = parse_xstats_ids(optarg,
+				int ret = parse_xstats_ids(optarg,
 						xstats_ids, MAX_NB_XSTATS_IDS);
-
-				if (nb_xstats_ids <= 0) {
+				if (ret <= 0) {
 					printf("xstats-id list parse error.\n");
 					return -1;
 				}
-
+				nb_xstats_ids = ret;
 			}
 			break;
 		default:
@@ -429,11 +428,9 @@ static void collectd_resolve_cnt_type(char *cnt_type, size_t cnt_type_len,
 	} else if ((type_end != NULL) &&
 		   (strncmp(cnt_name, "flow_", strlen("flow_"))) == 0) {
 		if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
-			strlcpy(cnt_type, "operations", cnt_type_len);
+			strlcpy(cnt_type, "filter_result", cnt_type_len);
 		else if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
 			strlcpy(cnt_type, "errors", cnt_type_len);
-		else if (strncmp(type_end, "_filters", strlen("_filters")) == 0)
-			strlcpy(cnt_type, "filter_result", cnt_type_len);
 	} else if ((type_end != NULL) &&
 		   (strncmp(cnt_name, "mac_", strlen("mac_"))) == 0) {
 		if (strncmp(type_end, "_errors", strlen("_errors")) == 0)
@@ -1110,7 +1107,6 @@ show_crypto(void)
 
 		display_crypto_feature_info(dev_info.feature_flags);
 
-		memset(&stats, 0, sizeof(0));
 		if (rte_cryptodev_stats_get(i, &stats) == 0) {
 			printf("\t  -- stats\n");
 			printf("\t\t  + enqueue count (%"PRIu64")"
diff --git a/dpdk/app/test-acl/main.c b/dpdk/app/test-acl/main.c
index 57f23942eb..08f06c1fa3 100644
--- a/dpdk/app/test-acl/main.c
+++ b/dpdk/app/test-acl/main.c
@@ -12,7 +12,7 @@
 #include <rte_lcore.h>
 #include <rte_ip.h>
 
-#define	PRINT_USAGE_START	"%s [EAL options]\n"
+#define	PRINT_USAGE_START	"%s [EAL options] --\n"
 
 #define	RTE_LOGTYPE_TESTACL	RTE_LOGTYPE_USER1
 
diff --git a/dpdk/app/test-bbdev/ldpc_enc_default.data b/dpdk/app/test-bbdev/ldpc_enc_default.data
index 371cbc692d..52d51ae330 120000
--- a/dpdk/app/test-bbdev/ldpc_enc_default.data
+++ b/dpdk/app/test-bbdev/ldpc_enc_default.data
@@ -1 +1 @@
-test_vectors/turbo_dec_c1_k6144_r0_e10376_crc24b_sbd_negllr_high_snr.data
\ No newline at end of file
+test_vectors/ldpc_enc_v2342.data
\ No newline at end of file
diff --git a/dpdk/app/test-crypto-perf/cperf_options_parsing.c b/dpdk/app/test-crypto-perf/cperf_options_parsing.c
index f43c5bede7..49b469781c 100644
--- a/dpdk/app/test-crypto-perf/cperf_options_parsing.c
+++ b/dpdk/app/test-crypto-perf/cperf_options_parsing.c
@@ -23,7 +23,7 @@ usage(char *progname)
 {
 	printf("%s [EAL options] --\n"
 		" --silent: disable options dump\n"
-		" --ptest throughput / latency / verify / pmd-cycleount :"
+		" --ptest throughput / latency / verify / pmd-cyclecount :"
 		" set test type\n"
 		" --pool_sz N: set the number of crypto ops/mbufs allocated\n"
 		" --total-ops N: set the number of total operations performed\n"
diff --git a/dpdk/app/test-crypto-perf/cperf_test_latency.c b/dpdk/app/test-crypto-perf/cperf_test_latency.c
index 62478a2df5..951b4d10ac 100644
--- a/dpdk/app/test-crypto-perf/cperf_test_latency.c
+++ b/dpdk/app/test-crypto-perf/cperf_test_latency.c
@@ -313,11 +313,11 @@ cperf_latency_test_runner(void *arg)
 		if (ctx->options->csv) {
 			if (rte_atomic16_test_and_set(&display_once))
 				printf("\n# lcore, Buffer Size, Burst Size, Pakt Seq #, "
-						"Packet Size, cycles, time (us)");
+						"cycles, time (us)");
 
 			for (i = 0; i < ctx->options->total_ops; i++) {
 
-				printf("\n%u;%u;%u;%"PRIu64";%"PRIu64";%.3f",
+				printf("\n%u,%u,%u,%"PRIu64",%"PRIu64",%.3f",
 					ctx->lcore_id, ctx->options->test_buffer_size,
 					test_burst_size, i + 1,
 					ctx->res[i].tsc_end - ctx->res[i].tsc_start,
diff --git a/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c b/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
index 74371faa8d..de01e3bc51 100644
--- a/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
+++ b/dpdk/app/test-crypto-perf/cperf_test_pmd_cyclecount.c
@@ -16,7 +16,7 @@
 #define PRETTY_HDR_FMT "%12s%12s%12s%12s%12s%12s%12s%12s%12s%12s\n\n"
 #define PRETTY_LINE_FMT "%12u%12u%12u%12u%12u%12u%12u%12.0f%12.0f%12.0f\n"
 #define CSV_HDR_FMT "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"
-#define CSV_LINE_FMT "%10u;%10u;%u;%u;%u;%u;%u;%.3f;%.3f;%.3f\n"
+#define CSV_LINE_FMT "%10u,%10u,%u,%u,%u,%u,%u,%.3f,%.3f,%.3f\n"
 
 struct cperf_pmd_cyclecount_ctx {
 	uint8_t dev_id;
diff --git a/dpdk/app/test-crypto-perf/cperf_test_throughput.c b/dpdk/app/test-crypto-perf/cperf_test_throughput.c
index 35c51026fe..2528f39571 100644
--- a/dpdk/app/test-crypto-perf/cperf_test_throughput.c
+++ b/dpdk/app/test-crypto-perf/cperf_test_throughput.c
@@ -298,8 +298,8 @@ cperf_throughput_test_runner(void *test_ctx)
 					"Failed Deq,Ops(Millions),Throughput(Gbps),"
 					"Cycles/Buf\n\n");
 
-			printf("%u;%u;%u;%"PRIu64";%"PRIu64";%"PRIu64";%"PRIu64";"
-					"%.3f;%.3f;%.3f\n",
+			printf("%u,%u,%u,%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64","
+					"%.3f,%.3f,%.3f\n",
 					ctx->lcore_id,
 					ctx->options->test_buffer_size,
 					test_burst_size,
diff --git a/dpdk/app/test-crypto-perf/cperf_test_verify.c b/dpdk/app/test-crypto-perf/cperf_test_verify.c
index 833bc9a552..2939aeaa93 100644
--- a/dpdk/app/test-crypto-perf/cperf_test_verify.c
+++ b/dpdk/app/test-crypto-perf/cperf_test_verify.c
@@ -406,7 +406,7 @@ cperf_verify_test_runner(void *test_ctx)
 				"Burst Size,Enqueued,Dequeued,Failed Enq,"
 				"Failed Deq,Failed Ops\n");
 
-		printf("%10u;%10u;%u;%"PRIu64";%"PRIu64";%"PRIu64";%"PRIu64";"
+		printf("%10u,%10u,%u,%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64","
 				"%"PRIu64"\n",
 				ctx->lcore_id,
 				ctx->options->max_buffer_size,
diff --git a/dpdk/app/test-crypto-perf/main.c b/dpdk/app/test-crypto-perf/main.c
index 52a1860fbf..048b10c652 100644
--- a/dpdk/app/test-crypto-perf/main.c
+++ b/dpdk/app/test-crypto-perf/main.c
@@ -380,7 +380,7 @@ cperf_check_test_vector(struct cperf_options *opts,
 		if (opts->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
 			if (test_vec->plaintext.data == NULL)
 				return -1;
-		} else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+		} else {
 			if (test_vec->plaintext.data == NULL)
 				return -1;
 			if (test_vec->plaintext.length < opts->max_buffer_size)
@@ -430,7 +430,7 @@ cperf_check_test_vector(struct cperf_options *opts,
 				return -1;
 			if (test_vec->plaintext.length < opts->max_buffer_size)
 				return -1;
-		} else if (opts->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+		} else {
 			if (test_vec->plaintext.data == NULL)
 				return -1;
 			if (test_vec->plaintext.length < opts->max_buffer_size)
@@ -520,14 +520,14 @@ main(int argc, char **argv)
 
 	ret = cperf_options_parse(&opts, argc, argv);
 	if (ret) {
-		RTE_LOG(ERR, USER1, "Parsing on or more user options failed\n");
+		RTE_LOG(ERR, USER1, "Parsing one or more user options failed\n");
 		goto err;
 	}
 
 	ret = cperf_options_check(&opts);
 	if (ret) {
 		RTE_LOG(ERR, USER1,
-				"Checking on or more user options failed\n");
+				"Checking one or more user options failed\n");
 		goto err;
 	}
 
@@ -582,7 +582,8 @@ main(int argc, char **argv)
 		goto err;
 	}
 
-	if (!opts.silent)
+	if (!opts.silent && opts.test != CPERF_TEST_TYPE_THROUGHPUT &&
+			opts.test != CPERF_TEST_TYPE_LATENCY)
 		show_test_vector(t_vec);
 
 	total_nb_qps = nb_cryptodevs * opts.nb_qps;
diff --git a/dpdk/app/test-crypto-perf/meson.build b/dpdk/app/test-crypto-perf/meson.build
index 0674396da8..dcc4bf9cbc 100644
--- a/dpdk/app/test-crypto-perf/meson.build
+++ b/dpdk/app/test-crypto-perf/meson.build
@@ -13,3 +13,6 @@ sources = files('cperf_ops.c',
 		'cperf_test_verify.c',
 		'main.c')
 deps += ['cryptodev', 'security']
+if dpdk_conf.has('RTE_LIBRTE_CRYPTO_SCHEDULER_PMD')
+	deps += 'pmd_crypto_scheduler'
+endif
diff --git a/dpdk/app/test-eventdev/evt_options.c b/dpdk/app/test-eventdev/evt_options.c
index c60b61a904..4f4800d99d 100644
--- a/dpdk/app/test-eventdev/evt_options.c
+++ b/dpdk/app/test-eventdev/evt_options.c
@@ -197,6 +197,10 @@ evt_parse_nb_timer_adptrs(struct evt_options *opt, const char *arg)
 	int ret;
 
 	ret = parser_read_uint8(&(opt->nb_timer_adptrs), arg);
+	if (opt->nb_timer_adptrs <= 0) {
+		evt_err("Number of timer adapters cannot be <= 0");
+		return -EINVAL;
+	}
 
 	return ret;
 }
diff --git a/dpdk/app/test-eventdev/meson.build b/dpdk/app/test-eventdev/meson.build
index 7ff2b786cf..9e588d9ec7 100644
--- a/dpdk/app/test-eventdev/meson.build
+++ b/dpdk/app/test-eventdev/meson.build
@@ -10,5 +10,8 @@ sources = files('evt_main.c',
 		'test_order_queue.c',
 		'test_perf_common.c',
 		'test_perf_atq.c',
-		'test_perf_queue.c')
+		'test_perf_queue.c',
+		'test_pipeline_common.c',
+		'test_pipeline_atq.c',
+		'test_pipeline_queue.c')
 deps += 'eventdev'
diff --git a/dpdk/app/test-eventdev/test_perf_common.h b/dpdk/app/test-eventdev/test_perf_common.h
index d8fbee6d89..e095da9a47 100644
--- a/dpdk/app/test-eventdev/test_perf_common.h
+++ b/dpdk/app/test-eventdev/test_perf_common.h
@@ -97,8 +97,13 @@ perf_process_last_stage(struct rte_mempool *const pool,
 		void *bufs[], int const buf_sz, uint8_t count)
 {
 	bufs[count++] = ev->event_ptr;
-	w->processed_pkts++;
+
+	/* wmb here ensures event_prt is stored before
+	 * updating the number of processed packets
+	 * for worker lcores
+	 */
 	rte_smp_wmb();
+	w->processed_pkts++;
 
 	if (unlikely(count == buf_sz)) {
 		count = 0;
@@ -116,6 +121,12 @@ perf_process_last_stage_latency(struct rte_mempool *const pool,
 	struct perf_elt *const m = ev->event_ptr;
 
 	bufs[count++] = ev->event_ptr;
+
+	/* wmb here ensures event_prt is stored before
+	 * updating the number of processed packets
+	 * for worker lcores
+	 */
+	rte_smp_wmb();
 	w->processed_pkts++;
 
 	if (unlikely(count == buf_sz)) {
@@ -127,7 +138,6 @@ perf_process_last_stage_latency(struct rte_mempool *const pool,
 	}
 
 	w->latency += latency;
-	rte_smp_wmb();
 	return count;
 }
 
diff --git a/dpdk/app/test-eventdev/test_pipeline_atq.c b/dpdk/app/test-eventdev/test_pipeline_atq.c
index 8e8686c145..0872b25b53 100644
--- a/dpdk/app/test-eventdev/test_pipeline_atq.c
+++ b/dpdk/app/test-eventdev/test_pipeline_atq.c
@@ -495,6 +495,8 @@ pipeline_atq_capability_check(struct evt_options *opt)
 			evt_nr_active_lcores(opt->wlcores),
 			dev_info.max_event_ports);
 	}
+	if (!evt_has_all_types_queue(opt->dev_id))
+		return false;
 
 	return true;
 }
diff --git a/dpdk/app/test-eventdev/test_pipeline_common.c b/dpdk/app/test-eventdev/test_pipeline_common.c
index fa91bf2290..126e2165a3 100644
--- a/dpdk/app/test-eventdev/test_pipeline_common.c
+++ b/dpdk/app/test-eventdev/test_pipeline_common.c
@@ -385,12 +385,16 @@ pipeline_event_tx_adapter_setup(struct evt_options *opt,
 		if (!(cap & RTE_EVENT_ETH_TX_ADAPTER_CAP_INTERNAL_PORT)) {
 			uint32_t service_id = -1U;
 
-			rte_event_eth_tx_adapter_service_id_get(consm,
-					&service_id);
+			ret = rte_event_eth_tx_adapter_service_id_get(consm,
+								   &service_id);
+			if (ret != -ESRCH && ret != 0) {
+				evt_err("Failed to get Tx adptr service ID");
+				return ret;
+			}
 			ret = evt_service_setup(service_id);
 			if (ret) {
 				evt_err("Failed to setup service core"
-						" for Tx adapter\n");
+						" for Tx adapter");
 				return ret;
 			}
 		}
diff --git a/dpdk/app/test-eventdev/test_pipeline_queue.c b/dpdk/app/test-eventdev/test_pipeline_queue.c
index 7bebac34fc..9a9febb199 100644
--- a/dpdk/app/test-eventdev/test_pipeline_queue.c
+++ b/dpdk/app/test-eventdev/test_pipeline_queue.c
@@ -83,16 +83,15 @@ pipeline_queue_worker_single_stage_burst_tx(void *arg)
 			rte_prefetch0(ev[i + 1].mbuf);
 			if (ev[i].sched_type == RTE_SCHED_TYPE_ATOMIC) {
 				pipeline_event_tx(dev, port, &ev[i]);
-				ev[i].op = RTE_EVENT_OP_RELEASE;
 				w->processed_pkts++;
 			} else {
 				ev[i].queue_id++;
 				pipeline_fwd_event(&ev[i],
 						RTE_SCHED_TYPE_ATOMIC);
+				pipeline_event_enqueue_burst(dev, port, ev,
+						nb_rx);
 			}
 		}
-
-		pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
 	}
 
 	return 0;
@@ -180,13 +179,13 @@ pipeline_queue_worker_multi_stage_fwd(void *arg)
 			ev.queue_id = tx_queue[ev.mbuf->port];
 			rte_event_eth_tx_adapter_txq_set(ev.mbuf, 0);
 			pipeline_fwd_event(&ev, RTE_SCHED_TYPE_ATOMIC);
+			pipeline_event_enqueue(dev, port, &ev);
 			w->processed_pkts++;
 		} else {
 			ev.queue_id++;
 			pipeline_fwd_event(&ev, sched_type_list[cq_id]);
+			pipeline_event_enqueue(dev, port, &ev);
 		}
-
-		pipeline_event_enqueue(dev, port, &ev);
 	}
 
 	return 0;
@@ -213,7 +212,6 @@ pipeline_queue_worker_multi_stage_burst_tx(void *arg)
 
 			if (ev[i].queue_id == tx_queue[ev[i].mbuf->port]) {
 				pipeline_event_tx(dev, port, &ev[i]);
-				ev[i].op = RTE_EVENT_OP_RELEASE;
 				w->processed_pkts++;
 				continue;
 			}
@@ -222,9 +220,8 @@ pipeline_queue_worker_multi_stage_burst_tx(void *arg)
 			pipeline_fwd_event(&ev[i], cq_id != last_queue ?
 					sched_type_list[cq_id] :
 					RTE_SCHED_TYPE_ATOMIC);
+			pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
 		}
-
-		pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
 	}
 
 	return 0;
@@ -237,6 +234,7 @@ pipeline_queue_worker_multi_stage_burst_fwd(void *arg)
 	const uint8_t *tx_queue = t->tx_evqueue_id;
 
 	while (t->done == false) {
+		uint16_t processed_pkts = 0;
 		uint16_t nb_rx = rte_event_dequeue_burst(dev, port, ev,
 				BURST_SIZE, 0);
 
@@ -254,7 +252,7 @@ pipeline_queue_worker_multi_stage_burst_fwd(void *arg)
 				rte_event_eth_tx_adapter_txq_set(ev[i].mbuf, 0);
 				pipeline_fwd_event(&ev[i],
 						RTE_SCHED_TYPE_ATOMIC);
-				w->processed_pkts++;
+				processed_pkts++;
 			} else {
 				ev[i].queue_id++;
 				pipeline_fwd_event(&ev[i],
@@ -263,6 +261,7 @@ pipeline_queue_worker_multi_stage_burst_fwd(void *arg)
 		}
 
 		pipeline_event_enqueue_burst(dev, port, ev, nb_rx);
+		w->processed_pkts += processed_pkts;
 	}
 
 	return 0;
diff --git a/dpdk/app/test-pipeline/config.c b/dpdk/app/test-pipeline/config.c
index 28ac9fcc0e..33f3f1c827 100644
--- a/dpdk/app/test-pipeline/config.c
+++ b/dpdk/app/test-pipeline/config.c
@@ -42,8 +42,6 @@
 
 #include "main.h"
 
-struct app_params app;
-
 static const char usage[] = "\n";
 
 void
diff --git a/dpdk/app/test-pmd/bpf_cmd.c b/dpdk/app/test-pmd/bpf_cmd.c
index 830bfc13a5..d2deadd4e6 100644
--- a/dpdk/app/test-pmd/bpf_cmd.c
+++ b/dpdk/app/test-pmd/bpf_cmd.c
@@ -55,7 +55,7 @@ static const struct rte_bpf_xsym bpf_xsym[] = {
 struct cmd_bpf_ld_result {
 	cmdline_fixed_string_t bpf;
 	cmdline_fixed_string_t dir;
-	uint8_t port;
+	uint16_t port;
 	uint16_t queue;
 	cmdline_fixed_string_t op;
 	cmdline_fixed_string_t flags;
@@ -153,7 +153,7 @@ cmdline_parse_inst_t cmd_operate_bpf_ld_parse = {
 struct cmd_bpf_unld_result {
 	cmdline_fixed_string_t bpf;
 	cmdline_fixed_string_t dir;
-	uint8_t port;
+	uint16_t port;
 	uint16_t queue;
 };
 
diff --git a/dpdk/app/test-pmd/cmdline.c b/dpdk/app/test-pmd/cmdline.c
index 9f3e0b251b..9a9da744a1 100644
--- a/dpdk/app/test-pmd/cmdline.c
+++ b/dpdk/app/test-pmd/cmdline.c
@@ -94,7 +94,7 @@ static void cmd_help_brief_parsed(__attribute__((unused)) void *parsed_result,
 		"    help ports                      : Configuring ports.\n"
 		"    help registers                  : Reading and setting port registers.\n"
 		"    help filters                    : Filters configuration help.\n"
-		"    help traffic_management         : Traffic Management commmands.\n"
+		"    help traffic_management         : Traffic Management commands.\n"
 		"    help devices                    : Device related cmds.\n"
 		"    help all                        : All of the above sections.\n\n"
 	);
@@ -614,7 +614,7 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"set bonding mode IEEE802.3AD aggregator policy (port_id) (agg_name)"
 			"	Set Aggregation mode for IEEE802.3AD (mode 4)"
 
-			"set bonding xmit_balance_policy (port_id) (l2|l23|l34)\n"
+			"set bonding balance_xmit_policy (port_id) (l2|l23|l34)\n"
 			"	Set the transmit balance policy for bonded device running in balance mode.\n\n"
 
 			"set bonding mon_period (port_id) (value)\n"
@@ -1437,7 +1437,7 @@ cmdline_parse_inst_t cmd_set_port_setup_on = {
 struct cmd_operate_attach_port_result {
 	cmdline_fixed_string_t port;
 	cmdline_fixed_string_t keyword;
-	cmdline_fixed_string_t identifier;
+	cmdline_multi_string_t identifier;
 };
 
 static void cmd_operate_attach_port_parsed(void *parsed_result,
@@ -1460,7 +1460,7 @@ cmdline_parse_token_string_t cmd_operate_attach_port_keyword =
 			keyword, "attach");
 cmdline_parse_token_string_t cmd_operate_attach_port_identifier =
 	TOKEN_STRING_INITIALIZER(struct cmd_operate_attach_port_result,
-			identifier, NULL);
+			identifier, TOKEN_STRING_MULTI);
 
 cmdline_parse_inst_t cmd_operate_attach_port = {
 	.f = cmd_operate_attach_port_parsed,
@@ -1488,10 +1488,12 @@ static void cmd_operate_detach_port_parsed(void *parsed_result,
 {
 	struct cmd_operate_detach_port_result *res = parsed_result;
 
-	if (!strcmp(res->keyword, "detach"))
+	if (!strcmp(res->keyword, "detach")) {
+		RTE_ETH_VALID_PORTID_OR_RET(res->port_id);
 		detach_port_device(res->port_id);
-	else
+	} else {
 		printf("Unknown parameter\n");
+	}
 }
 
 cmdline_parse_token_string_t cmd_operate_detach_port_port =
@@ -1530,7 +1532,7 @@ static void cmd_operate_detach_device_parsed(void *parsed_result,
 	struct cmd_operate_detach_device_result *res = parsed_result;
 
 	if (!strcmp(res->keyword, "detach"))
-		detach_device(res->identifier);
+		detach_devargs(res->identifier);
 	else
 		printf("Unknown parameter\n");
 }
@@ -1911,18 +1913,13 @@ cmd_config_rx_tx_parsed(void *parsed_result,
 		nb_txq = res->value;
 	}
 	else if (!strcmp(res->name, "rxd")) {
-		if (res->value <= 0 || res->value > RTE_TEST_RX_DESC_MAX) {
-			printf("rxd %d invalid - must be > 0 && <= %d\n",
-					res->value, RTE_TEST_RX_DESC_MAX);
+		if (check_nb_rxd(res->value) != 0)
 			return;
-		}
 		nb_rxd = res->value;
 	} else if (!strcmp(res->name, "txd")) {
-		if (res->value <= 0 || res->value > RTE_TEST_TX_DESC_MAX) {
-			printf("txd %d invalid - must be > 0 && <= %d\n",
-					res->value, RTE_TEST_TX_DESC_MAX);
+		if (check_nb_txd(res->value) != 0)
 			return;
-		}
+
 		nb_txd = res->value;
 	} else {
 		printf("Unknown parameter\n");
@@ -1977,7 +1974,9 @@ cmd_config_max_pkt_len_parsed(void *parsed_result,
 				__attribute__((unused)) void *data)
 {
 	struct cmd_config_max_pkt_len_result *res = parsed_result;
+	uint32_t max_rx_pkt_len_backup = 0;
 	portid_t pid;
+	int ret;
 
 	if (!all_ports_stopped()) {
 		printf("Please stop all ports first\n");
@@ -1986,7 +1985,6 @@ cmd_config_max_pkt_len_parsed(void *parsed_result,
 
 	RTE_ETH_FOREACH_DEV(pid) {
 		struct rte_port *port = &ports[pid];
-		uint64_t rx_offloads = port->dev_conf.rxmode.offloads;
 
 		if (!strcmp(res->name, "max-pkt-len")) {
 			if (res->value < RTE_ETHER_MIN_LEN) {
@@ -1997,12 +1995,18 @@ cmd_config_max_pkt_len_parsed(void *parsed_result,
 			if (res->value == port->dev_conf.rxmode.max_rx_pkt_len)
 				return;
 
+			ret = eth_dev_info_get_print_err(pid, &port->dev_info);
+			if (ret != 0) {
+				printf("rte_eth_dev_info_get() failed for port %u\n",
+					pid);
+				return;
+			}
+
+			max_rx_pkt_len_backup = port->dev_conf.rxmode.max_rx_pkt_len;
+
 			port->dev_conf.rxmode.max_rx_pkt_len = res->value;
-			if (res->value > RTE_ETHER_MAX_LEN)
-				rx_offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
-			else
-				rx_offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
-			port->dev_conf.rxmode.offloads = rx_offloads;
+			if (update_jumbo_frame_offload(pid) != 0)
+				port->dev_conf.rxmode.max_rx_pkt_len = max_rx_pkt_len_backup;
 		} else {
 			printf("Unknown parameter\n");
 			return;
@@ -4171,6 +4175,9 @@ cmd_tx_vlan_set_parsed(void *parsed_result,
 {
 	struct cmd_tx_vlan_set_result *res = parsed_result;
 
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
 	if (!port_is_stopped(res->port_id)) {
 		printf("Please stop port %d first\n", res->port_id);
 		return;
@@ -4225,6 +4232,9 @@ cmd_tx_vlan_set_qinq_parsed(void *parsed_result,
 {
 	struct cmd_tx_vlan_set_qinq_result *res = parsed_result;
 
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
 	if (!port_is_stopped(res->port_id)) {
 		printf("Please stop port %d first\n", res->port_id);
 		return;
@@ -4338,6 +4348,9 @@ cmd_tx_vlan_reset_parsed(void *parsed_result,
 {
 	struct cmd_tx_vlan_reset_result *res = parsed_result;
 
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
 	if (!port_is_stopped(res->port_id)) {
 		printf("Please stop port %d first\n", res->port_id);
 		return;
@@ -5120,7 +5133,7 @@ cmd_gso_size_parsed(void *parsed_result,
 
 	if (test_done == 0) {
 		printf("Before setting GSO segsz, please first"
-				" stop fowarding\n");
+				" stop forwarding\n");
 		return;
 	}
 
@@ -7078,9 +7091,10 @@ cmd_priority_flow_ctrl_set_parsed(void *parsed_result,
 	 * the RTE_FC_RX_PAUSE, Respond to the pause frame at the Tx side.
 	 */
 	static enum rte_eth_fc_mode rx_tx_onoff_2_pfc_mode[2][2] = {
-			{RTE_FC_NONE, RTE_FC_RX_PAUSE}, {RTE_FC_TX_PAUSE, RTE_FC_FULL}
+		{RTE_FC_NONE, RTE_FC_TX_PAUSE}, {RTE_FC_RX_PAUSE, RTE_FC_FULL}
 	};
 
+	memset(&pfc_conf, 0, sizeof(struct rte_eth_pfc_conf));
 	rx_fc_enable = (!strncmp(res->rx_pfc_mode, "on",2)) ? 1 : 0;
 	tx_fc_enable = (!strncmp(res->tx_pfc_mode, "on",2)) ? 1 : 0;
 	pfc_conf.fc.mode       = rx_tx_onoff_2_pfc_mode[rx_fc_enable][tx_fc_enable];
@@ -16802,8 +16816,10 @@ cmd_ddp_get_list_parsed(
 #ifdef RTE_LIBRTE_I40E_PMD
 	size = PROFILE_INFO_SIZE * MAX_PROFILE_NUM + 4;
 	p_list = (struct rte_pmd_i40e_profile_list *)malloc(size);
-	if (!p_list)
+	if (!p_list) {
 		printf("%s: Failed to malloc buffer\n", __func__);
+		return;
+	}
 
 	if (ret == -ENOTSUP)
 		ret = rte_pmd_i40e_get_ddp_list(res->port_id,
@@ -19494,6 +19510,7 @@ cmdline_read_from_file(const char *filename)
 void
 prompt(void)
 {
+	int ret;
 	/* initialize non-constant commands */
 	cmd_set_fwd_mode_init();
 	cmd_set_fwd_retry_mode_init();
@@ -19501,15 +19518,23 @@ prompt(void)
 	testpmd_cl = cmdline_stdin_new(main_ctx, "testpmd> ");
 	if (testpmd_cl == NULL)
 		return;
+
+	ret = atexit(prompt_exit);
+	if (ret != 0)
+		printf("Cannot set exit function for cmdline\n");
+
 	cmdline_interact(testpmd_cl);
-	cmdline_stdin_exit(testpmd_cl);
+	if (ret != 0)
+		cmdline_stdin_exit(testpmd_cl);
 }
 
 void
 prompt_exit(void)
 {
-	if (testpmd_cl != NULL)
+	if (testpmd_cl != NULL) {
 		cmdline_quit(testpmd_cl);
+		cmdline_stdin_exit(testpmd_cl);
+	}
 }
 
 static void
diff --git a/dpdk/app/test-pmd/cmdline_flow.c b/dpdk/app/test-pmd/cmdline_flow.c
index 99dade7d8c..da3533c557 100644
--- a/dpdk/app/test-pmd/cmdline_flow.c
+++ b/dpdk/app/test-pmd/cmdline_flow.c
@@ -1005,7 +1005,6 @@ static const enum index item_pppoes[] = {
 };
 
 static const enum index item_pppoe_proto_id[] = {
-	ITEM_PPPOE_PROTO_ID,
 	ITEM_NEXT,
 	ZERO,
 };
@@ -2544,11 +2543,14 @@ static const struct token token_list[] = {
 					session_id)),
 	},
 	[ITEM_PPPOE_PROTO_ID] = {
-		.name = "proto_id",
+		.name = "pppoe_proto_id",
 		.help = "match PPPoE session protocol identifier",
 		.priv = PRIV_ITEM(PPPOE_PROTO_ID,
 				sizeof(struct rte_flow_item_pppoe_proto_id)),
-		.next = NEXT(item_pppoe_proto_id),
+		.next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_item_pppoe_proto_id, proto_id)),
 		.call = parse_vc,
 	},
 	[ITEM_HIGIG2] = {
@@ -2766,7 +2768,10 @@ static const struct token token_list[] = {
 		.name = "key",
 		.help = "RSS hash key",
 		.next = NEXT(action_rss, NEXT_ENTRY(HEX)),
-		.args = ARGS(ARGS_ENTRY_ARB(0, 0),
+		.args = ARGS(ARGS_ENTRY_ARB
+			     (offsetof(struct action_rss_data, conf) +
+			      offsetof(struct rte_flow_action_rss, key),
+			      sizeof(((struct rte_flow_action_rss *)0)->key)),
 			     ARGS_ENTRY_ARB
 			     (offsetof(struct action_rss_data, conf) +
 			      offsetof(struct rte_flow_action_rss, key_len),
@@ -3898,30 +3903,15 @@ parse_vc_action_rss(struct context *ctx, const struct token *token,
 			.func = RTE_ETH_HASH_FUNCTION_DEFAULT,
 			.level = 0,
 			.types = rss_hf,
-			.key_len = sizeof(action_rss_data->key),
+			.key_len = 0,
 			.queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
-			.key = action_rss_data->key,
+			.key = NULL,
 			.queue = action_rss_data->queue,
 		},
-		.key = "testpmd's default RSS hash key, "
-			"override it for better balancing",
 		.queue = { 0 },
 	};
 	for (i = 0; i < action_rss_data->conf.queue_num; ++i)
 		action_rss_data->queue[i] = i;
-	if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
-	    ctx->port != (portid_t)RTE_PORT_ALL) {
-		struct rte_eth_dev_info info;
-		int ret2;
-
-		ret2 = rte_eth_dev_info_get(ctx->port, &info);
-		if (ret2 != 0)
-			return ret2;
-
-		action_rss_data->conf.key_len =
-			RTE_MIN(sizeof(action_rss_data->key),
-				info.hash_key_size);
-	}
 	action->conf = &action_rss_data->conf;
 	return ret;
 }
@@ -4534,7 +4524,9 @@ parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token,
 	struct rte_flow_item_gre gre = {
 		.protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST),
 	};
-	struct rte_flow_item_mpls mpls;
+	struct rte_flow_item_mpls mpls = {
+		.ttl = 0,
+	};
 	uint8_t *header;
 	int ret;
 
@@ -6236,6 +6228,9 @@ flow_item_default_mask(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
 		mask = &rte_flow_item_gtp_psc_mask;
 		break;
+	case RTE_FLOW_ITEM_TYPE_GENEVE:
+		mask = &rte_flow_item_geneve_mask;
+		break;
 	case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID:
 		mask = &rte_flow_item_pppoe_proto_id_mask;
 	default:
diff --git a/dpdk/app/test-pmd/cmdline_mtr.c b/dpdk/app/test-pmd/cmdline_mtr.c
index ab5c8642db..c6e7529b3d 100644
--- a/dpdk/app/test-pmd/cmdline_mtr.c
+++ b/dpdk/app/test-pmd/cmdline_mtr.c
@@ -312,7 +312,7 @@ static void cmd_show_port_meter_cap_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_show_port_meter_cap = {
 	.f = cmd_show_port_meter_cap_parsed,
 	.data = NULL,
-	.help_str = "Show port meter cap",
+	.help_str = "show port meter cap <port_id>",
 	.tokens = {
 		(void *)&cmd_show_port_meter_cap_show,
 		(void *)&cmd_show_port_meter_cap_port,
@@ -408,7 +408,7 @@ static void cmd_add_port_meter_profile_srtcm_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_add_port_meter_profile_srtcm = {
 	.f = cmd_add_port_meter_profile_srtcm_parsed,
 	.data = NULL,
-	.help_str = "Add port meter profile srtcm (rfc2697)",
+	.help_str = "add port meter profile srtcm_rfc2697 <port_id> <profile_id> <cir> <cbs> <ebs>",
 	.tokens = {
 		(void *)&cmd_add_port_meter_profile_srtcm_add,
 		(void *)&cmd_add_port_meter_profile_srtcm_port,
@@ -515,7 +515,7 @@ static void cmd_add_port_meter_profile_trtcm_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm = {
 	.f = cmd_add_port_meter_profile_trtcm_parsed,
 	.data = NULL,
-	.help_str = "Add port meter profile trtcm (rfc2698)",
+	.help_str = "add port meter profile trtcm_rfc2698 <port_id> <profile_id> <cir> <pir> <cbs> <pbs>",
 	.tokens = {
 		(void *)&cmd_add_port_meter_profile_trtcm_add,
 		(void *)&cmd_add_port_meter_profile_trtcm_port,
@@ -627,7 +627,7 @@ static void cmd_add_port_meter_profile_trtcm_rfc4115_parsed(
 cmdline_parse_inst_t cmd_add_port_meter_profile_trtcm_rfc4115 = {
 	.f = cmd_add_port_meter_profile_trtcm_rfc4115_parsed,
 	.data = NULL,
-	.help_str = "Add port meter profile trtcm (rfc4115)",
+	.help_str = "add port meter profile trtcm_rfc4115 <port_id> <profile_id> <cir> <eir> <cbs> <ebs>",
 	.tokens = {
 		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_add,
 		(void *)&cmd_add_port_meter_profile_trtcm_rfc4115_port,
@@ -702,7 +702,7 @@ static void cmd_del_port_meter_profile_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_del_port_meter_profile = {
 	.f = cmd_del_port_meter_profile_parsed,
 	.data = NULL,
-	.help_str = "Delete port meter profile",
+	.help_str = "del port meter profile <port_id> <profile_id>",
 	.tokens = {
 		(void *)&cmd_del_port_meter_profile_del,
 		(void *)&cmd_del_port_meter_profile_port,
@@ -827,7 +827,10 @@ static void cmd_create_port_meter_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_create_port_meter = {
 	.f = cmd_create_port_meter_parsed,
 	.data = NULL,
-	.help_str = "Create port meter",
+	.help_str = "create port meter <port_id> <mtr_id> <profile_id> <meter_enable>(yes|no) "
+		"<g_action>(R|Y|G|D) <y_action>(R|Y|G|D) <r_action>(R|Y|G|D) "
+		"<stats_mask> <shared> <use_pre_meter_color> "
+		"[<dscp_tbl_entry0> <dscp_tbl_entry1> ...<dscp_tbl_entry63>]",
 	.tokens = {
 		(void *)&cmd_create_port_meter_create,
 		(void *)&cmd_create_port_meter_port,
@@ -896,7 +899,7 @@ static void cmd_enable_port_meter_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_enable_port_meter = {
 	.f = cmd_enable_port_meter_parsed,
 	.data = NULL,
-	.help_str = "Enable port meter",
+	.help_str = "enable port meter <port_id> <mtr_id>",
 	.tokens = {
 		(void *)&cmd_enable_port_meter_enable,
 		(void *)&cmd_enable_port_meter_port,
@@ -957,7 +960,7 @@ static void cmd_disable_port_meter_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_disable_port_meter = {
 	.f = cmd_disable_port_meter_parsed,
 	.data = NULL,
-	.help_str = "Disable port meter",
+	.help_str = "disable port meter <port_id> <mtr_id>",
 	.tokens = {
 		(void *)&cmd_disable_port_meter_disable,
 		(void *)&cmd_disable_port_meter_port,
@@ -1018,7 +1021,7 @@ static void cmd_del_port_meter_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_del_port_meter = {
 	.f = cmd_del_port_meter_parsed,
 	.data = NULL,
-	.help_str = "Delete port meter",
+	.help_str = "del port meter <port_id> <mtr_id>",
 	.tokens = {
 		(void *)&cmd_del_port_meter_del,
 		(void *)&cmd_del_port_meter_port,
@@ -1089,7 +1092,7 @@ static void cmd_set_port_meter_profile_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_set_port_meter_profile = {
 	.f = cmd_set_port_meter_profile_parsed,
 	.data = NULL,
-	.help_str = "Set port meter profile",
+	.help_str = "set port meter profile <port_id> <mtr_id> <profile_id>",
 	.tokens = {
 		(void *)&cmd_set_port_meter_profile_set,
 		(void *)&cmd_set_port_meter_profile_port,
@@ -1163,7 +1166,8 @@ static void cmd_set_port_meter_dscp_table_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_set_port_meter_dscp_table = {
 	.f = cmd_set_port_meter_dscp_table_parsed,
 	.data = NULL,
-	.help_str = "Update port meter dscp table",
+	.help_str = "set port meter dscp table <port_id> <mtr_id> "
+		"[<dscp_tbl_entry0> <dscp_tbl_entry1> ... <dscp_tbl_entry63>]",
 	.tokens = {
 		(void *)&cmd_set_port_meter_dscp_table_set,
 		(void *)&cmd_set_port_meter_dscp_table_port,
@@ -1262,6 +1266,7 @@ static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
 	ret = rte_mtr_policer_actions_update(port_id, mtr_id,
 		action_mask, actions, &error);
 	if (ret != 0) {
+		free(actions);
 		print_err_msg(&error);
 		return;
 	}
@@ -1272,7 +1277,8 @@ static void cmd_set_port_meter_policer_action_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_set_port_meter_policer_action = {
 	.f = cmd_set_port_meter_policer_action_parsed,
 	.data = NULL,
-	.help_str = "Set port meter policer action",
+	.help_str = "set port meter policer action <port_id> <mtr_id> "
+		"<action_mask> <action0> [<action1> <action2>]",
 	.tokens = {
 		(void *)&cmd_set_port_meter_policer_action_set,
 		(void *)&cmd_set_port_meter_policer_action_port,
@@ -1349,7 +1355,7 @@ static void cmd_set_port_meter_stats_mask_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_set_port_meter_stats_mask = {
 	.f = cmd_set_port_meter_stats_mask_parsed,
 	.data = NULL,
-	.help_str = "Set port meter stats mask",
+	.help_str = "set port meter stats mask <port_id> <mtr_id> <stats_mask>",
 	.tokens = {
 		(void *)&cmd_set_port_meter_stats_mask_set,
 		(void *)&cmd_set_port_meter_stats_mask_port,
@@ -1453,7 +1459,7 @@ static void cmd_show_port_meter_stats_parsed(void *parsed_result,
 cmdline_parse_inst_t cmd_show_port_meter_stats = {
 	.f = cmd_show_port_meter_stats_parsed,
 	.data = NULL,
-	.help_str = "Show port meter stats",
+	.help_str = "show port meter stats <port_id> <mtr_id> <clear>(yes|no)",
 	.tokens = {
 		(void *)&cmd_show_port_meter_stats_show,
 		(void *)&cmd_show_port_meter_stats_port,
diff --git a/dpdk/app/test-pmd/config.c b/dpdk/app/test-pmd/config.c
index d599682788..e14ff42745 100644
--- a/dpdk/app/test-pmd/config.c
+++ b/dpdk/app/test-pmd/config.c
@@ -53,6 +53,14 @@
 
 #include "testpmd.h"
 
+#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
+#define CLOCK_TYPE_ID CLOCK_MONOTONIC_RAW
+#else
+#define CLOCK_TYPE_ID CLOCK_MONOTONIC
+#endif
+
+#define NS_PER_SEC 1E9
+
 static char *flowtype_to_str(uint16_t flow_type);
 
 static const struct {
@@ -125,9 +133,10 @@ nic_stats_display(portid_t port_id)
 	static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
 	static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];
 	static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];
-	static uint64_t prev_cycles[RTE_MAX_ETHPORTS];
+	static uint64_t prev_ns[RTE_MAX_ETHPORTS];
+	struct timespec cur_time;
 	uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx,
-								diff_cycles;
+								diff_ns;
 	uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;
 	struct rte_eth_stats stats;
 	struct rte_port *port = &ports[port_id];
@@ -184,10 +193,17 @@ nic_stats_display(portid_t port_id)
 		}
 	}
 
-	diff_cycles = prev_cycles[port_id];
-	prev_cycles[port_id] = rte_rdtsc();
-	if (diff_cycles > 0)
-		diff_cycles = prev_cycles[port_id] - diff_cycles;
+	diff_ns = 0;
+	if (clock_gettime(CLOCK_TYPE_ID, &cur_time) == 0) {
+		uint64_t ns;
+
+		ns = cur_time.tv_sec * NS_PER_SEC;
+		ns += cur_time.tv_nsec;
+
+		if (prev_ns[port_id] != 0)
+			diff_ns = ns - prev_ns[port_id];
+		prev_ns[port_id] = ns;
+	}
 
 	diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?
 		(stats.ipackets - prev_pkts_rx[port_id]) : 0;
@@ -195,10 +211,10 @@ nic_stats_display(portid_t port_id)
 		(stats.opackets - prev_pkts_tx[port_id]) : 0;
 	prev_pkts_rx[port_id] = stats.ipackets;
 	prev_pkts_tx[port_id] = stats.opackets;
-	mpps_rx = diff_cycles > 0 ?
-		diff_pkts_rx * rte_get_tsc_hz() / diff_cycles : 0;
-	mpps_tx = diff_cycles > 0 ?
-		diff_pkts_tx * rte_get_tsc_hz() / diff_cycles : 0;
+	mpps_rx = diff_ns > 0 ?
+		(double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0;
+	mpps_tx = diff_ns > 0 ?
+		(double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0;
 
 	diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ?
 		(stats.ibytes - prev_bytes_rx[port_id]) : 0;
@@ -206,10 +222,10 @@ nic_stats_display(portid_t port_id)
 		(stats.obytes - prev_bytes_tx[port_id]) : 0;
 	prev_bytes_rx[port_id] = stats.ibytes;
 	prev_bytes_tx[port_id] = stats.obytes;
-	mbps_rx = diff_cycles > 0 ?
-		diff_bytes_rx * rte_get_tsc_hz() / diff_cycles : 0;
-	mbps_tx = diff_cycles > 0 ?
-		diff_bytes_tx * rte_get_tsc_hz() / diff_cycles : 0;
+	mbps_rx = diff_ns > 0 ?
+		(double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0;
+	mbps_tx = diff_ns > 0 ?
+		(double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0;
 
 	printf("\n  Throughput (since last show)\n");
 	printf("  Rx-pps: %12"PRIu64"          Rx-bps: %12"PRIu64"\n  Tx-pps: %12"
@@ -223,11 +239,28 @@ nic_stats_display(portid_t port_id)
 void
 nic_stats_clear(portid_t port_id)
 {
+	int ret;
+
 	if (port_id_is_invalid(port_id, ENABLED_WARN)) {
 		print_valid_ports();
 		return;
 	}
-	rte_eth_stats_reset(port_id);
+
+	ret = rte_eth_stats_reset(port_id);
+	if (ret != 0) {
+		printf("%s: Error: failed to reset stats (port %u): %s",
+		       __func__, port_id, strerror(-ret));
+		return;
+	}
+
+	ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
+	if (ret != 0) {
+		if (ret < 0)
+			ret = -ret;
+		printf("%s: Error: failed to get stats (port %u): %s",
+		       __func__, port_id, strerror(ret));
+		return;
+	}
 	printf("\n  NIC statistics for port %d cleared\n", port_id);
 }
 
@@ -303,10 +336,21 @@ nic_xstats_clear(portid_t port_id)
 		print_valid_ports();
 		return;
 	}
+
 	ret = rte_eth_xstats_reset(port_id);
 	if (ret != 0) {
 		printf("%s: Error: failed to reset xstats (port %u): %s",
+		       __func__, port_id, strerror(-ret));
+		return;
+	}
+
+	ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
+	if (ret != 0) {
+		if (ret < 0)
+			ret = -ret;
+		printf("%s: Error: failed to get stats (port %u): %s",
 		       __func__, port_id, strerror(ret));
+		return;
 	}
 }
 
@@ -1216,7 +1260,9 @@ void
 port_mtu_set(portid_t port_id, uint16_t mtu)
 {
 	int diag;
+	struct rte_port *rte_port = &ports[port_id];
 	struct rte_eth_dev_info dev_info;
+	uint16_t eth_overhead;
 	int ret;
 
 	if (port_id_is_invalid(port_id, ENABLED_WARN))
@@ -1232,9 +1278,24 @@ port_mtu_set(portid_t port_id, uint16_t mtu)
 		return;
 	}
 	diag = rte_eth_dev_set_mtu(port_id, mtu);
-	if (diag == 0)
-		return;
-	printf("Set MTU failed. diag=%d\n", diag);
+	if (diag)
+		printf("Set MTU failed. diag=%d\n", diag);
+	else if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) {
+		/*
+		 * Ether overhead in driver is equal to the difference of
+		 * max_rx_pktlen and max_mtu in rte_eth_dev_info when the
+		 * device supports jumbo frame.
+		 */
+		eth_overhead = dev_info.max_rx_pktlen - dev_info.max_mtu;
+		if (mtu > RTE_ETHER_MTU) {
+			rte_port->dev_conf.rxmode.offloads |=
+						DEV_RX_OFFLOAD_JUMBO_FRAME;
+			rte_port->dev_conf.rxmode.max_rx_pkt_len =
+						mtu + eth_overhead;
+		} else
+			rte_port->dev_conf.rxmode.offloads &=
+						~DEV_RX_OFFLOAD_JUMBO_FRAME;
+	}
 }
 
 /* Generic flow management functions. */
@@ -1507,7 +1568,7 @@ port_flow_query(portid_t port_id, uint32_t rule,
 
 /** List flow rules. */
 void
-port_flow_list(portid_t port_id, uint32_t n, const uint32_t group[n])
+port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group)
 {
 	struct rte_port *port;
 	struct port_flow *pf;
@@ -1624,22 +1685,102 @@ tx_queue_id_is_invalid(queueid_t txq_id)
 }
 
 static int
-rx_desc_id_is_invalid(uint16_t rxdesc_id)
+get_rx_ring_size(portid_t port_id, queueid_t rxq_id, uint16_t *ring_size)
 {
-	if (rxdesc_id < nb_rxd)
+	struct rte_port *port = &ports[port_id];
+	struct rte_eth_rxq_info rx_qinfo;
+	int ret;
+
+	ret = rte_eth_rx_queue_info_get(port_id, rxq_id, &rx_qinfo);
+	if (ret == 0) {
+		*ring_size = rx_qinfo.nb_desc;
+		return ret;
+	}
+
+	if (ret != -ENOTSUP)
+		return ret;
+	/*
+	 * If the rte_eth_rx_queue_info_get is not support for this PMD,
+	 * ring_size stored in testpmd will be used for validity verification.
+	 * When configure the rxq by rte_eth_rx_queue_setup with nb_rx_desc
+	 * being 0, it will use a default value provided by PMDs to setup this
+	 * rxq. If the default value is 0, it will use the
+	 * RTE_ETH_DEV_FALLBACK_RX_RINGSIZE to setup this rxq.
+	 */
+	if (port->nb_rx_desc[rxq_id])
+		*ring_size = port->nb_rx_desc[rxq_id];
+	else if (port->dev_info.default_rxportconf.ring_size)
+		*ring_size = port->dev_info.default_rxportconf.ring_size;
+	else
+		*ring_size = RTE_ETH_DEV_FALLBACK_RX_RINGSIZE;
+	return 0;
+}
+
+static int
+get_tx_ring_size(portid_t port_id, queueid_t txq_id, uint16_t *ring_size)
+{
+	struct rte_port *port = &ports[port_id];
+	struct rte_eth_txq_info tx_qinfo;
+	int ret;
+
+	ret = rte_eth_tx_queue_info_get(port_id, txq_id, &tx_qinfo);
+	if (ret == 0) {
+		*ring_size = tx_qinfo.nb_desc;
+		return ret;
+	}
+
+	if (ret != -ENOTSUP)
+		return ret;
+	/*
+	 * If the rte_eth_tx_queue_info_get is not support for this PMD,
+	 * ring_size stored in testpmd will be used for validity verification.
+	 * When configure the txq by rte_eth_tx_queue_setup with nb_tx_desc
+	 * being 0, it will use a default value provided by PMDs to setup this
+	 * txq. If the default value is 0, it will use the
+	 * RTE_ETH_DEV_FALLBACK_TX_RINGSIZE to setup this txq.
+	 */
+	if (port->nb_tx_desc[txq_id])
+		*ring_size = port->nb_tx_desc[txq_id];
+	else if (port->dev_info.default_txportconf.ring_size)
+		*ring_size = port->dev_info.default_txportconf.ring_size;
+	else
+		*ring_size = RTE_ETH_DEV_FALLBACK_TX_RINGSIZE;
+	return 0;
+}
+
+static int
+rx_desc_id_is_invalid(portid_t port_id, queueid_t rxq_id, uint16_t rxdesc_id)
+{
+	uint16_t ring_size;
+	int ret;
+
+	ret = get_rx_ring_size(port_id, rxq_id, &ring_size);
+	if (ret)
+		return 1;
+
+	if (rxdesc_id < ring_size)
 		return 0;
-	printf("Invalid RX descriptor %d (must be < nb_rxd=%d)\n",
-	       rxdesc_id, nb_rxd);
+
+	printf("Invalid RX descriptor %u (must be < ring_size=%u)\n",
+	       rxdesc_id, ring_size);
 	return 1;
 }
 
 static int
-tx_desc_id_is_invalid(uint16_t txdesc_id)
+tx_desc_id_is_invalid(portid_t port_id, queueid_t txq_id, uint16_t txdesc_id)
 {
-	if (txdesc_id < nb_txd)
+	uint16_t ring_size;
+	int ret;
+
+	ret = get_tx_ring_size(port_id, txq_id, &ring_size);
+	if (ret)
+		return 1;
+
+	if (txdesc_id < ring_size)
 		return 0;
-	printf("Invalid TX descriptor %d (must be < nb_txd=%d)\n",
-	       txdesc_id, nb_txd);
+
+	printf("Invalid TX descriptor %u (must be < ring_size=%u)\n",
+	       txdesc_id, ring_size);
 	return 1;
 }
 
@@ -1760,11 +1901,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id)
 {
 	const struct rte_memzone *rx_mz;
 
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
-	if (rx_queue_id_is_invalid(rxq_id))
-		return;
-	if (rx_desc_id_is_invalid(rxd_id))
+	if (rx_desc_id_is_invalid(port_id, rxq_id, rxd_id))
 		return;
 	rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id);
 	if (rx_mz == NULL)
@@ -1777,11 +1914,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id)
 {
 	const struct rte_memzone *tx_mz;
 
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
-	if (tx_queue_id_is_invalid(txq_id))
-		return;
-	if (tx_desc_id_is_invalid(txd_id))
+	if (tx_desc_id_is_invalid(port_id, txq_id, txd_id))
 		return;
 	tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id);
 	if (tx_mz == NULL)
@@ -1822,10 +1955,17 @@ rxtx_config_display(void)
 		struct rte_eth_txconf *tx_conf = &ports[pid].tx_conf[0];
 		uint16_t *nb_rx_desc = &ports[pid].nb_rx_desc[0];
 		uint16_t *nb_tx_desc = &ports[pid].nb_tx_desc[0];
-		uint16_t nb_rx_desc_tmp;
-		uint16_t nb_tx_desc_tmp;
 		struct rte_eth_rxq_info rx_qinfo;
 		struct rte_eth_txq_info tx_qinfo;
+		uint16_t rx_free_thresh_tmp;
+		uint16_t tx_free_thresh_tmp;
+		uint16_t tx_rs_thresh_tmp;
+		uint16_t nb_rx_desc_tmp;
+		uint16_t nb_tx_desc_tmp;
+		uint64_t offloads_tmp;
+		uint8_t pthresh_tmp;
+		uint8_t hthresh_tmp;
+		uint8_t wthresh_tmp;
 		int32_t rc;
 
 		/* per port config */
@@ -1839,41 +1979,64 @@ rxtx_config_display(void)
 		/* per rx queue config only for first queue to be less verbose */
 		for (qid = 0; qid < 1; qid++) {
 			rc = rte_eth_rx_queue_info_get(pid, qid, &rx_qinfo);
-			if (rc)
+			if (rc) {
 				nb_rx_desc_tmp = nb_rx_desc[qid];
-			else
+				rx_free_thresh_tmp =
+					rx_conf[qid].rx_free_thresh;
+				pthresh_tmp = rx_conf[qid].rx_thresh.pthresh;
+				hthresh_tmp = rx_conf[qid].rx_thresh.hthresh;
+				wthresh_tmp = rx_conf[qid].rx_thresh.wthresh;
+				offloads_tmp = rx_conf[qid].offloads;
+			} else {
 				nb_rx_desc_tmp = rx_qinfo.nb_desc;
+				rx_free_thresh_tmp =
+						rx_qinfo.conf.rx_free_thresh;
+				pthresh_tmp = rx_qinfo.conf.rx_thresh.pthresh;
+				hthresh_tmp = rx_qinfo.conf.rx_thresh.hthresh;
+				wthresh_tmp = rx_qinfo.conf.rx_thresh.wthresh;
+				offloads_tmp = rx_qinfo.conf.offloads;
+			}
 
 			printf("    RX queue: %d\n", qid);
 			printf("      RX desc=%d - RX free threshold=%d\n",
-				nb_rx_desc_tmp, rx_conf[qid].rx_free_thresh);
+				nb_rx_desc_tmp, rx_free_thresh_tmp);
 			printf("      RX threshold registers: pthresh=%d hthresh=%d "
 				" wthresh=%d\n",
-				rx_conf[qid].rx_thresh.pthresh,
-				rx_conf[qid].rx_thresh.hthresh,
-				rx_conf[qid].rx_thresh.wthresh);
-			printf("      RX Offloads=0x%"PRIx64"\n",
-				rx_conf[qid].offloads);
+				pthresh_tmp, hthresh_tmp, wthresh_tmp);
+			printf("      RX Offloads=0x%"PRIx64"\n", offloads_tmp);
 		}
 
 		/* per tx queue config only for first queue to be less verbose */
 		for (qid = 0; qid < 1; qid++) {
 			rc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo);
-			if (rc)
+			if (rc) {
 				nb_tx_desc_tmp = nb_tx_desc[qid];
-			else
+				tx_free_thresh_tmp =
+					tx_conf[qid].tx_free_thresh;
+				pthresh_tmp = tx_conf[qid].tx_thresh.pthresh;
+				hthresh_tmp = tx_conf[qid].tx_thresh.hthresh;
+				wthresh_tmp = tx_conf[qid].tx_thresh.wthresh;
+				offloads_tmp = tx_conf[qid].offloads;
+				tx_rs_thresh_tmp = tx_conf[qid].tx_rs_thresh;
+			} else {
 				nb_tx_desc_tmp = tx_qinfo.nb_desc;
+				tx_free_thresh_tmp =
+						tx_qinfo.conf.tx_free_thresh;
+				pthresh_tmp = tx_qinfo.conf.tx_thresh.pthresh;
+				hthresh_tmp = tx_qinfo.conf.tx_thresh.hthresh;
+				wthresh_tmp = tx_qinfo.conf.tx_thresh.wthresh;
+				offloads_tmp = tx_qinfo.conf.offloads;
+				tx_rs_thresh_tmp = tx_qinfo.conf.tx_rs_thresh;
+			}
 
 			printf("    TX queue: %d\n", qid);
 			printf("      TX desc=%d - TX free threshold=%d\n",
-				nb_tx_desc_tmp, tx_conf[qid].tx_free_thresh);
+				nb_tx_desc_tmp, tx_free_thresh_tmp);
 			printf("      TX threshold registers: pthresh=%d hthresh=%d "
 				" wthresh=%d\n",
-				tx_conf[qid].tx_thresh.pthresh,
-				tx_conf[qid].tx_thresh.hthresh,
-				tx_conf[qid].tx_thresh.wthresh);
+				pthresh_tmp, hthresh_tmp, wthresh_tmp);
 			printf("      TX offloads=0x%"PRIx64" - TX RS bit threshold=%d\n",
-				tx_conf[qid].offloads, tx_conf->tx_rs_thresh);
+				offloads_tmp, tx_rs_thresh_tmp);
 		}
 	}
 }
@@ -2518,6 +2681,10 @@ set_fwd_lcores_mask(uint64_t lcoremask)
 void
 set_fwd_lcores_number(uint16_t nb_lc)
 {
+	if (test_done == 0) {
+		printf("Please stop forwarding first\n");
+		return;
+	}
 	if (nb_lc > nb_cfg_lcores) {
 		printf("nb fwd cores %u > %u (max. number of configured "
 		       "lcores) - ignored\n",
@@ -2665,17 +2832,41 @@ show_tx_pkt_segments(void)
 	printf("Split packet: %s\n", split);
 }
 
+static bool
+nb_segs_is_invalid(unsigned int nb_segs)
+{
+	uint16_t ring_size;
+	uint16_t queue_id;
+	uint16_t port_id;
+	int ret;
+
+	RTE_ETH_FOREACH_DEV(port_id) {
+		for (queue_id = 0; queue_id < nb_txq; queue_id++) {
+			ret = get_tx_ring_size(port_id, queue_id, &ring_size);
+
+			if (ret)
+				return true;
+
+			if (ring_size < nb_segs) {
+				printf("nb segments per TX packets=%u >= "
+				       "TX queue(%u) ring_size=%u - ignored\n",
+				       nb_segs, queue_id, ring_size);
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
 void
 set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs)
 {
 	uint16_t tx_pkt_len;
 	unsigned i;
 
-	if (nb_segs >= (unsigned) nb_txd) {
-		printf("nb segments per TX packets=%u >= nb_txd=%u - ignored\n",
-		       nb_segs, (unsigned int) nb_txd);
+	if (nb_segs_is_invalid(nb_segs))
 		return;
-	}
 
 	/*
 	 * Check that each segment length is greater or equal than
@@ -3019,9 +3210,11 @@ vlan_extend_set(portid_t port_id, int on)
 	}
 
 	diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
-	if (diag < 0)
+	if (diag < 0) {
 		printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed "
 	       "diag=%d\n", port_id, on, diag);
+		return;
+	}
 	ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
 }
 
@@ -3046,9 +3239,11 @@ rx_vlan_strip_set(portid_t port_id, int on)
 	}
 
 	diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
-	if (diag < 0)
+	if (diag < 0) {
 		printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed "
 	       "diag=%d\n", port_id, on, diag);
+		return;
+	}
 	ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
 }
 
@@ -3087,9 +3282,11 @@ rx_vlan_filter_set(portid_t port_id, int on)
 	}
 
 	diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
-	if (diag < 0)
+	if (diag < 0) {
 		printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed "
 	       "diag=%d\n", port_id, on, diag);
+		return;
+	}
 	ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
 }
 
@@ -3114,9 +3311,11 @@ rx_vlan_qinq_strip_set(portid_t port_id, int on)
 	}
 
 	diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
-	if (diag < 0)
+	if (diag < 0) {
 		printf("%s(port_pi=%d, on=%d) failed "
 	       "diag=%d\n", __func__, port_id, on, diag);
+		return;
+	}
 	ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
 }
 
@@ -3174,8 +3373,6 @@ tx_vlan_set(portid_t port_id, uint16_t vlan_id)
 	struct rte_eth_dev_info dev_info;
 	int ret;
 
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
 	if (vlan_id_is_invalid(vlan_id))
 		return;
 
@@ -3206,8 +3403,6 @@ tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
 	struct rte_eth_dev_info dev_info;
 	int ret;
 
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
 	if (vlan_id_is_invalid(vlan_id))
 		return;
 	if (vlan_id_is_invalid(vlan_id_outer))
@@ -3233,8 +3428,6 @@ tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
 void
 tx_vlan_reset(portid_t port_id)
 {
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
 	ports[port_id].dev_conf.txmode.offloads &=
 				~(DEV_TX_OFFLOAD_VLAN_INSERT |
 				  DEV_TX_OFFLOAD_QINQ_INSERT);
@@ -3707,6 +3900,14 @@ mcast_addr_pool_extend(struct rte_port *port)
 
 }
 
+static void
+mcast_addr_pool_append(struct rte_port *port, struct rte_ether_addr *mc_addr)
+{
+	if (mcast_addr_pool_extend(port) != 0)
+		return;
+	rte_ether_addr_copy(mc_addr, &port->mc_addr_pool[port->mc_addr_nb - 1]);
+}
+
 static void
 mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx)
 {
@@ -3725,7 +3926,7 @@ mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx)
 		sizeof(struct rte_ether_addr) * (port->mc_addr_nb - addr_idx));
 }
 
-static void
+static int
 eth_port_multicast_addr_list_set(portid_t port_id)
 {
 	struct rte_port *port;
@@ -3734,10 +3935,11 @@ eth_port_multicast_addr_list_set(portid_t port_id)
 	port = &ports[port_id];
 	diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool,
 					    port->mc_addr_nb);
-	if (diag == 0)
-		return;
-	printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n",
-	       port->mc_addr_nb, port_id, -diag);
+	if (diag < 0)
+		printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n",
+			port_id, port->mc_addr_nb, diag);
+
+	return diag;
 }
 
 void
@@ -3762,10 +3964,10 @@ mcast_addr_add(portid_t port_id, struct rte_ether_addr *mc_addr)
 		}
 	}
 
-	if (mcast_addr_pool_extend(port) != 0)
-		return;
-	rte_ether_addr_copy(mc_addr, &port->mc_addr_pool[i]);
-	eth_port_multicast_addr_list_set(port_id);
+	mcast_addr_pool_append(port, mc_addr);
+	if (eth_port_multicast_addr_list_set(port_id) < 0)
+		/* Rollback on failure, remove the address from the pool */
+		mcast_addr_pool_remove(port, i);
 }
 
 void
@@ -3792,7 +3994,9 @@ mcast_addr_remove(portid_t port_id, struct rte_ether_addr *mc_addr)
 	}
 
 	mcast_addr_pool_remove(port, i);
-	eth_port_multicast_addr_list_set(port_id);
+	if (eth_port_multicast_addr_list_set(port_id) < 0)
+		/* Rollback on failure, add the address back into the pool */
+		mcast_addr_pool_append(port, mc_addr);
 }
 
 void
diff --git a/dpdk/app/test-pmd/csumonly.c b/dpdk/app/test-pmd/csumonly.c
index 25091de881..7b92ab1195 100644
--- a/dpdk/app/test-pmd/csumonly.c
+++ b/dpdk/app/test-pmd/csumonly.c
@@ -139,22 +139,23 @@ parse_ipv6(struct rte_ipv6_hdr *ipv6_hdr, struct testpmd_offload_info *info)
 
 /*
  * Parse an ethernet header to fill the ethertype, l2_len, l3_len and
- * ipproto. This function is able to recognize IPv4/IPv6 with one optional vlan
- * header. The l4_len argument is only set in case of TCP (useful for TSO).
+ * ipproto. This function is able to recognize IPv4/IPv6 with optional VLAN
+ * headers. The l4_len argument is only set in case of TCP (useful for TSO).
  */
 static void
 parse_ethernet(struct rte_ether_hdr *eth_hdr, struct testpmd_offload_info *info)
 {
 	struct rte_ipv4_hdr *ipv4_hdr;
 	struct rte_ipv6_hdr *ipv6_hdr;
+	struct rte_vlan_hdr *vlan_hdr;
 
 	info->l2_len = sizeof(struct rte_ether_hdr);
 	info->ethertype = eth_hdr->ether_type;
 
-	if (info->ethertype == _htons(RTE_ETHER_TYPE_VLAN)) {
-		struct rte_vlan_hdr *vlan_hdr = (
-			struct rte_vlan_hdr *)(eth_hdr + 1);
-
+	while (info->ethertype == _htons(RTE_ETHER_TYPE_VLAN) ||
+	       info->ethertype == _htons(RTE_ETHER_TYPE_QINQ)) {
+		vlan_hdr = (struct rte_vlan_hdr *)
+			((char *)eth_hdr + info->l2_len);
 		info->l2_len  += sizeof(struct rte_vlan_hdr);
 		info->ethertype = vlan_hdr->eth_proto;
 	}
diff --git a/dpdk/app/test-pmd/flowgen.c b/dpdk/app/test-pmd/flowgen.c
index 03b72aaa56..3e1335b627 100644
--- a/dpdk/app/test-pmd/flowgen.c
+++ b/dpdk/app/test-pmd/flowgen.c
@@ -1,35 +1,5 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2013 Tilera Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Tilera Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
  */
 
 #include <stdarg.h>
@@ -83,8 +53,11 @@ static struct rte_ether_addr cfg_ether_dst =
 
 #define IP_DEFTTL  64   /* from RFC 1340. */
 
+/* Use this type to inform GCC that ip_sum violates aliasing rules. */
+typedef unaligned_uint16_t alias_int16_t __attribute__((__may_alias__));
+
 static inline uint16_t
-ip_sum(const unaligned_uint16_t *hdr, int hdr_len)
+ip_sum(const alias_int16_t *hdr, int hdr_len)
 {
 	uint32_t sum = 0;
 
@@ -186,7 +159,7 @@ pkt_burst_flow_gen(struct fwd_stream *fs)
 							   next_flow);
 		ip_hdr->total_length	= RTE_CPU_TO_BE_16(pkt_size -
 							   sizeof(*eth_hdr));
-		ip_hdr->hdr_checksum	= ip_sum((unaligned_uint16_t *)ip_hdr,
+		ip_hdr->hdr_checksum	= ip_sum((const alias_int16_t *)ip_hdr,
 						 sizeof(*ip_hdr));
 
 		/* Initialize UDP header. */
diff --git a/dpdk/app/test-pmd/macswap.c b/dpdk/app/test-pmd/macswap.c
index 71af916fc3..8428c26d85 100644
--- a/dpdk/app/test-pmd/macswap.c
+++ b/dpdk/app/test-pmd/macswap.c
@@ -1,34 +1,5 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2014 Tilera Corporation. All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Tilera Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2014-2020 Mellanox Technologies, Ltd
  */
 
 #include <stdarg.h>
diff --git a/dpdk/app/test-pmd/meson.build b/dpdk/app/test-pmd/meson.build
index 6006c60f99..b0249bdb3c 100644
--- a/dpdk/app/test-pmd/meson.build
+++ b/dpdk/app/test-pmd/meson.build
@@ -28,6 +28,18 @@ deps += ['ethdev', 'gro', 'gso', 'cmdline', 'metrics', 'meter', 'bus_pci']
 if dpdk_conf.has('RTE_LIBRTE_PDUMP')
 	deps += 'pdump'
 endif
+if dpdk_conf.has('RTE_LIBRTE_BITRATESTATS')
+	deps += 'bitratestats'
+endif
+if dpdk_conf.has('RTE_LIBRTE_LATENCYSTATS')
+	deps += 'latencystats'
+endif
+if dpdk_conf.has('RTE_LIBRTE_PMD_CRYPTO_SCHEDULER')
+	deps += 'pmd_crypto_scheduler'
+endif
+if dpdk_conf.has('RTE_LIBRTE_BOND_PMD')
+	deps += 'pmd_bond'
+endif
 if dpdk_conf.has('RTE_LIBRTE_BNXT_PMD')
 	deps += 'pmd_bnxt'
 endif
diff --git a/dpdk/app/test-pmd/parameters.c b/dpdk/app/test-pmd/parameters.c
index 2e7a504415..a1c08a411a 100644
--- a/dpdk/app/test-pmd/parameters.c
+++ b/dpdk/app/test-pmd/parameters.c
@@ -49,7 +49,7 @@
 static void
 usage(char* progname)
 {
-	printf("usage: %s "
+	printf("usage: %s [EAL options] -- "
 #ifdef RTE_LIBRTE_CMDLINE
 	       "[--interactive|-i] "
 	       "[--cmdline-file=FILENAME] "
@@ -884,12 +884,9 @@ launch_args_parse(int argc, char** argv)
 			}
 			if (!strcmp(lgopts[opt_idx].name, "max-pkt-len")) {
 				n = atoi(optarg);
-				if (n >= RTE_ETHER_MIN_LEN) {
+				if (n >= RTE_ETHER_MIN_LEN)
 					rx_mode.max_rx_pkt_len = (uint32_t) n;
-					if (n > RTE_ETHER_MAX_LEN)
-						rx_offloads |=
-							DEV_RX_OFFLOAD_JUMBO_FRAME;
-				} else
+				else
 					rte_exit(EXIT_FAILURE,
 						 "Invalid max-pkt-len=%d - should be > %d\n",
 						 n, RTE_ETHER_MIN_LEN);
diff --git a/dpdk/app/test-pmd/testpmd.c b/dpdk/app/test-pmd/testpmd.c
index b374682236..0c3361e817 100644
--- a/dpdk/app/test-pmd/testpmd.c
+++ b/dpdk/app/test-pmd/testpmd.c
@@ -421,8 +421,11 @@ lcoreid_t latencystats_lcore_id = -1;
  * Ethernet device configuration.
  */
 struct rte_eth_rxmode rx_mode = {
-	.max_rx_pkt_len = RTE_ETHER_MAX_LEN,
-		/**< Default maximum frame length. */
+	/* Default maximum frame length.
+	 * Zero is converted to "RTE_ETHER_MTU + PMD Ethernet overhead"
+	 * in init_config().
+	 */
+	.max_rx_pkt_len = 0,
 };
 
 struct rte_eth_txmode tx_mode = {
@@ -1071,6 +1074,177 @@ check_nb_txq(queueid_t txq)
 	return 0;
 }
 
+/*
+ * Get the allowed maximum number of RXDs of every rx queue.
+ * *pid return the port id which has minimal value of
+ * max_rxd in all queues of all ports.
+ */
+static uint16_t
+get_allowed_max_nb_rxd(portid_t *pid)
+{
+	uint16_t allowed_max_rxd = UINT16_MAX;
+	portid_t pi;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_FOREACH_DEV(pi) {
+		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+			continue;
+
+		if (dev_info.rx_desc_lim.nb_max < allowed_max_rxd) {
+			allowed_max_rxd = dev_info.rx_desc_lim.nb_max;
+			*pid = pi;
+		}
+	}
+	return allowed_max_rxd;
+}
+
+/*
+ * Get the allowed minimal number of RXDs of every rx queue.
+ * *pid return the port id which has minimal value of
+ * min_rxd in all queues of all ports.
+ */
+static uint16_t
+get_allowed_min_nb_rxd(portid_t *pid)
+{
+	uint16_t allowed_min_rxd = 0;
+	portid_t pi;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_FOREACH_DEV(pi) {
+		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+			continue;
+
+		if (dev_info.rx_desc_lim.nb_min > allowed_min_rxd) {
+			allowed_min_rxd = dev_info.rx_desc_lim.nb_min;
+			*pid = pi;
+		}
+	}
+
+	return allowed_min_rxd;
+}
+
+/*
+ * Check input rxd is valid or not.
+ * If input rxd is not greater than any of maximum number
+ * of RXDs of every Rx queues and is not less than any of
+ * minimal number of RXDs of every Rx queues, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_rxd(queueid_t rxd)
+{
+	uint16_t allowed_max_rxd;
+	uint16_t allowed_min_rxd;
+	portid_t pid = 0;
+
+	allowed_max_rxd = get_allowed_max_nb_rxd(&pid);
+	if (rxd > allowed_max_rxd) {
+		printf("Fail: input rxd (%u) can't be greater "
+		       "than max_rxds (%u) of port %u\n",
+		       rxd,
+		       allowed_max_rxd,
+		       pid);
+		return -1;
+	}
+
+	allowed_min_rxd = get_allowed_min_nb_rxd(&pid);
+	if (rxd < allowed_min_rxd) {
+		printf("Fail: input rxd (%u) can't be less "
+		       "than min_rxds (%u) of port %u\n",
+		       rxd,
+		       allowed_min_rxd,
+		       pid);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Get the allowed maximum number of TXDs of every rx queues.
+ * *pid return the port id which has minimal value of
+ * max_txd in every tx queue.
+ */
+static uint16_t
+get_allowed_max_nb_txd(portid_t *pid)
+{
+	uint16_t allowed_max_txd = UINT16_MAX;
+	portid_t pi;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_FOREACH_DEV(pi) {
+		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+			continue;
+
+		if (dev_info.tx_desc_lim.nb_max < allowed_max_txd) {
+			allowed_max_txd = dev_info.tx_desc_lim.nb_max;
+			*pid = pi;
+		}
+	}
+	return allowed_max_txd;
+}
+
+/*
+ * Get the allowed maximum number of TXDs of every tx queues.
+ * *pid return the port id which has minimal value of
+ * min_txd in every tx queue.
+ */
+static uint16_t
+get_allowed_min_nb_txd(portid_t *pid)
+{
+	uint16_t allowed_min_txd = 0;
+	portid_t pi;
+	struct rte_eth_dev_info dev_info;
+
+	RTE_ETH_FOREACH_DEV(pi) {
+		if (eth_dev_info_get_print_err(pi, &dev_info) != 0)
+			continue;
+
+		if (dev_info.tx_desc_lim.nb_min > allowed_min_txd) {
+			allowed_min_txd = dev_info.tx_desc_lim.nb_min;
+			*pid = pi;
+		}
+	}
+
+	return allowed_min_txd;
+}
+
+/*
+ * Check input txd is valid or not.
+ * If input txd is not greater than any of maximum number
+ * of TXDs of every Rx queues, it is valid.
+ * if valid, return 0, else return -1
+ */
+int
+check_nb_txd(queueid_t txd)
+{
+	uint16_t allowed_max_txd;
+	uint16_t allowed_min_txd;
+	portid_t pid = 0;
+
+	allowed_max_txd = get_allowed_max_nb_txd(&pid);
+	if (txd > allowed_max_txd) {
+		printf("Fail: input txd (%u) can't be greater "
+		       "than max_txds (%u) of port %u\n",
+		       txd,
+		       allowed_max_txd,
+		       pid);
+		return -1;
+	}
+
+	allowed_min_txd = get_allowed_min_nb_txd(&pid);
+	if (txd < allowed_min_txd) {
+		printf("Fail: input txd (%u) can't be less "
+		       "than min_txds (%u) of port %u\n",
+		       txd,
+		       allowed_min_txd,
+		       pid);
+		return -1;
+	}
+	return 0;
+}
+
+
 /*
  * Get the allowed maximum number of hairpin queues.
  * *pid return the port id which has minimal value of
@@ -1166,6 +1340,11 @@ init_config(void)
 			rte_exit(EXIT_FAILURE,
 				 "rte_eth_dev_info_get() failed\n");
 
+		ret = update_jumbo_frame_offload(pid);
+		if (ret != 0)
+			printf("Updating jumbo frame offload failed for port %u\n",
+				pid);
+
 		if (!(port->dev_info.tx_offload_capa &
 		      DEV_TX_OFFLOAD_MBUF_FAST_FREE))
 			port->dev_conf.txmode.offloads &=
@@ -1430,9 +1609,9 @@ init_fwd_streams(void)
 static void
 pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
 {
-	unsigned int total_burst;
-	unsigned int nb_burst;
-	unsigned int burst_stats[3];
+	uint64_t total_burst;
+	uint64_t nb_burst;
+	uint64_t burst_stats[3];
 	uint16_t pktnb_stats[3];
 	uint16_t nb_pkt;
 	int burst_percent[3];
@@ -1461,8 +1640,8 @@ pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
 	}
 	if (total_burst == 0)
 		return;
-	burst_percent[0] = (burst_stats[0] * 100) / total_burst;
-	printf("  %s-bursts : %u [%d%% of %d pkts", rx_tx, total_burst,
+	burst_percent[0] = (double)burst_stats[0] / total_burst * 100;
+	printf("  %s-bursts : %"PRIu64" [%d%% of %d pkts", rx_tx, total_burst,
 	       burst_percent[0], (int) pktnb_stats[0]);
 	if (burst_stats[0] == total_burst) {
 		printf("]\n");
@@ -1473,7 +1652,7 @@ pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
 		       100 - burst_percent[0], pktnb_stats[1]);
 		return;
 	}
-	burst_percent[1] = (burst_stats[1] * 100) / total_burst;
+	burst_percent[1] = (double)burst_stats[1] / total_burst * 100;
 	burst_percent[2] = 100 - (burst_percent[0] + burst_percent[1]);
 	if ((burst_percent[1] == 0) || (burst_percent[2] == 0)) {
 		printf(" + %d%% of others]\n", 100 - burst_percent[0]);
@@ -1698,11 +1877,22 @@ fwd_stats_display(void)
 	       "%s\n",
 	       acc_stats_border, acc_stats_border);
 #ifdef RTE_TEST_PMD_RECORD_CORE_CYCLES
-	if (total_recv > 0)
-		printf("\n  CPU cycles/packet=%u (total cycles="
-		       "%"PRIu64" / total RX packets=%"PRIu64")\n",
-		       (unsigned int)(fwd_cycles / total_recv),
-		       fwd_cycles, total_recv);
+#define CYC_PER_MHZ 1E6
+	if (total_recv > 0 || total_xmit > 0) {
+		uint64_t total_pkts = 0;
+		if (strcmp(cur_fwd_eng->fwd_mode_name, "txonly") == 0 ||
+		    strcmp(cur_fwd_eng->fwd_mode_name, "flowgen") == 0)
+			total_pkts = total_xmit;
+		else
+			total_pkts = total_recv;
+
+		printf("\n  CPU cycles/packet=%.2F (total cycles="
+		       "%"PRIu64" / total %s packets=%"PRIu64") at %"PRIu64
+		       " MHz Clock\n",
+		       (double) fwd_cycles / total_pkts,
+		       fwd_cycles, cur_fwd_eng->fwd_mode_name, total_pkts,
+		       (uint64_t)(rte_get_tsc_hz() / CYC_PER_MHZ));
+	}
 #endif
 }
 
@@ -2549,32 +2739,17 @@ setup_attached_port(portid_t pi)
 	printf("Done\n");
 }
 
-void
-detach_port_device(portid_t port_id)
+static void
+detach_device(struct rte_device *dev)
 {
-	struct rte_device *dev;
 	portid_t sibling;
 
-	printf("Removing a device...\n");
-
-	if (port_id_is_invalid(port_id, ENABLED_WARN))
-		return;
-
-	dev = rte_eth_devices[port_id].device;
 	if (dev == NULL) {
 		printf("Device already removed\n");
 		return;
 	}
 
-	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
-		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
-			printf("Port not stopped\n");
-			return;
-		}
-		printf("Port was not closed\n");
-		if (ports[port_id].flow_list)
-			port_flow_flush(port_id);
-	}
+	printf("Removing a device...\n");
 
 	if (rte_dev_remove(dev) < 0) {
 		TESTPMD_LOG(ERR, "Failed to detach device %s\n", dev->name);
@@ -2592,14 +2767,33 @@ detach_port_device(portid_t port_id)
 
 	remove_invalid_ports();
 
-	printf("Device of port %u is detached\n", port_id);
+	printf("Device is detached\n");
 	printf("Now total ports is %d\n", nb_ports);
 	printf("Done\n");
 	return;
 }
 
 void
-detach_device(char *identifier)
+detach_port_device(portid_t port_id)
+{
+	if (port_id_is_invalid(port_id, ENABLED_WARN))
+		return;
+
+	if (ports[port_id].port_status != RTE_PORT_CLOSED) {
+		if (ports[port_id].port_status != RTE_PORT_STOPPED) {
+			printf("Port not stopped\n");
+			return;
+		}
+		printf("Port was not closed\n");
+		if (ports[port_id].flow_list)
+			port_flow_flush(port_id);
+	}
+
+	detach_device(rte_eth_devices[port_id].device);
+}
+
+void
+detach_devargs(char *identifier)
 {
 	struct rte_dev_iterator iterator;
 	struct rte_devargs da;
@@ -2748,7 +2942,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. speed %u Mbps- %s\n",
 					portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
@@ -2790,6 +2984,7 @@ rmv_port_callback(void *arg)
 	int need_to_start = 0;
 	int org_no_link_check = no_link_check;
 	portid_t port_id = (intptr_t)arg;
+	struct rte_device *dev;
 
 	RTE_ETH_VALID_PORTID_OR_RET(port_id);
 
@@ -2800,8 +2995,12 @@ rmv_port_callback(void *arg)
 	no_link_check = 1;
 	stop_port(port_id);
 	no_link_check = org_no_link_check;
+
+	/* Save rte_device pointer before closing ethdev port */
+	dev = rte_eth_devices[port_id].device;
 	close_port(port_id);
-	detach_port_device(port_id);
+	detach_device(dev); /* might be already removed or have more ports */
+
 	if (need_to_start)
 		start_packet_forwarding(0);
 }
@@ -3049,6 +3248,80 @@ rxtx_port_config(struct rte_port *port)
 	}
 }
 
+/*
+ * Helper function to arrange max_rx_pktlen value and JUMBO_FRAME offload,
+ * MTU is also aligned if JUMBO_FRAME offload is not set.
+ *
+ * port->dev_info should be set before calling this function.
+ *
+ * return 0 on success, negative on error
+ */
+int
+update_jumbo_frame_offload(portid_t portid)
+{
+	struct rte_port *port = &ports[portid];
+	uint32_t eth_overhead;
+	uint64_t rx_offloads;
+	int ret;
+	bool on;
+
+	/* Update the max_rx_pkt_len to have MTU as RTE_ETHER_MTU */
+	if (port->dev_info.max_mtu != UINT16_MAX &&
+	    port->dev_info.max_rx_pktlen > port->dev_info.max_mtu)
+		eth_overhead = port->dev_info.max_rx_pktlen -
+				port->dev_info.max_mtu;
+	else
+		eth_overhead = RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
+
+	rx_offloads = port->dev_conf.rxmode.offloads;
+
+	/* Default config value is 0 to use PMD specific overhead */
+	if (port->dev_conf.rxmode.max_rx_pkt_len == 0)
+		port->dev_conf.rxmode.max_rx_pkt_len = RTE_ETHER_MTU + eth_overhead;
+
+	if (port->dev_conf.rxmode.max_rx_pkt_len <= RTE_ETHER_MTU + eth_overhead) {
+		rx_offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
+		on = false;
+	} else {
+		if ((port->dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) == 0) {
+			printf("Frame size (%u) is not supported by port %u\n",
+				port->dev_conf.rxmode.max_rx_pkt_len,
+				portid);
+			return -1;
+		}
+		rx_offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
+		on = true;
+	}
+
+	if (rx_offloads != port->dev_conf.rxmode.offloads) {
+		uint16_t qid;
+
+		port->dev_conf.rxmode.offloads = rx_offloads;
+
+		/* Apply JUMBO_FRAME offload configuration to Rx queue(s) */
+		for (qid = 0; qid < port->dev_info.nb_rx_queues; qid++) {
+			if (on)
+				port->rx_conf[qid].offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
+			else
+				port->rx_conf[qid].offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
+		}
+	}
+
+	/* If JUMBO_FRAME is set MTU conversion done by ethdev layer,
+	 * if unset do it here
+	 */
+	if ((rx_offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) == 0) {
+		ret = rte_eth_dev_set_mtu(portid,
+				port->dev_conf.rxmode.max_rx_pkt_len - eth_overhead);
+		if (ret)
+			printf("Failed to set MTU to %u for port %u\n",
+				port->dev_conf.rxmode.max_rx_pkt_len - eth_overhead,
+				portid);
+	}
+
+	return 0;
+}
+
 void
 init_port_config(void)
 {
@@ -3184,6 +3457,8 @@ get_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf,
 		struct rte_eth_dcb_tx_conf *tx_conf =
 				&eth_conf->tx_adv_conf.dcb_tx_conf;
 
+		memset(&rss_conf, 0, sizeof(struct rte_eth_rss_conf));
+
 		rc = rte_eth_dev_rss_hash_conf_get(pid, &rss_conf);
 		if (rc != 0)
 			return rc;
@@ -3570,5 +3845,10 @@ main(int argc, char** argv)
 			return 1;
 	}
 
-	return 0;
+	ret = rte_eal_cleanup();
+	if (ret != 0)
+		rte_exit(EXIT_FAILURE,
+			 "EAL cleanup failed: %s\n", strerror(-ret));
+
+	return EXIT_SUCCESS;
 }
diff --git a/dpdk/app/test-pmd/testpmd.h b/dpdk/app/test-pmd/testpmd.h
index 217d577018..4dbcee3a62 100644
--- a/dpdk/app/test-pmd/testpmd.h
+++ b/dpdk/app/test-pmd/testpmd.h
@@ -797,7 +797,7 @@ void stop_port(portid_t pid);
 void close_port(portid_t pid);
 void reset_port(portid_t pid);
 void attach_port(char *identifier);
-void detach_device(char *identifier);
+void detach_devargs(char *identifier);
 void detach_port_device(portid_t port_id);
 int all_ports_stopped(void);
 int port_is_stopped(portid_t port_id);
@@ -859,6 +859,8 @@ queueid_t get_allowed_max_nb_rxq(portid_t *pid);
 int check_nb_rxq(queueid_t rxq);
 queueid_t get_allowed_max_nb_txq(portid_t *pid);
 int check_nb_txq(queueid_t txq);
+int check_nb_rxd(queueid_t rxd);
+int check_nb_txd(queueid_t txd);
 queueid_t get_allowed_max_nb_hairpinq(portid_t *pid);
 int check_nb_hairpinq(queueid_t hairpinq);
 
@@ -881,6 +883,8 @@ uint16_t tx_pkt_set_md(uint16_t port_id, __rte_unused uint16_t queue,
 void add_tx_md_callback(portid_t portid);
 void remove_tx_md_callback(portid_t portid);
 
+int update_jumbo_frame_offload(portid_t portid);
+
 /*
  * Work-around of a compilation error with ICC on invocations of the
  * rte_be_to_cpu_16() function.
diff --git a/dpdk/app/test-pmd/txonly.c b/dpdk/app/test-pmd/txonly.c
index 3caf281cb8..a1822c631d 100644
--- a/dpdk/app/test-pmd/txonly.c
+++ b/dpdk/app/test-pmd/txonly.c
@@ -45,8 +45,8 @@ uint16_t tx_udp_src_port = 9;
 uint16_t tx_udp_dst_port = 9;
 
 /* use RFC5735 / RFC2544 reserved network test addresses */
-uint32_t tx_ip_src_addr = (192U << 24) | (18 << 16) | (0 << 8) | 1;
-uint32_t tx_ip_dst_addr = (192U << 24) | (18 << 16) | (0 << 8) | 2;
+uint32_t tx_ip_src_addr = (198U << 24) | (18 << 16) | (0 << 8) | 1;
+uint32_t tx_ip_dst_addr = (198U << 24) | (18 << 16) | (0 << 8) | 2;
 
 #define IP_DEFTTL  64   /* from RFC 1340. */
 
@@ -147,13 +147,40 @@ setup_pkt_udp_ip_headers(struct rte_ipv4_hdr *ip_hdr,
 	ip_hdr->hdr_checksum = (uint16_t) ip_cksum;
 }
 
+static inline void
+update_pkt_header(struct rte_mbuf *pkt, uint32_t total_pkt_len)
+{
+	struct rte_ipv4_hdr *ip_hdr;
+	struct rte_udp_hdr *udp_hdr;
+	uint16_t pkt_data_len;
+	uint16_t pkt_len;
+
+	pkt_data_len = (uint16_t) (total_pkt_len - (
+					sizeof(struct rte_ether_hdr) +
+					sizeof(struct rte_ipv4_hdr) +
+					sizeof(struct rte_udp_hdr)));
+	/* updata udp pkt length */
+	udp_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_udp_hdr *,
+				sizeof(struct rte_ether_hdr) +
+				sizeof(struct rte_ipv4_hdr));
+	pkt_len = (uint16_t) (pkt_data_len + sizeof(struct rte_udp_hdr));
+	udp_hdr->dgram_len = RTE_CPU_TO_BE_16(pkt_len);
+
+	/* updata ip pkt length and csum */
+	ip_hdr = rte_pktmbuf_mtod_offset(pkt, struct rte_ipv4_hdr *,
+				sizeof(struct rte_ether_hdr));
+	ip_hdr->hdr_checksum = 0;
+	pkt_len = (uint16_t) (pkt_len + sizeof(struct rte_ipv4_hdr));
+	ip_hdr->total_length = RTE_CPU_TO_BE_16(pkt_len);
+	ip_hdr->hdr_checksum = rte_ipv4_cksum(ip_hdr);
+}
+
 static inline bool
 pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
 		struct rte_ether_hdr *eth_hdr, const uint16_t vlan_tci,
 		const uint16_t vlan_tci_outer, const uint64_t ol_flags)
 {
 	struct rte_mbuf *pkt_segs[RTE_MAX_SEGS_PER_PKT];
-	uint8_t  ip_var = RTE_PER_LCORE(_ip_var);
 	struct rte_mbuf *pkt_seg;
 	uint32_t nb_segs, pkt_len;
 	uint8_t i;
@@ -192,6 +219,7 @@ pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
 	copy_buf_to_pkt(&pkt_ip_hdr, sizeof(pkt_ip_hdr), pkt,
 			sizeof(struct rte_ether_hdr));
 	if (txonly_multi_flow) {
+		uint8_t  ip_var = RTE_PER_LCORE(_ip_var);
 		struct rte_ipv4_hdr *ip_hdr;
 		uint32_t addr;
 
@@ -207,10 +235,15 @@ pkt_burst_prepare(struct rte_mbuf *pkt, struct rte_mempool *mbp,
 		 */
 		addr = (tx_ip_dst_addr | (ip_var++ << 8)) + rte_lcore_id();
 		ip_hdr->src_addr = rte_cpu_to_be_32(addr);
+		RTE_PER_LCORE(_ip_var) = ip_var;
 	}
 	copy_buf_to_pkt(&pkt_udp_hdr, sizeof(pkt_udp_hdr), pkt,
 			sizeof(struct rte_ether_hdr) +
 			sizeof(struct rte_ipv4_hdr));
+
+	if (unlikely(tx_pkt_split == TX_PKT_SPLIT_RND) || txonly_multi_flow)
+		update_pkt_header(pkt, pkt_len);
+
 	/*
 	 * Complete first mbuf of packet and append it to the
 	 * burst of packets to be transmitted.
@@ -314,7 +347,7 @@ pkt_burst_transmit(struct fwd_stream *fs)
 	fs->tx_packets += nb_tx;
 
 	if (txonly_multi_flow)
-		RTE_PER_LCORE(_ip_var) += nb_tx;
+		RTE_PER_LCORE(_ip_var) -= nb_pkt - nb_tx;
 
 #ifdef RTE_TEST_PMD_RECORD_BURST_STATS
 	fs->tx_burst_stats.pkt_burst_spread[nb_tx]++;
diff --git a/dpdk/app/test-pmd/util.c b/dpdk/app/test-pmd/util.c
index b514be5e16..487260d59d 100644
--- a/dpdk/app/test-pmd/util.c
+++ b/dpdk/app/test-pmd/util.c
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2010-2014 Intel Corporation
- * Copyright(c) 2018 Mellanox Technology
+ * Copyright 2018 Mellanox Technologies, Ltd
  */
 
 #include <stdio.h>
@@ -14,12 +14,23 @@
 
 #include "testpmd.h"
 
+#define MAX_STRING_LEN 8192
+
+#define MKDUMPSTR(buf, buf_size, cur_len, ...) \
+do { \
+	if (cur_len >= buf_size) \
+		break; \
+	cur_len += snprintf(buf + cur_len, buf_size - cur_len, __VA_ARGS__); \
+} while (0)
+
 static inline void
-print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr)
+print_ether_addr(const char *what, const struct rte_ether_addr *eth_addr,
+		 char print_buf[], size_t buf_size, size_t *cur_len)
 {
 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
+
 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
-	printf("%s%s", what, buf);
+	MKDUMPSTR(print_buf, buf_size, *cur_len, "%s%s", what, buf);
 }
 
 static inline void
@@ -39,13 +50,15 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
 	uint16_t udp_port;
 	uint32_t vx_vni;
 	const char *reason;
+	char print_buf[MAX_STRING_LEN];
+	size_t buf_size = MAX_STRING_LEN;
+	size_t cur_len = 0;
 
 	if (!nb_pkts)
 		return;
-	printf("port %u/queue %u: %s %u packets\n",
-		port_id, queue,
-	       is_rx ? "received" : "sent",
-	       (unsigned int) nb_pkts);
+	MKDUMPSTR(print_buf, buf_size, cur_len,
+		  "port %u/queue %u: %s %u packets\n", port_id, queue,
+		  is_rx ? "received" : "sent", (unsigned int) nb_pkts);
 	for (i = 0; i < nb_pkts; i++) {
 		mb = pkts[i];
 		eth_hdr = rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr), &_eth_hdr);
@@ -54,62 +67,84 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
 		packet_type = mb->packet_type;
 		is_encapsulation = RTE_ETH_IS_TUNNEL_PKT(packet_type);
 
-		print_ether_addr("  src=", &eth_hdr->s_addr);
-		print_ether_addr(" - dst=", &eth_hdr->d_addr);
-		printf(" - type=0x%04x - length=%u - nb_segs=%d",
-		       eth_type, (unsigned int) mb->pkt_len,
-		       (int)mb->nb_segs);
+		print_ether_addr("  src=", &eth_hdr->s_addr,
+				 print_buf, buf_size, &cur_len);
+		print_ether_addr(" - dst=", &eth_hdr->d_addr,
+				 print_buf, buf_size, &cur_len);
+		MKDUMPSTR(print_buf, buf_size, cur_len,
+			  " - type=0x%04x - length=%u - nb_segs=%d",
+			  eth_type, (unsigned int) mb->pkt_len,
+			  (int)mb->nb_segs);
 		if (ol_flags & PKT_RX_RSS_HASH) {
-			printf(" - RSS hash=0x%x", (unsigned int) mb->hash.rss);
-			printf(" - RSS queue=0x%x", (unsigned int) queue);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - RSS hash=0x%x",
+				  (unsigned int) mb->hash.rss);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - RSS queue=0x%x", (unsigned int) queue);
 		}
 		if (ol_flags & PKT_RX_FDIR) {
-			printf(" - FDIR matched ");
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - FDIR matched ");
 			if (ol_flags & PKT_RX_FDIR_ID)
-				printf("ID=0x%x",
-				       mb->hash.fdir.hi);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  "ID=0x%x", mb->hash.fdir.hi);
 			else if (ol_flags & PKT_RX_FDIR_FLX)
-				printf("flex bytes=0x%08x %08x",
-				       mb->hash.fdir.hi, mb->hash.fdir.lo);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  "flex bytes=0x%08x %08x",
+					  mb->hash.fdir.hi, mb->hash.fdir.lo);
 			else
-				printf("hash=0x%x ID=0x%x ",
-				       mb->hash.fdir.hash, mb->hash.fdir.id);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  "hash=0x%x ID=0x%x ",
+					  mb->hash.fdir.hash, mb->hash.fdir.id);
 		}
 		if (ol_flags & PKT_RX_TIMESTAMP)
-			printf(" - timestamp %"PRIu64" ", mb->timestamp);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - timestamp %"PRIu64" ", mb->timestamp);
 		if (ol_flags & PKT_RX_QINQ)
-			printf(" - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
-			       mb->vlan_tci, mb->vlan_tci_outer);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - QinQ VLAN tci=0x%x, VLAN tci outer=0x%x",
+				  mb->vlan_tci, mb->vlan_tci_outer);
 		else if (ol_flags & PKT_RX_VLAN)
-			printf(" - VLAN tci=0x%x", mb->vlan_tci);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - VLAN tci=0x%x", mb->vlan_tci);
 		if (!is_rx && (ol_flags & PKT_TX_DYNF_METADATA))
-			printf(" - Tx metadata: 0x%x",
-			       *RTE_FLOW_DYNF_METADATA(mb));
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - Tx metadata: 0x%x",
+				  *RTE_FLOW_DYNF_METADATA(mb));
 		if (is_rx && (ol_flags & PKT_RX_DYNF_METADATA))
-			printf(" - Rx metadata: 0x%x",
-			       *RTE_FLOW_DYNF_METADATA(mb));
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - Rx metadata: 0x%x",
+				  *RTE_FLOW_DYNF_METADATA(mb));
 		if (mb->packet_type) {
 			rte_get_ptype_name(mb->packet_type, buf, sizeof(buf));
-			printf(" - hw ptype: %s", buf);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - hw ptype: %s", buf);
 		}
 		sw_packet_type = rte_net_get_ptype(mb, &hdr_lens,
 					RTE_PTYPE_ALL_MASK);
 		rte_get_ptype_name(sw_packet_type, buf, sizeof(buf));
-		printf(" - sw ptype: %s", buf);
+		MKDUMPSTR(print_buf, buf_size, cur_len, " - sw ptype: %s", buf);
 		if (sw_packet_type & RTE_PTYPE_L2_MASK)
-			printf(" - l2_len=%d", hdr_lens.l2_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len, " - l2_len=%d",
+				  hdr_lens.l2_len);
 		if (sw_packet_type & RTE_PTYPE_L3_MASK)
-			printf(" - l3_len=%d", hdr_lens.l3_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len, " - l3_len=%d",
+				  hdr_lens.l3_len);
 		if (sw_packet_type & RTE_PTYPE_L4_MASK)
-			printf(" - l4_len=%d", hdr_lens.l4_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len, " - l4_len=%d",
+				  hdr_lens.l4_len);
 		if (sw_packet_type & RTE_PTYPE_TUNNEL_MASK)
-			printf(" - tunnel_len=%d", hdr_lens.tunnel_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - tunnel_len=%d", hdr_lens.tunnel_len);
 		if (sw_packet_type & RTE_PTYPE_INNER_L2_MASK)
-			printf(" - inner_l2_len=%d", hdr_lens.inner_l2_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - inner_l2_len=%d", hdr_lens.inner_l2_len);
 		if (sw_packet_type & RTE_PTYPE_INNER_L3_MASK)
-			printf(" - inner_l3_len=%d", hdr_lens.inner_l3_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - inner_l3_len=%d", hdr_lens.inner_l3_len);
 		if (sw_packet_type & RTE_PTYPE_INNER_L4_MASK)
-			printf(" - inner_l4_len=%d", hdr_lens.inner_l4_len);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  " - inner_l4_len=%d", hdr_lens.inner_l4_len);
 		if (is_encapsulation) {
 			struct rte_ipv4_hdr *ipv4_hdr;
 			struct rte_ipv6_hdr *ipv6_hdr;
@@ -146,18 +181,27 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue, struct rte_mbuf *pkts[],
 				l2_len + l3_len + l4_len);
 				udp_port = RTE_BE_TO_CPU_16(udp_hdr->dst_port);
 				vx_vni = rte_be_to_cpu_32(vxlan_hdr->vx_vni);
-				printf(" - VXLAN packet: packet type =%d, "
-				       "Destination UDP port =%d, VNI = %d",
-				       packet_type, udp_port, vx_vni >> 8);
+				MKDUMPSTR(print_buf, buf_size, cur_len,
+					  " - VXLAN packet: packet type =%d, "
+					  "Destination UDP port =%d, VNI = %d",
+					  packet_type, udp_port, vx_vni >> 8);
 			}
 		}
-		printf(" - %s queue=0x%x", is_rx ? "Receive" : "Send",
-			(unsigned int) queue);
-		printf("\n");
+		MKDUMPSTR(print_buf, buf_size, cur_len,
+			  " - %s queue=0x%x", is_rx ? "Receive" : "Send",
+			  (unsigned int) queue);
+		MKDUMPSTR(print_buf, buf_size, cur_len, "\n");
 		rte_get_rx_ol_flag_list(mb->ol_flags, buf, sizeof(buf));
-		printf("  ol_flags: %s\n", buf);
+		MKDUMPSTR(print_buf, buf_size, cur_len,
+			  "  ol_flags: %s\n", buf);
 		if (rte_mbuf_check(mb, 1, &reason) < 0)
-			printf("INVALID mbuf: %s\n", reason);
+			MKDUMPSTR(print_buf, buf_size, cur_len,
+				  "INVALID mbuf: %s\n", reason);
+		if (cur_len >= buf_size)
+			printf("%s ...\n", print_buf);
+		else
+			printf("%s", print_buf);
+		cur_len = 0;
 	}
 }
 
diff --git a/dpdk/app/test-sad/main.c b/dpdk/app/test-sad/main.c
index b01e84c570..8380fad744 100644
--- a/dpdk/app/test-sad/main.c
+++ b/dpdk/app/test-sad/main.c
@@ -617,7 +617,7 @@ main(int argc, char **argv)
 {
 	int ret;
 	struct rte_ipsec_sad *sad;
-	struct rte_ipsec_sad_conf conf;
+	struct rte_ipsec_sad_conf conf = {0};
 	unsigned int lcore_id;
 
 	ret = rte_eal_init(argc, argv);
diff --git a/dpdk/app/test/Makefile b/dpdk/app/test/Makefile
index 57930c00b1..30eff33206 100644
--- a/dpdk/app/test/Makefile
+++ b/dpdk/app/test/Makefile
@@ -122,7 +122,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_multiwriter.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite.c
-SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite_lf.c
+SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_readwrite_lf_perf.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_RIB) += test_rib.c
 SRCS-$(CONFIG_RTE_LIBRTE_RIB) += test_rib6.c
@@ -151,8 +151,12 @@ SRCS-y += test_func_reentrancy.c
 
 SRCS-y += test_service_cores.c
 
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
+SRCS-y += sample_packet_forward.c
 SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) += test_bitratestats.c
 SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += test_latencystats.c
+SRCS-$(CONFIG_RTE_LIBRTE_PDUMP) += test_pdump.c
+endif
 
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline.c
 SRCS-$(CONFIG_RTE_LIBRTE_CMDLINE) += test_cmdline_num.c
@@ -181,11 +185,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_DISTRIBUTOR) += test_distributor_perf.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_REORDER) += test_reorder.c
 
-SRCS-$(CONFIG_RTE_LIBRTE_PDUMP) += test_pdump.c
-
 SRCS-y += virtual_pmd.c
 SRCS-y += packet_burst_generator.c
-SRCS-y += sample_packet_forward.c
 SRCS-$(CONFIG_RTE_LIBRTE_ACL) += test_acl.c
 
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
@@ -215,7 +216,7 @@ ifeq ($(CONFIG_RTE_LIBRTE_EVENTDEV),y)
 SRCS-y += test_eventdev.c
 SRCS-y += test_event_ring.c
 SRCS-y += test_event_eth_rx_adapter.c
-SRCS-y += test_event_eth_tx_adapter.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_RING) += test_event_eth_tx_adapter.c
 SRCS-y += test_event_timer_adapter.c
 SRCS-y += test_event_crypto_adapter.c
 endif
@@ -268,13 +269,6 @@ endif
 endif
 endif
 
-# Link against shared libraries when needed
-ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
-ifneq ($(CONFIG_RTE_LIBRTE_PMD_RING),y)
-$(error Link bonding tests require CONFIG_RTE_LIBRTE_PMD_RING=y)
-endif
-endif
-
 ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
 
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_BOND),y)
diff --git a/dpdk/app/test/autotest_data.py b/dpdk/app/test/autotest_data.py
index 6deb97bcc1..ca29b09f31 100644
--- a/dpdk/app/test/autotest_data.py
+++ b/dpdk/app/test/autotest_data.py
@@ -670,8 +670,8 @@
         "Report":  None,
     },
     {
-        "Name":    "Hash read-write lock-free concurrency autotest",
-        "Command": "hash_readwrite_lf_autotest",
+        "Name":    "Hash read-write lock-free concurrency perf autotest",
+        "Command": "hash_readwrite_lf_perf_autotest",
         "Func":    default_autotest,
         "Report":  None,
     },
diff --git a/dpdk/app/test/get-coremask.sh b/dpdk/app/test/get-coremask.sh
new file mode 100755
index 0000000000..bb8cf404d2
--- /dev/null
+++ b/dpdk/app/test/get-coremask.sh
@@ -0,0 +1,13 @@
+#! /bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+
+if [ "$(uname)" = "Linux" ] ; then
+	cat /sys/devices/system/cpu/present
+elif [ "$(uname)" = "FreeBSD" ] ; then
+	ncpus=$(/sbin/sysctl -n hw.ncpu)
+	echo 0-$(expr $ncpus - 1)
+else
+# fallback
+	echo 0-3
+fi
diff --git a/dpdk/app/test/meson.build b/dpdk/app/test/meson.build
index fb49d804ba..24fb59f74f 100644
--- a/dpdk/app/test/meson.build
+++ b/dpdk/app/test/meson.build
@@ -7,13 +7,11 @@ endif
 
 test_sources = files('commands.c',
 	'packet_burst_generator.c',
-	'sample_packet_forward.c',
 	'test.c',
 	'test_acl.c',
 	'test_alarm.c',
 	'test_atomic.c',
 	'test_barrier.c',
-	'test_bitratestats.c',
 	'test_bpf.c',
 	'test_byteorder.c',
 	'test_cmdline.c',
@@ -43,7 +41,6 @@ test_sources = files('commands.c',
 	'test_event_crypto_adapter.c',
 	'test_event_eth_rx_adapter.c',
 	'test_event_ring.c',
-	'test_event_eth_tx_adapter.c',
 	'test_event_timer_adapter.c',
 	'test_eventdev.c',
 	'test_external_mem.c',
@@ -59,15 +56,13 @@ test_sources = files('commands.c',
 	'test_hash_multiwriter.c',
 	'test_hash_readwrite.c',
 	'test_hash_perf.c',
-	'test_hash_readwrite_lf.c',
+	'test_hash_readwrite_lf_perf.c',
 	'test_interrupts.c',
 	'test_ipsec.c',
 	'test_ipsec_sad.c',
 	'test_kni.c',
 	'test_kvargs.c',
-	'test_latencystats.c',
 	'test_link_bonding.c',
-	'test_link_bonding_mode4.c',
 	'test_link_bonding_rssconf.c',
 	'test_logs.c',
 	'test_lpm.c',
@@ -88,11 +83,8 @@ test_sources = files('commands.c',
 	'test_metrics.c',
 	'test_mcslock.c',
 	'test_mp_secondary.c',
-	'test_pdump.c',
 	'test_per_lcore.c',
 	'test_pmd_perf.c',
-	'test_pmd_ring.c',
-	'test_pmd_ring_perf.c',
 	'test_power.c',
 	'test_power_cpufreq.c',
 	'test_power_kvm_vm.c',
@@ -162,92 +154,89 @@ test_deps = ['acl',
 	'timer'
 ]
 
-fast_test_names = [
-        'acl_autotest',
-        'alarm_autotest',
-        'atomic_autotest',
-        'byteorder_autotest',
-        'cmdline_autotest',
-        'common_autotest',
-        'cpuflags_autotest',
-        'cycles_autotest',
-        'debug_autotest',
-        'eal_flags_c_opt_autotest',
-        'eal_flags_master_opt_autotest',
-        'eal_flags_n_opt_autotest',
-        'eal_flags_hpet_autotest',
-        'eal_flags_no_huge_autotest',
-        'eal_flags_w_opt_autotest',
-        'eal_flags_b_opt_autotest',
-        'eal_flags_vdev_opt_autotest',
-        'eal_flags_r_opt_autotest',
-        'eal_flags_mem_autotest',
-        'eal_flags_file_prefix_autotest',
-        'eal_flags_misc_autotest',
-        'eal_fs_autotest',
-        'errno_autotest',
-        'event_ring_autotest',
-        'fib_autotest',
-        'fib6_autotest',
-        'func_reentrancy_autotest',
-        'flow_classify_autotest',
-        'hash_autotest',
-        'interrupt_autotest',
-        'logs_autotest',
-        'lpm_autotest',
-        'lpm6_autotest',
-        'malloc_autotest',
-        'mbuf_autotest',
-        'mcslock_autotest',
-        'memcpy_autotest',
-        'memory_autotest',
-        'mempool_autotest',
-        'memzone_autotest',
-        'meter_autotest',
-        'multiprocess_autotest',
-        'per_lcore_autotest',
-        'prefetch_autotest',
-        'rcu_qsbr_autotest',
-        'red_autotest',
-        'rib_autotest',
-        'rib6_autotest',
-        'ring_autotest',
-        'ring_pmd_autotest',
-        'rwlock_test1_autotest',
-        'rwlock_rda_autotest',
-        'rwlock_rds_wrm_autotest',
-        'rwlock_rde_wro_autotest',
-        'sched_autotest',
-        'spinlock_autotest',
-        'stack_autotest',
-        'stack_lf_autotest',
-        'string_autotest',
-        'table_autotest',
-        'tailq_autotest',
-        'timer_autotest',
-        'user_delay_us',
-        'version_autotest',
-        'bitratestats_autotest',
-        'crc_autotest',
-        'delay_us_sleep_autotest',
-        'distributor_autotest',
-        'eventdev_common_autotest',
-        'fbarray_autotest',
-        'hash_readwrite_autotest',
-        'hash_readwrite_lf_autotest',
-        'ipsec_autotest',
-        'kni_autotest',
-        'kvargs_autotest',
-        'latencystats_autotest',
-        'member_autotest',
-        'metrics_autotest',
-        'pdump_autotest',
-        'power_cpufreq_autotest',
-        'power_autotest',
-        'power_kvm_vm_autotest',
-        'reorder_autotest',
-        'service_autotest',
-        'thash_autotest',
+# Each test is marked with flag true/false
+# to indicate whether it can run in no-huge mode.
+fast_tests = [
+        ['acl_autotest', true],
+        ['alarm_autotest', false],
+        ['atomic_autotest', false],
+        ['byteorder_autotest', true],
+        ['cmdline_autotest', true],
+        ['common_autotest', true],
+        ['cpuflags_autotest', true],
+        ['cycles_autotest', true],
+        ['debug_autotest', true],
+        ['eal_flags_c_opt_autotest', false],
+        ['eal_flags_master_opt_autotest', false],
+        ['eal_flags_n_opt_autotest', false],
+        ['eal_flags_hpet_autotest', false],
+        ['eal_flags_no_huge_autotest', false],
+        ['eal_flags_w_opt_autotest', false],
+        ['eal_flags_b_opt_autotest', false],
+        ['eal_flags_vdev_opt_autotest', false],
+        ['eal_flags_r_opt_autotest', false],
+        ['eal_flags_mem_autotest', false],
+        ['eal_flags_file_prefix_autotest', false],
+        ['eal_flags_misc_autotest', false],
+        ['eal_fs_autotest', true],
+        ['errno_autotest', true],
+        ['event_ring_autotest', true],
+        ['fib_autotest', true],
+        ['fib6_autotest', true],
+        ['func_reentrancy_autotest', false],
+        ['flow_classify_autotest', false],
+        ['hash_autotest', true],
+        ['interrupt_autotest', true],
+        ['logs_autotest', true],
+        ['lpm_autotest', true],
+        ['lpm6_autotest', true],
+        ['malloc_autotest', false],
+        ['mbuf_autotest', false],
+        ['mcslock_autotest', false],
+        ['memcpy_autotest', true],
+        ['memory_autotest', false],
+        ['mempool_autotest', false],
+        ['memzone_autotest', false],
+        ['meter_autotest', true],
+        ['multiprocess_autotest', false],
+        ['per_lcore_autotest', true],
+        ['prefetch_autotest', true],
+        ['rcu_qsbr_autotest', true],
+        ['red_autotest', true],
+        ['rib_autotest', true],
+        ['rib6_autotest', true],
+        ['ring_autotest', true],
+        ['rwlock_test1_autotest', true],
+        ['rwlock_rda_autotest', true],
+        ['rwlock_rds_wrm_autotest', true],
+        ['rwlock_rde_wro_autotest', true],
+        ['sched_autotest', true],
+        ['spinlock_autotest', true],
+        ['stack_autotest', false],
+        ['stack_lf_autotest', false],
+        ['string_autotest', true],
+        ['table_autotest', true],
+        ['tailq_autotest', true],
+        ['timer_autotest', false],
+        ['user_delay_us', true],
+        ['version_autotest', true],
+        ['crc_autotest', true],
+        ['delay_us_sleep_autotest', true],
+        ['distributor_autotest', false],
+        ['eventdev_common_autotest', true],
+        ['fbarray_autotest', true],
+        ['hash_readwrite_autotest', false],
+        ['ipsec_autotest', true],
+        ['kni_autotest', false],
+        ['kvargs_autotest', true],
+        ['member_autotest', true],
+        ['metrics_autotest', true],
+        ['power_cpufreq_autotest', false],
+        ['power_autotest', true],
+        ['power_kvm_vm_autotest', false],
+        ['reorder_autotest', true],
+        ['service_autotest', true],
+        ['thash_autotest', true],
 ]
 
 perf_test_names = [
@@ -277,11 +266,11 @@ perf_test_names = [
         'rcu_qsbr_perf_autotest',
         'red_perf',
         'distributor_perf_autotest',
-        'ring_pmd_perf_autotest',
         'pmd_perf_autotest',
         'stack_perf_autotest',
         'stack_lf_perf_autotest',
         'rand_perf_autotest',
+        'hash_readwrite_lf_perf_autotest',
 ]
 
 driver_test_names = [
@@ -302,7 +291,6 @@ driver_test_names = [
         'eventdev_selftest_octeontx',
         'eventdev_selftest_sw',
         'link_bonding_autotest',
-        'link_bonding_mode4_autotest',
         'link_bonding_rssconf_autotest',
         'rawdev_autotest',
 ]
@@ -336,9 +324,26 @@ endif
 # they are used via a driver-specific API.
 if dpdk_conf.has('RTE_LIBRTE_BOND_PMD')
 	test_deps += 'pmd_bond'
+	if dpdk_conf.has('RTE_LIBRTE_RING_PMD')
+		test_sources += 'test_link_bonding_mode4.c'
+		driver_test_names += 'link_bonding_mode4_autotest'
+	endif
 endif
 if dpdk_conf.has('RTE_LIBRTE_RING_PMD')
 	test_deps += 'pmd_ring'
+	test_sources += 'test_pmd_ring_perf.c'
+	test_sources += 'test_pmd_ring.c'
+	test_sources += 'test_event_eth_tx_adapter.c'
+	test_sources += 'test_bitratestats.c'
+	test_sources += 'test_latencystats.c'
+	test_sources += 'sample_packet_forward.c'
+	test_sources += 'test_pdump.c'
+	fast_tests += [['ring_pmd_autotest', true]]
+	perf_test_names += 'ring_pmd_perf_autotest'
+	fast_tests += [['event_eth_tx_adapter_autotest', false]]
+	fast_tests += [['bitratestats_autotest', true]]
+	fast_tests += [['latencystats_autotest', true]]
+	fast_tests += [['pdump_autotest', true]]
 endif
 
 if dpdk_conf.has('RTE_LIBRTE_POWER')
@@ -359,19 +364,23 @@ endif
 # specify -D_GNU_SOURCE unconditionally
 cflags += '-D_GNU_SOURCE'
 
+# Enable using internal APIs in unit tests
+cflags += ['-DALLOW_INTERNAL_API']
+
 test_dep_objs = []
 if dpdk_conf.has('RTE_LIBRTE_COMPRESSDEV')
-	compress_test_dep = dependency('zlib', required: false)
+	compress_test_dep = dependency('zlib', required: false, method: 'pkg-config')
 	if compress_test_dep.found()
 		test_dep_objs += compress_test_dep
 		test_sources += 'test_compressdev.c'
 		test_deps += 'compressdev'
-		fast_test_names += 'compressdev_autotest'
+		fast_tests += [['compressdev_autotest', false]]
 	endif
 endif
 
-if dpdk_conf.has('RTE_LIBRTE_PMD_CRYPTO_SCHEDULER')
+if dpdk_conf.has('RTE_LIBRTE_CRYPTO_SCHEDULER_PMD')
 	driver_test_names += 'cryptodev_scheduler_autotest'
+	test_deps += 'pmd_crypto_scheduler'
 endif
 
 foreach d:test_deps
@@ -382,7 +391,7 @@ test_dep_objs += cc.find_library('execinfo', required: false)
 
 link_libs = []
 if get_option('default_library') == 'static'
-	link_libs = dpdk_drivers
+	link_libs = dpdk_static_libraries + dpdk_drivers
 endif
 
 dpdk_test = executable('dpdk-test',
@@ -390,53 +399,66 @@ dpdk_test = executable('dpdk-test',
 	link_whole: link_libs,
 	dependencies: test_dep_objs,
 	c_args: [cflags, '-DALLOW_EXPERIMENTAL_API'],
-	install_rpath: driver_install_path,
+	install_rpath: join_paths(get_option('prefix'),
+			 driver_install_path),
 	install: true)
 
+has_hugepage = true
+if is_linux
+	check_hugepage = run_command('cat',
+				     '/proc/sys/vm/nr_hugepages')
+	if (check_hugepage.returncode() != 0 or
+	    check_hugepage.stdout().strip() == '0')
+		has_hugepage = false
+	endif
+endif
+message('hugepage availability: @0@'.format(has_hugepage))
+
 # some perf tests (eg: memcpy perf autotest)take very long
 # to complete, so timeout to 10 minutes
 timeout_seconds = 600
 timeout_seconds_fast = 10
 
-# Retrieve the number of CPU cores, defaulting to 4.
-num_cores = '0-3'
-if host_machine.system() == 'linux'
-	num_cores = run_command('cat',
-				'/sys/devices/system/cpu/present'
-			       ).stdout().strip()
-elif host_machine.system() == 'freebsd'
-	snum_cores = run_command('/sbin/sysctl', '-n',
-				 'hw.ncpu').stdout().strip()
-	inum_cores = snum_cores.to_int() - 1
-        num_cores = '0-@0@'.format(inum_cores)
-endif
+get_coremask = find_program('get-coremask.sh')
+num_cores_arg = '-l ' + run_command(get_coremask).stdout().strip()
 
-num_cores_arg = '-l ' + num_cores
+default_test_args = [num_cores_arg]
 
-test_args = [num_cores_arg]
-foreach arg : fast_test_names
-	if host_machine.system() == 'linux'
-		test(arg, dpdk_test,
-			  env : ['DPDK_TEST=' + arg],
-			  args : test_args +
-				 ['--file-prefix=@0@'.format(arg)],
-		timeout : timeout_seconds_fast,
-		is_parallel : false,
-		suite : 'fast-tests')
-	else
-		test(arg, dpdk_test,
-			env : ['DPDK_TEST=' + arg],
+foreach arg : fast_tests
+	test_args = default_test_args
+	run_test = true
+	if not has_hugepage
+		if arg[1]
+			test_args += ['--no-huge', '-m', '2048']
+		else
+			run_test = false
+		endif
+	endif
+
+	if (get_option('default_library') == 'shared' and
+		arg[0] == 'event_eth_tx_adapter_autotest')
+		foreach drv:dpdk_drivers
+			test_args += ['-d', drv.full_path().split('.a')[0] + '.so']
+		endforeach
+	endif
+	if is_linux
+		test_args += ['--file-prefix=@0@'.format(arg[0])]
+	endif
+
+	if run_test
+		test(arg[0], dpdk_test,
+			env : ['DPDK_TEST=' + arg[0]],
 			args : test_args,
-		timeout : timeout_seconds_fast,
-		is_parallel : false,
-		suite : 'fast-tests')
+			timeout : timeout_seconds_fast,
+			is_parallel : false,
+			suite : 'fast-tests')
 	endif
 endforeach
 
 foreach arg : perf_test_names
 	test(arg, dpdk_test,
 	env : ['DPDK_TEST=' + arg],
-	args : test_args,
+	args : default_test_args,
 	timeout : timeout_seconds,
 	is_parallel : false,
 	suite : 'perf-tests')
@@ -445,7 +467,7 @@ endforeach
 foreach arg : driver_test_names
 	test(arg, dpdk_test,
 		env : ['DPDK_TEST=' + arg],
-		args : test_args,
+		args : default_test_args,
 		timeout : timeout_seconds,
 		is_parallel : false,
 		suite : 'driver-tests')
@@ -454,7 +476,7 @@ endforeach
 foreach arg : dump_test_names
 	test(arg, dpdk_test,
 		env : ['DPDK_TEST=' + arg],
-		args : test_args,
+		args : default_test_args,
 		timeout : timeout_seconds,
 		is_parallel : false,
 		suite : 'debug-tests')
diff --git a/dpdk/app/test/process.h b/dpdk/app/test/process.h
index 191d2796a9..c3b3780337 100644
--- a/dpdk/app/test/process.h
+++ b/dpdk/app/test/process.h
@@ -25,10 +25,12 @@
 #endif
 
 #ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
 #include <pthread.h>
 extern void *send_pkts(void *empty);
 extern uint16_t flag_for_send_pkts;
 #endif
+#endif
 
 /*
  * launches a second copy of the test process using the given argv parameters,
@@ -44,7 +46,9 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	int i, status;
 	char path[32];
 #ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
 	pthread_t thread;
+#endif
 #endif
 
 	pid_t pid = fork();
@@ -121,17 +125,21 @@ process_dup(const char *const argv[], int numargs, const char *env_value)
 	}
 	/* parent process does a wait */
 #ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0))
 		pthread_create(&thread, NULL, &send_pkts, NULL);
+#endif
 #endif
 
 	while (wait(&status) != pid)
 		;
 #ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
 	if ((strcmp(env_value, "run_pdump_server_tests") == 0)) {
 		flag_for_send_pkts = 0;
 		pthread_join(thread, NULL);
 	}
+#endif
 #endif
 	return status;
 }
diff --git a/dpdk/app/test/test.c b/dpdk/app/test/test.c
index cd7aaf645f..4736a17ff3 100644
--- a/dpdk/app/test/test.c
+++ b/dpdk/app/test/test.c
@@ -53,7 +53,9 @@ do_recursive_call(void)
 	} actions[] =  {
 			{ "run_secondary_instances", test_mp_secondary },
 #ifdef RTE_LIBRTE_PDUMP
+#ifdef RTE_LIBRTE_RING_PMD
 			{ "run_pdump_server_tests", test_pdump },
+#endif
 #endif
 			{ "test_missing_c_flag", no_action },
 			{ "test_master_lcore_flag", no_action },
@@ -162,29 +164,38 @@ main(int argc, char **argv)
 
 
 #ifdef RTE_LIBRTE_CMDLINE
-	cl = cmdline_stdin_new(main_ctx, "RTE>>");
-	if (cl == NULL) {
-		ret = -1;
-		goto out;
-	}
-
 	char *dpdk_test = getenv("DPDK_TEST");
 	if (dpdk_test && strlen(dpdk_test)) {
 		char buf[1024];
+
+		cl = cmdline_new(main_ctx, "RTE>>", 0, 1);
+		if (cl == NULL) {
+			ret = -1;
+			goto out;
+		}
+
 		snprintf(buf, sizeof(buf), "%s\n", dpdk_test);
 		if (cmdline_in(cl, buf, strlen(buf)) < 0) {
 			printf("error on cmdline input\n");
+
+			ret = -1;
+		} else {
+			ret = last_test_result;
+		}
+		cmdline_free(cl);
+		goto out;
+	} else {
+		/* if no DPDK_TEST env variable, go interactive */
+		cl = cmdline_stdin_new(main_ctx, "RTE>>");
+		if (cl == NULL) {
 			ret = -1;
 			goto out;
 		}
 
+		cmdline_interact(cl);
 		cmdline_stdin_exit(cl);
-		ret = last_test_result;
-		goto out;
+		cmdline_free(cl);
 	}
-	/* if no DPDK_TEST env variable, go interactive */
-	cmdline_interact(cl);
-	cmdline_stdin_exit(cl);
 #endif
 	ret = 0;
 
diff --git a/dpdk/app/test/test.h b/dpdk/app/test/test.h
index ac0c50616c..b07f6c1ef0 100644
--- a/dpdk/app/test/test.h
+++ b/dpdk/app/test/test.h
@@ -22,8 +22,6 @@
 # define TEST_TRACE_FAILURE(_file, _line, _func)
 #endif
 
-#define RTE_TEST_TRACE_FAILURE TEST_TRACE_FAILURE
-
 #include <rte_test.h>
 
 #define TEST_ASSERT RTE_TEST_ASSERT
diff --git a/dpdk/app/test/test_acl.c b/dpdk/app/test/test_acl.c
index 9cd9e37dbe..b78b67193a 100644
--- a/dpdk/app/test/test_acl.c
+++ b/dpdk/app/test/test_acl.c
@@ -1394,16 +1394,18 @@ test_invalid_parameters(void)
 	} else
 		rte_acl_free(acx);
 
-	/* invalid NUMA node */
-	memcpy(&param, &acl_param, sizeof(param));
-	param.socket_id = RTE_MAX_NUMA_NODES + 1;
-
-	acx = rte_acl_create(&param);
-	if (acx != NULL) {
-		printf("Line %i: ACL context creation with invalid NUMA "
-				"should have failed!\n", __LINE__);
-		rte_acl_free(acx);
-		return -1;
+	if (rte_eal_has_hugepages()) {
+		/* invalid NUMA node */
+		memcpy(&param, &acl_param, sizeof(param));
+		param.socket_id = RTE_MAX_NUMA_NODES + 1;
+
+		acx = rte_acl_create(&param);
+		if (acx != NULL) {
+			printf("Line %i: ACL context creation with invalid "
+					"NUMA should have failed!\n", __LINE__);
+			rte_acl_free(acx);
+			return -1;
+		}
 	}
 
 	/* NULL name */
diff --git a/dpdk/app/test/test_bpf.c b/dpdk/app/test/test_bpf.c
index ee534687a6..4a61a7d7cb 100644
--- a/dpdk/app/test/test_bpf.c
+++ b/dpdk/app/test/test_bpf.c
@@ -1797,13 +1797,6 @@ test_call1_check(uint64_t rc, const void *arg)
 	dummy_func1(arg, &v32, &v64);
 	v64 += v32;
 
-	if (v64 != rc) {
-		printf("%s@%d: invalid return value "
-			"expected=0x%" PRIx64 ", actual=0x%" PRIx64 "\n",
-			__func__, __LINE__, v64, rc);
-		return -1;
-	}
-	return 0;
 	return cmp_res(__func__, v64, rc, dv, dv, sizeof(*dv));
 }
 
@@ -1934,13 +1927,7 @@ test_call2_check(uint64_t rc, const void *arg)
 	dummy_func2(&a, &b);
 	v = a.u64 + a.u32 + b.u16 + b.u8;
 
-	if (v != rc) {
-		printf("%s@%d: invalid return value "
-			"expected=0x%" PRIx64 ", actual=0x%" PRIx64 "\n",
-			__func__, __LINE__, v, rc);
-		return -1;
-	}
-	return 0;
+	return cmp_res(__func__, v, rc, arg, arg, 0);
 }
 
 static const struct rte_bpf_xsym test_call2_xsym[] = {
@@ -2429,7 +2416,6 @@ test_call5_check(uint64_t rc, const void *arg)
 	v = 0;
 
 fail:
-
 	return cmp_res(__func__, v, rc, &v, &rc, sizeof(v));
 }
 
@@ -2458,6 +2444,7 @@ static const struct rte_bpf_xsym test_call5_xsym[] = {
 	},
 };
 
+/* all bpf test cases */
 static const struct bpf_test tests[] = {
 	{
 		.name = "test_store1",
@@ -2738,7 +2725,6 @@ run_test(const struct bpf_test *tst)
 	}
 
 	tst->prepare(tbuf);
-
 	rc = rte_bpf_exec(bpf, tbuf);
 	ret = tst->check_result(rc, tbuf);
 	if (ret != 0) {
@@ -2746,17 +2732,20 @@ run_test(const struct bpf_test *tst)
 			__func__, __LINE__, tst->name, ret, strerror(ret));
 	}
 
+	/* repeat the same test with jit, when possible */
 	rte_bpf_get_jit(bpf, &jit);
-	if (jit.func == NULL)
-		return 0;
-
-	tst->prepare(tbuf);
-	rc = jit.func(tbuf);
-	rv = tst->check_result(rc, tbuf);
-	ret |= rv;
-	if (rv != 0) {
-		printf("%s@%d: check_result(%s) failed, error: %d(%s);\n",
-			__func__, __LINE__, tst->name, rv, strerror(ret));
+	if (jit.func != NULL) {
+
+		tst->prepare(tbuf);
+		rc = jit.func(tbuf);
+		rv = tst->check_result(rc, tbuf);
+		ret |= rv;
+		if (rv != 0) {
+			printf("%s@%d: check_result(%s) failed, "
+				"error: %d(%s);\n",
+				__func__, __LINE__, tst->name,
+				rv, strerror(ret));
+		}
 	}
 
 	rte_bpf_destroy(bpf);
diff --git a/dpdk/app/test/test_common.c b/dpdk/app/test/test_common.c
index 2b856f8ba5..12bd1cad90 100644
--- a/dpdk/app/test/test_common.c
+++ b/dpdk/app/test/test_common.c
@@ -216,7 +216,19 @@ test_log2(void)
 	const uint32_t max = 0x10000;
 	const uint32_t step = 1;
 
-	for (i = 0; i < max; i = i + step) {
+	compare = rte_log2_u32(0);
+	if (compare != 0) {
+		printf("Wrong rte_log2_u32(0) val %x, expected 0\n", compare);
+		return TEST_FAILED;
+	}
+
+	compare = rte_log2_u64(0);
+	if (compare != 0) {
+		printf("Wrong rte_log2_u64(0) val %x, expected 0\n", compare);
+		return TEST_FAILED;
+	}
+
+	for (i = 1; i < max; i = i + step) {
 		uint64_t i64;
 
 		/* extend range for 64-bit */
diff --git a/dpdk/app/test/test_compressdev_test_buffer.h b/dpdk/app/test/test_compressdev_test_buffer.h
index c0492f89a2..d241602445 100644
--- a/dpdk/app/test/test_compressdev_test_buffer.h
+++ b/dpdk/app/test/test_compressdev_test_buffer.h
@@ -1,3 +1,7 @@
+/* SPDX-License-Identifier: (BSD-3-Clause)
+ * Copyright(c) 2018-2020 Intel Corporation
+ */
+
 #ifndef TEST_COMPRESSDEV_TEST_BUFFERS_H_
 #define TEST_COMPRESSDEV_TEST_BUFFERS_H_
 
@@ -190,106 +194,104 @@ static const char test_buf_shakespeare[] =
 	"\n"
 	"ORLANDO	Go apart, Adam, and thou shalt hear how he will\n";
 
-/* Snippet of source code in Pascal */
-static const char test_buf_pascal[] =
-	"	Ptr    = 1..DMem;\n"
-	"	Loc    = 1..IMem;\n"
-	"	Loc0   = 0..IMem;\n"
-	"	EdgeT  = (hout,lin,hin,lout); {Warning this order is important in}\n"
-	"				      {predicates such as gtS,geS}\n"
-	"	CardT  = (finite,infinite);\n"
-	"	ExpT   = Minexp..Maxexp;\n"
-	"	ManT   = Mininf..Maxinf; \n"
-	"	Pflag  = (PNull,PSoln,PTrace,PPrint);\n"
-	"	Sreal  = record\n"
-	"		    edge:EdgeT;\n"
-	"		    cardinality:CardT;\n"
-	"		    exp:ExpT; {exponent}\n"
-	"		    mantissa:ManT;\n"
-	"		 end;\n"
-	"	Int    = record\n"
-	"		    hi:Sreal;\n"
-	"		    lo:Sreal;\n"
-	"	 end;\n"
-	"	Instr  = record\n"
-	"		    Code:OpType;\n"
-	"		    Pars: array[0..Par] of 0..DMem;\n"
-	"		 end;\n"
-	"	DataMem= record\n"
-	"		    D        :array [Ptr] of Int;\n"
-	"		    S        :array [Loc] of State;\n"
-	"		    LastHalve:Loc;\n"
-	"		    RHalve   :array [Loc] of real;\n"
-	"		 end;\n"
-	"	DataFlags=record\n"
-	"		    PF	     :array [Ptr] of Pflag;\n"
-	"		 end;\n"
-	"var\n"
-	"	Debug  : (none,activity,post,trace,dump);\n"
-	"	Cut    : (once,all);\n"
-	"	GlobalEnd,Verifiable:boolean;\n"
-	"	HalveThreshold:real;\n"
-	"	I      : array [Loc] of Instr; {Memory holding instructions}\n"
-	"	End    : Loc; {last instruction in I}\n"
-	"	ParN   : array [OpType] of -1..Par; {number of parameters for each \n"
-	"			opcode. -1 means no result}\n"
-	"        ParIntersect : array [OpType] of boolean ;\n"
-	"	DInit  : DataMem; {initial memory which is cleared and \n"
-	"				used in first call}\n"
-	"	DF     : DataFlags; {hold flags for variables, e.g. print/trace}\n"
-	"	MaxDMem:0..DMem;\n"
-	"	Shift  : array[0..Digits] of 1..maxint;{array of constant multipliers}\n"
-	"						{used for alignment etc.}\n"
-	"	Dummy  :Positive;\n"
-	"	{constant intervals and Sreals}\n"
-	"	PlusInfS,MinusInfS,PlusSmallS,MinusSmallS,ZeroS,\n"
-	"	PlusFiniteS,MinusFiniteS:Sreal;\n"
-	"	Zero,All,AllFinite:Int;\n"
-	"\n"
-	"procedure deblank;\n"
-	"var Ch:char;\n"
-	"begin\n"
-	"   while (not eof) and (input^ in [' ','	']) do read(Ch);\n"
-	"end;\n"
-	"\n"
-	"procedure InitialOptions;\n"
-	"\n"
-	"#include '/user/profs/cleary/bin/options.i';\n"
-	"\n"
-	"   procedure Option;\n"
-	"   begin\n"
-	"      case Opt of\n"
-	"      'a','A':Debug:=activity;\n"
-	"      'd','D':Debug:=dump;\n"
-	"      'h','H':HalveThreshold:=StringNum/100;\n"
-	"      'n','N':Debug:=none;\n"
-	"      'p','P':Debug:=post;\n"
-	"      't','T':Debug:=trace;\n"
-	"      'v','V':Verifiable:=true;\n"
-	"      end;\n"
-	"   end;\n"
-	"\n"
-	"begin\n"
-	"   Debug:=trace;\n"
-	"   Verifiable:=false;\n"
-	"   HalveThreshold:=67/100;\n"
-	"   Options;\n"
-	"   writeln(Debug);\n"
-	"   writeln('Verifiable:',Verifiable);\n"
-	"   writeln('Halve threshold',HalveThreshold);\n"
-	"end;{InitialOptions}\n"
-	"\n"
-	"procedure NormalizeUp(E,M:integer;var S:Sreal;var Closed:boolean);\n"
-	"begin\n"
-	"with S do\n"
-	"begin\n"
-	"   if M=0 then S:=ZeroS else\n"
-	"   if M>0 then\n";
+/* Snippet of Alice's Adventures in Wonderland */
+static const char test_buf_alice2[] =
+	"`Curiouser and curiouser!' cried Alice (she was so much\n"
+	"surprised, that for the moment she quite forgot how to speak good\n"
+	"English); `now I'm opening out like the largest telescope that\n"
+	"ever was!  Good-bye, feet!' (for when she looked down at her\n"
+	"feet, they seemed to be almost out of sight, they were getting so\n"
+	"far off).  `Oh, my poor little feet, I wonder who will put on\n"
+	"your shoes and stockings for you now, dears?  I'm sure _I_ shan't\n"
+	"be able!  I shall be a great deal too far off to trouble myself\n"
+	"about you:  you must manage the best way you can; --but I must be\n"
+	"kind to them,' thought Alice, `or perhaps they won't walk the\n"
+	"way I want to go!  Let me see:  I'll give them a new pair of\n"
+	"boots every Christmas.'\n"
+	"\n"
+	"  And she went on planning to herself how she would manage it.\n"
+	"`They must go by the carrier,' she thought; `and how funny it'll\n"
+	"seem, sending presents to one's own feet!  And how odd the\n"
+	"directions will look!\n"
+	"\n"
+	"	    ALICE'S RIGHT FOOT, ESQ.\n"
+	"		HEARTHRUG,\n"
+	"		    NEAR THE FENDER,\n"
+	"			(WITH ALICE'S LOVE).\n"
+	"\n"
+	"Oh dear, what nonsense I'm talking!'\n"
+	"\n"
+	"  Just then her head struck against the roof of the hall:  in\n"
+	"fact she was now more than nine feet high, and she at once took\n"
+	"up the little golden key and hurried off to the garden door.\n"
+	"\n"
+	"  Poor Alice!  It was as much as she could do, lying down on one\n"
+	"side, to look through into the garden with one eye; but to get\n"
+	"through was more hopeless than ever:  she sat down and began to\n"
+	"cry again.\n"
+	"\n"
+	"  `You ought to be ashamed of yourself,' said Alice, `a great\n"
+	"girl like you,' (she might well say this), `to go on crying in\n"
+	"this way!  Stop this moment, I tell you!'  But she went on all\n"
+	"the same, shedding gallons of tears, until there was a large pool\n"
+	"all round her, about four inches deep and reaching half down the\n"
+	"hall.\n"
+	"\n"
+	" After a time she heard a little pattering of feet in the\n"
+	"distance, and she hastily dried her eyes to see what was coming.\n"
+	"It was the White Rabbit returning, splendidly dressed, with a\n"
+	"pair of white kid gloves in one hand and a large fan in the\n"
+	"other:  he came trotting along in a great hurry, muttering to\n"
+	"himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she\n"
+	"be savage if I've kept her waiting!'  Alice felt so desperate\n"
+	"that she was ready to ask help of any one; so, when the Rabbit\n"
+	"came near her, she began, in a low, timid voice, `If you please,\n"
+	"sir--'  The Rabbit started violently, dropped the white kid\n"
+	"gloves and the fan, and skurried away into the darkness as hard\n"
+	"as he could go.\n"
+	"\n"
+	"  Alice took up the fan and gloves, and, as the hall was very\n"
+	"hot, she kept fanning herself all the time she went on talking:\n"
+	"`Dear, dear!  How queer everything is to-day!  And yesterday\n"
+	"things went on just as usual.  I wonder if I've been changed in\n"
+	"the night?  Let me think:  was I the same when I got up this\n"
+	"morning?  I almost think I can remember feeling a little\n"
+	"different.  But if I'm not the same, the next question is, Who in\n"
+	"the world am I?  Ah, THAT'S the great puzzle!'  And she began\n"
+	"thinking over all the children she knew that were of the same age\n"
+	"as herself, to see if she could have been changed for any of\n"
+	"them.\n"
+	"\n"
+	"  `I'm sure I'm not Ada,' she said, `for her hair goes in such\n"
+	"long ringlets, and mine doesn't go in ringlets at all; and I'm\n"
+	"sure I can't be Mabel, for I know all sorts of things, and she,\n"
+	"oh! she knows such a very little!  Besides, SHE'S she, and I'm I,\n"
+	"and--oh dear, how puzzling it all is!  I'll try if I know all the\n"
+	"things I used to know.  Let me see:  four times five is twelve,\n"
+	"and four times six is thirteen, and four times seven is--oh dear!\n"
+	"I shall never get to twenty at that rate!  However, the\n"
+	"Multiplication Table doesn't signify:  let's try Geography.\n"
+	"London is the capital of Paris, and Paris is the capital of Rome,\n"
+	"and Rome--no, THAT'S all wrong, I'm certain!  I must have been\n"
+	"changed for Mabel!  I'll try and say ''How doth the little--''\n"
+	"and she crossed her hands on her lap as if she were saying lessons,\n"
+	"and began to repeat it, but her voice sounded hoarse and\n"
+	"strange, and the words did not come the same as they used to do:--\n"
+	"\n"
+	"	    `How doth the little crocodile\n"
+	"	      Improve his shining tail,\n"
+	"	    And pour the waters of the Nile\n"
+	"	      On every golden scale!\n"
+	"\n"
+	"	    `How cheerfully he seems to grin,\n"
+	"	      How neatly spread his claws,\n"
+	"	    And welcome little fishes in\n"
+	"	      With gently smiling jaws!'\n";
 
 static const char * const compress_test_bufs[] = {
 	test_buf_alice,
 	test_buf_shakespeare,
-	test_buf_pascal
+	test_buf_alice2
 };
 
 #endif /* TEST_COMPRESSDEV_TEST_BUFFERS_H_ */
diff --git a/dpdk/app/test/test_cryptodev.c b/dpdk/app/test/test_cryptodev.c
index 1b561456d7..a852040ec2 100644
--- a/dpdk/app/test/test_cryptodev.c
+++ b/dpdk/app/test/test_cryptodev.c
@@ -143,7 +143,7 @@ static struct rte_crypto_op *
 process_crypto_request(uint8_t dev_id, struct rte_crypto_op *op)
 {
 	if (rte_cryptodev_enqueue_burst(dev_id, 0, &op, 1) != 1) {
-		printf("Error sending packet for encryption");
+		RTE_LOG(ERR, USER1, "Error sending packet for encryption\n");
 		return NULL;
 	}
 
@@ -152,6 +152,11 @@ process_crypto_request(uint8_t dev_id, struct rte_crypto_op *op)
 	while (rte_cryptodev_dequeue_burst(dev_id, 0, &op, 1) == 0)
 		rte_pause();
 
+	if (op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		RTE_LOG(DEBUG, USER1, "Operation status %d\n", op->status);
+		return NULL;
+	}
+
 	return op;
 }
 
@@ -638,7 +643,7 @@ test_device_configure_invalid_dev_id(void)
 			"Need at least %d devices for test", 1);
 
 	/* valid dev_id values */
-	dev_id = ts_params->valid_devs[ts_params->valid_dev_count - 1];
+	dev_id = ts_params->valid_devs[0];
 
 	/* Stop the device in case it's started so it can be configured */
 	rte_cryptodev_stop(dev_id);
@@ -2696,13 +2701,15 @@ create_wireless_algo_cipher_auth_session(uint8_t dev_id,
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_sym_session_create(
 			ts_params->session_mpool);
+	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
 			&ut_params->cipher_xform,
 			ts_params->session_priv_mpool);
+	if (status == -ENOTSUP)
+		return status;
 
 	TEST_ASSERT_EQUAL(status, 0, "session init failed");
-	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 	return 0;
 }
 
@@ -2822,12 +2829,24 @@ create_wireless_algo_auth_cipher_session(uint8_t dev_id,
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_sym_session_create(
 			ts_params->session_mpool);
+	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
+
+	if (cipher_op == RTE_CRYPTO_CIPHER_OP_DECRYPT) {
+		ut_params->auth_xform.next = NULL;
+		ut_params->cipher_xform.next = &ut_params->auth_xform;
+		status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+				&ut_params->cipher_xform,
+				ts_params->session_priv_mpool);
+
+	} else
+		status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
+				&ut_params->auth_xform,
+				ts_params->session_priv_mpool);
+
+	if (status == -ENOTSUP)
+		return status;
 
-	status = rte_cryptodev_sym_session_init(dev_id, ut_params->sess,
-			&ut_params->auth_xform,
-			ts_params->session_priv_mpool);
 	TEST_ASSERT_EQUAL(status, 0, "session init failed");
-	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	return 0;
 }
@@ -2971,6 +2990,11 @@ create_wireless_algo_cipher_hash_operation(const uint8_t *auth_tag,
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
 	struct crypto_unittest_params *ut_params = &unittest_params;
 
+	enum rte_crypto_cipher_algorithm cipher_algo =
+			ut_params->cipher_xform.cipher.algo;
+	enum rte_crypto_auth_algorithm auth_algo =
+			ut_params->auth_xform.auth.algo;
+
 	/* Generate Crypto op data structure */
 	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
 			RTE_CRYPTO_OP_TYPE_SYMMETRIC);
@@ -2991,8 +3015,22 @@ create_wireless_algo_cipher_hash_operation(const uint8_t *auth_tag,
 	TEST_ASSERT_NOT_NULL(sym_op->auth.digest.data,
 			"no room to append auth tag");
 	ut_params->digest = sym_op->auth.digest.data;
-	sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
-			ut_params->ibuf, data_pad_len);
+
+	if (rte_pktmbuf_is_contiguous(ut_params->ibuf)) {
+		sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+				ut_params->ibuf, data_pad_len);
+	} else {
+		struct rte_mbuf *m = ut_params->ibuf;
+		unsigned int offset = data_pad_len;
+
+		while (offset > m->data_len && m->next != NULL) {
+			offset -= m->data_len;
+			m = m->next;
+		}
+		sym_op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(
+			m, offset);
+	}
+
 	if (op == RTE_CRYPTO_AUTH_OP_GENERATE)
 		memset(sym_op->auth.digest.data, 0, auth_tag_len);
 	else
@@ -3009,22 +3047,38 @@ create_wireless_algo_cipher_hash_operation(const uint8_t *auth_tag,
 	iv_ptr += cipher_iv_len;
 	rte_memcpy(iv_ptr, auth_iv, auth_iv_len);
 
-	sym_op->cipher.data.length = cipher_len;
-	sym_op->cipher.data.offset = cipher_offset;
-	sym_op->auth.data.length = auth_len;
-	sym_op->auth.data.offset = auth_offset;
+	if (cipher_algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2 ||
+		cipher_algo == RTE_CRYPTO_CIPHER_KASUMI_F8 ||
+		cipher_algo == RTE_CRYPTO_CIPHER_ZUC_EEA3) {
+		sym_op->cipher.data.length = cipher_len;
+		sym_op->cipher.data.offset = cipher_offset;
+	} else {
+		sym_op->cipher.data.length = cipher_len >> 3;
+		sym_op->cipher.data.offset = cipher_offset >> 3;
+	}
+
+	if (auth_algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2 ||
+		auth_algo == RTE_CRYPTO_AUTH_KASUMI_F9 ||
+		auth_algo == RTE_CRYPTO_AUTH_ZUC_EIA3) {
+		sym_op->auth.data.length = auth_len;
+		sym_op->auth.data.offset = auth_offset;
+	} else {
+		sym_op->auth.data.length = auth_len >> 3;
+		sym_op->auth.data.offset = auth_offset >> 3;
+	}
 
 	return 0;
 }
 
 static int
-create_wireless_algo_auth_cipher_operation(unsigned int auth_tag_len,
+create_wireless_algo_auth_cipher_operation(
+		const uint8_t *auth_tag, unsigned int auth_tag_len,
 		const uint8_t *cipher_iv, uint8_t cipher_iv_len,
 		const uint8_t *auth_iv, uint8_t auth_iv_len,
 		unsigned int data_pad_len,
 		unsigned int cipher_len, unsigned int cipher_offset,
 		unsigned int auth_len, unsigned int auth_offset,
-		uint8_t op_mode, uint8_t do_sgl)
+		uint8_t op_mode, uint8_t do_sgl, uint8_t verify)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
 	struct crypto_unittest_params *ut_params = &unittest_params;
@@ -3081,6 +3135,10 @@ create_wireless_algo_auth_cipher_operation(unsigned int auth_tag_len,
 		}
 	}
 
+	/* Copy digest for the verification */
+	if (verify)
+		memcpy(sym_op->auth.digest.data, auth_tag, auth_tag_len);
+
 	/* Copy cipher and auth IVs at the end of the crypto operation */
 	uint8_t *iv_ptr = rte_crypto_op_ctod_offset(
 			ut_params->op, uint8_t *, IV_OFFSET);
@@ -4643,7 +4701,7 @@ test_snow3g_auth_cipher(const struct snow3g_test_data *tdata,
 
 	/* Create SNOW 3G operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-		tdata->digest.len,
+		tdata->digest.data, tdata->digest.len,
 		tdata->cipher_iv.data, tdata->cipher_iv.len,
 		tdata->auth_iv.data, tdata->auth_iv.len,
 		(tdata->digest.offset_bytes == 0 ?
@@ -4653,7 +4711,7 @@ test_snow3g_auth_cipher(const struct snow3g_test_data *tdata,
 		tdata->cipher.offset_bits,
 		tdata->validAuthLenInBits.len,
 		tdata->auth.offset_bits,
-		op_mode, 0);
+		op_mode, 0, verify);
 
 	if (retval < 0)
 		return retval;
@@ -4819,7 +4877,7 @@ test_snow3g_auth_cipher_sgl(const struct snow3g_test_data *tdata,
 
 	/* Create SNOW 3G operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-		tdata->digest.len,
+		tdata->digest.data, tdata->digest.len,
 		tdata->cipher_iv.data, tdata->cipher_iv.len,
 		tdata->auth_iv.data, tdata->auth_iv.len,
 		(tdata->digest.offset_bytes == 0 ?
@@ -4829,7 +4887,7 @@ test_snow3g_auth_cipher_sgl(const struct snow3g_test_data *tdata,
 		tdata->cipher.offset_bits,
 		tdata->validAuthLenInBits.len,
 		tdata->auth.offset_bits,
-		op_mode, 1);
+		op_mode, 1, verify);
 
 	if (retval < 0)
 		return retval;
@@ -4988,7 +5046,7 @@ test_kasumi_auth_cipher(const struct kasumi_test_data *tdata,
 
 	/* Create KASUMI operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-		tdata->digest.len,
+		tdata->digest.data, tdata->digest.len,
 		tdata->cipher_iv.data, tdata->cipher_iv.len,
 		NULL, 0,
 		(tdata->digest.offset_bytes == 0 ?
@@ -4998,7 +5056,7 @@ test_kasumi_auth_cipher(const struct kasumi_test_data *tdata,
 		tdata->validCipherOffsetInBits.len,
 		tdata->validAuthLenInBits.len,
 		0,
-		op_mode, 0);
+		op_mode, 0, verify);
 
 	if (retval < 0)
 		return retval;
@@ -5165,7 +5223,7 @@ test_kasumi_auth_cipher_sgl(const struct kasumi_test_data *tdata,
 
 	/* Create KASUMI operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-		tdata->digest.len,
+		tdata->digest.data, tdata->digest.len,
 		tdata->cipher_iv.data, tdata->cipher_iv.len,
 		NULL, 0,
 		(tdata->digest.offset_bytes == 0 ?
@@ -5175,7 +5233,7 @@ test_kasumi_auth_cipher_sgl(const struct kasumi_test_data *tdata,
 		tdata->validCipherOffsetInBits.len,
 		tdata->validAuthLenInBits.len,
 		0,
-		op_mode, 1);
+		op_mode, 1, verify);
 
 	if (retval < 0)
 		return retval;
@@ -5666,7 +5724,7 @@ test_zuc_auth_cipher(const struct wireless_test_data *tdata,
 
 	/* Create ZUC operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-		tdata->digest.len,
+		tdata->digest.data, tdata->digest.len,
 		tdata->cipher_iv.data, tdata->cipher_iv.len,
 		tdata->auth_iv.data, tdata->auth_iv.len,
 		(tdata->digest.offset_bytes == 0 ?
@@ -5676,7 +5734,7 @@ test_zuc_auth_cipher(const struct wireless_test_data *tdata,
 		tdata->validCipherOffsetInBits.len,
 		tdata->validAuthLenInBits.len,
 		0,
-		op_mode, 0);
+		op_mode, 0, verify);
 
 	if (retval < 0)
 		return retval;
@@ -5852,7 +5910,7 @@ test_zuc_auth_cipher_sgl(const struct wireless_test_data *tdata,
 
 	/* Create ZUC operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-		tdata->digest.len,
+		tdata->digest.data, tdata->digest.len,
 		tdata->cipher_iv.data, tdata->cipher_iv.len,
 		NULL, 0,
 		(tdata->digest.offset_bytes == 0 ?
@@ -5862,7 +5920,7 @@ test_zuc_auth_cipher_sgl(const struct wireless_test_data *tdata,
 		tdata->validCipherOffsetInBits.len,
 		tdata->validAuthLenInBits.len,
 		0,
-		op_mode, 1);
+		op_mode, 1, verify);
 
 	if (retval < 0)
 		return retval;
@@ -6576,8 +6634,9 @@ test_mixed_auth_cipher(const struct mixed_cipher_auth_test_data *tdata,
 	unsigned int ciphertext_len;
 
 	struct rte_cryptodev_info dev_info;
+	struct rte_crypto_op *op;
 
-	/* Check if device supports particular algorithms */
+	/* Check if device supports particular algorithms separately */
 	if (test_mixed_check_if_unsupported(tdata))
 		return -ENOTSUP;
 
@@ -6593,18 +6652,26 @@ test_mixed_auth_cipher(const struct mixed_cipher_auth_test_data *tdata,
 	}
 
 	/* Create the session */
-	retval = create_wireless_algo_auth_cipher_session(
-			ts_params->valid_devs[0],
-			(verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
-					: RTE_CRYPTO_CIPHER_OP_ENCRYPT),
-			(verify ? RTE_CRYPTO_AUTH_OP_VERIFY
-					: RTE_CRYPTO_AUTH_OP_GENERATE),
-			tdata->auth_algo,
-			tdata->cipher_algo,
-			tdata->auth_key.data, tdata->auth_key.len,
-			tdata->auth_iv.len, tdata->digest_enc.len,
-			tdata->cipher_iv.len);
-
+	if (verify)
+		retval = create_wireless_algo_cipher_auth_session(
+				ts_params->valid_devs[0],
+				RTE_CRYPTO_CIPHER_OP_DECRYPT,
+				RTE_CRYPTO_AUTH_OP_VERIFY,
+				tdata->auth_algo,
+				tdata->cipher_algo,
+				tdata->auth_key.data, tdata->auth_key.len,
+				tdata->auth_iv.len, tdata->digest_enc.len,
+				tdata->cipher_iv.len);
+	else
+		retval = create_wireless_algo_auth_cipher_session(
+				ts_params->valid_devs[0],
+				RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+				RTE_CRYPTO_AUTH_OP_GENERATE,
+				tdata->auth_algo,
+				tdata->cipher_algo,
+				tdata->auth_key.data, tdata->auth_key.len,
+				tdata->auth_iv.len, tdata->digest_enc.len,
+				tdata->cipher_iv.len);
 	if (retval < 0)
 		return retval;
 
@@ -6643,24 +6710,34 @@ test_mixed_auth_cipher(const struct mixed_cipher_auth_test_data *tdata,
 
 	/* Create the operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-			tdata->digest_enc.len,
+			tdata->digest_enc.data, tdata->digest_enc.len,
 			tdata->cipher_iv.data, tdata->cipher_iv.len,
 			tdata->auth_iv.data, tdata->auth_iv.len,
 			(tdata->digest_enc.offset == 0 ?
-			(verify ? ciphertext_pad_len : plaintext_pad_len)
+				plaintext_pad_len
 				: tdata->digest_enc.offset),
 			tdata->validCipherLen.len_bits,
 			tdata->cipher.offset_bits,
 			tdata->validAuthLen.len_bits,
 			tdata->auth.offset_bits,
-			op_mode, 0);
+			op_mode, 0, verify);
 
 	if (retval < 0)
 		return retval;
 
-	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+	op = process_crypto_request(ts_params->valid_devs[0],
 			ut_params->op);
 
+	/* Check if the op failed because the device doesn't */
+	/* support this particular combination of algorithms */
+	if (op == NULL && ut_params->op->status ==
+			RTE_CRYPTO_OP_STATUS_INVALID_SESSION) {
+		printf("Device doesn't support this mixed combination. "
+				"Test Skipped.\n");
+		return -ENOTSUP;
+	}
+	ut_params->op = op;
+
 	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
 
 	ut_params->obuf = (op_mode == IN_PLACE ?
@@ -6675,12 +6752,10 @@ test_mixed_auth_cipher(const struct mixed_cipher_auth_test_data *tdata,
 					(tdata->cipher.offset_bits >> 3);
 
 		debug_hexdump(stdout, "plaintext:", plaintext,
-				(tdata->plaintext.len_bits >> 3) -
-				tdata->digest_enc.len);
+				tdata->plaintext.len_bits >> 3);
 		debug_hexdump(stdout, "plaintext expected:",
 				tdata->plaintext.data,
-				(tdata->plaintext.len_bits >> 3) -
-				tdata->digest_enc.len);
+				tdata->plaintext.len_bits >> 3);
 	} else {
 		if (ut_params->obuf)
 			ciphertext = rte_pktmbuf_mtod(ut_params->obuf,
@@ -6725,6 +6800,10 @@ test_mixed_auth_cipher(const struct mixed_cipher_auth_test_data *tdata,
 				DIGEST_BYTE_LENGTH_SNOW3G_UIA2,
 				"Generated auth tag not as expected");
 	}
+
+	TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+			"crypto op processing failed");
+
 	return 0;
 }
 
@@ -6748,6 +6827,7 @@ test_mixed_auth_cipher_sgl(const struct mixed_cipher_auth_test_data *tdata,
 	uint8_t digest_buffer[10000];
 
 	struct rte_cryptodev_info dev_info;
+	struct rte_crypto_op *op;
 
 	/* Check if device supports particular algorithms */
 	if (test_mixed_check_if_unsupported(tdata))
@@ -6776,18 +6856,26 @@ test_mixed_auth_cipher_sgl(const struct mixed_cipher_auth_test_data *tdata,
 	}
 
 	/* Create the session */
-	retval = create_wireless_algo_auth_cipher_session(
-			ts_params->valid_devs[0],
-			(verify ? RTE_CRYPTO_CIPHER_OP_DECRYPT
-					: RTE_CRYPTO_CIPHER_OP_ENCRYPT),
-			(verify ? RTE_CRYPTO_AUTH_OP_VERIFY
-					: RTE_CRYPTO_AUTH_OP_GENERATE),
-			tdata->auth_algo,
-			tdata->cipher_algo,
-			tdata->auth_key.data, tdata->auth_key.len,
-			tdata->auth_iv.len, tdata->digest_enc.len,
-			tdata->cipher_iv.len);
-
+	if (verify)
+		retval = create_wireless_algo_cipher_auth_session(
+				ts_params->valid_devs[0],
+				RTE_CRYPTO_CIPHER_OP_DECRYPT,
+				RTE_CRYPTO_AUTH_OP_VERIFY,
+				tdata->auth_algo,
+				tdata->cipher_algo,
+				tdata->auth_key.data, tdata->auth_key.len,
+				tdata->auth_iv.len, tdata->digest_enc.len,
+				tdata->cipher_iv.len);
+	else
+		retval = create_wireless_algo_auth_cipher_session(
+				ts_params->valid_devs[0],
+				RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+				RTE_CRYPTO_AUTH_OP_GENERATE,
+				tdata->auth_algo,
+				tdata->cipher_algo,
+				tdata->auth_key.data, tdata->auth_key.len,
+				tdata->auth_iv.len, tdata->digest_enc.len,
+				tdata->cipher_iv.len);
 	if (retval < 0)
 		return retval;
 
@@ -6797,7 +6885,7 @@ test_mixed_auth_cipher_sgl(const struct mixed_cipher_auth_test_data *tdata,
 	plaintext_pad_len = RTE_ALIGN_CEIL(plaintext_len, 16);
 
 	ut_params->ibuf = create_segmented_mbuf(ts_params->mbuf_pool,
-			plaintext_pad_len, 15, 0);
+			ciphertext_pad_len, 15, 0);
 	TEST_ASSERT_NOT_NULL(ut_params->ibuf,
 			"Failed to allocate input buffer in mempool");
 
@@ -6827,24 +6915,35 @@ test_mixed_auth_cipher_sgl(const struct mixed_cipher_auth_test_data *tdata,
 
 	/* Create the operation */
 	retval = create_wireless_algo_auth_cipher_operation(
-			tdata->digest_enc.len,
+			tdata->digest_enc.data, tdata->digest_enc.len,
 			tdata->cipher_iv.data, tdata->cipher_iv.len,
 			tdata->auth_iv.data, tdata->auth_iv.len,
 			(tdata->digest_enc.offset == 0 ?
-			(verify ? ciphertext_pad_len : plaintext_pad_len)
+				plaintext_pad_len
 				: tdata->digest_enc.offset),
 			tdata->validCipherLen.len_bits,
 			tdata->cipher.offset_bits,
 			tdata->validAuthLen.len_bits,
 			tdata->auth.offset_bits,
-			op_mode, 1);
+			op_mode, 1, verify);
 
 	if (retval < 0)
 		return retval;
 
-	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
+	op = process_crypto_request(ts_params->valid_devs[0],
 			ut_params->op);
 
+	/* Check if the op failed because the device doesn't */
+	/* support this particular combination of algorithms */
+	if (op == NULL && ut_params->op->status ==
+			RTE_CRYPTO_OP_STATUS_INVALID_SESSION) {
+		printf("Device doesn't support this mixed combination. "
+				"Test Skipped.\n");
+		return -ENOTSUP;
+	}
+
+	ut_params->op = op;
+
 	TEST_ASSERT_NOT_NULL(ut_params->op, "failed to retrieve obuf");
 
 	ut_params->obuf = (op_mode == IN_PLACE ?
@@ -6917,6 +7016,10 @@ test_mixed_auth_cipher_sgl(const struct mixed_cipher_auth_test_data *tdata,
 				tdata->digest_enc.len,
 				"Generated auth tag not as expected");
 	}
+
+	TEST_ASSERT_EQUAL(ut_params->op->status, RTE_CRYPTO_OP_STATUS_SUCCESS,
+			"crypto op processing failed");
+
 	return 0;
 }
 
@@ -6978,6 +7081,176 @@ test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_oop_sgl(void)
 		&auth_aes_cmac_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
 }
 
+/** MIXED AUTH + CIPHER */
+
+static int
+test_auth_zuc_cipher_snow_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_zuc_cipher_snow_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_zuc_cipher_snow_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_zuc_cipher_snow_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_aes_cmac_cipher_snow_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_aes_cmac_cipher_snow_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_aes_cmac_cipher_snow_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_aes_cmac_cipher_snow_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_zuc_cipher_aes_ctr_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_zuc_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_zuc_cipher_aes_ctr_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_zuc_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_snow_cipher_aes_ctr_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_snow_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_snow_cipher_aes_ctr_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_snow_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_snow_cipher_zuc_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_snow_cipher_zuc_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_snow_cipher_zuc_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_snow_cipher_zuc_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_aes_cmac_cipher_zuc_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_aes_cmac_cipher_zuc_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_aes_cmac_cipher_zuc_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_aes_cmac_cipher_zuc_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_null_cipher_snow_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_null_cipher_snow_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_null_cipher_snow_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_null_cipher_snow_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_null_cipher_zuc_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_null_cipher_zuc_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_null_cipher_zuc_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_null_cipher_zuc_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_snow_cipher_null_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_snow_cipher_null_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_snow_cipher_null_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_snow_cipher_null_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_zuc_cipher_null_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_zuc_cipher_null_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_zuc_cipher_null_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_zuc_cipher_null_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_null_cipher_aes_ctr_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_null_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_null_cipher_aes_ctr_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_null_cipher_aes_ctr_test_case_1, OUT_OF_PLACE, 1);
+}
+
+static int
+test_auth_aes_cmac_cipher_null_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_aes_cmac_cipher_null_test_case_1, OUT_OF_PLACE, 0);
+}
+
+static int
+test_verify_auth_aes_cmac_cipher_null_test_case_1(void)
+{
+	return test_mixed_auth_cipher(
+		&auth_aes_cmac_cipher_null_test_case_1, OUT_OF_PLACE, 1);
+}
+
 static int
 test_3DES_chain_qat_all(void)
 {
@@ -9139,8 +9412,10 @@ test_stats(void)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
 	struct rte_cryptodev_stats stats;
-	struct rte_cryptodev *dev;
-	cryptodev_stats_get_t temp_pfn;
+
+	if (rte_cryptodev_stats_get(ts_params->valid_devs[0], &stats)
+			== -ENOTSUP)
+		return -ENOTSUP;
 
 	rte_cryptodev_stats_reset(ts_params->valid_devs[0]);
 	TEST_ASSERT((rte_cryptodev_stats_get(ts_params->valid_devs[0] + 600,
@@ -9148,18 +9423,9 @@ test_stats(void)
 		"rte_cryptodev_stats_get invalid dev failed");
 	TEST_ASSERT((rte_cryptodev_stats_get(ts_params->valid_devs[0], 0) != 0),
 		"rte_cryptodev_stats_get invalid Param failed");
-	dev = &rte_cryptodevs[ts_params->valid_devs[0]];
-	temp_pfn = dev->dev_ops->stats_get;
-	dev->dev_ops->stats_get = (cryptodev_stats_get_t)0;
-	TEST_ASSERT((rte_cryptodev_stats_get(ts_params->valid_devs[0], &stats)
-			== -ENOTSUP),
-		"rte_cryptodev_stats_get invalid Param failed");
-	dev->dev_ops->stats_get = temp_pfn;
 
 	/* Test expected values */
-	ut_setup();
 	test_AES_CBC_HMAC_SHA1_encrypt_digest();
-	ut_teardown();
 	TEST_ASSERT_SUCCESS(rte_cryptodev_stats_get(ts_params->valid_devs[0],
 			&stats),
 		"rte_cryptodev_stats_get failed");
@@ -10450,7 +10716,7 @@ aes128cbc_hmac_sha1_test_vector = {
 static const struct test_crypto_vector
 aes128cbc_hmac_sha1_aad_test_vector = {
 	.crypto_algo = RTE_CRYPTO_CIPHER_AES_CBC,
-	.cipher_offset = 12,
+	.cipher_offset = 8,
 	.cipher_len = 496,
 	.cipher_key = {
 		.data = {
@@ -10486,9 +10752,9 @@ aes128cbc_hmac_sha1_aad_test_vector = {
 	},
 	.digest = {
 		.data = {
-			0x1F, 0x6A, 0xD2, 0x8B, 0x4B, 0xB3, 0xC0, 0x9E,
-			0x86, 0x9B, 0x3A, 0xF2, 0x00, 0x5B, 0x4F, 0x08,
-			0x62, 0x8D, 0x62, 0x65
+			0x6D, 0xF3, 0x50, 0x79, 0x7A, 0x2A, 0xAC, 0x7F,
+			0xA6, 0xF0, 0xC6, 0x38, 0x1F, 0xA4, 0xDD, 0x9B,
+			0x62, 0x0F, 0xFB, 0x10
 		},
 		.len = 20
 	}
@@ -10818,13 +11084,8 @@ test_authentication_verify_fail_when_data_corruption(
 
 	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
 			ut_params->op);
-	TEST_ASSERT_NOT_NULL(ut_params->op, "failed crypto process");
-	TEST_ASSERT_NOT_EQUAL(ut_params->op->status,
-			RTE_CRYPTO_OP_STATUS_SUCCESS,
-			"authentication not failed");
 
-	ut_params->obuf = ut_params->op->sym->m_src;
-	TEST_ASSERT_NOT_NULL(ut_params->obuf, "failed to retrieve obuf");
+	TEST_ASSERT_NULL(ut_params->op, "authentication not failed");
 
 	return 0;
 }
@@ -10879,13 +11140,8 @@ test_authentication_verify_GMAC_fail_when_corruption(
 
 	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
 			ut_params->op);
-	TEST_ASSERT_NOT_NULL(ut_params->op, "failed crypto process");
-	TEST_ASSERT_NOT_EQUAL(ut_params->op->status,
-			RTE_CRYPTO_OP_STATUS_SUCCESS,
-			"authentication not failed");
 
-	ut_params->obuf = ut_params->op->sym->m_src;
-	TEST_ASSERT_NOT_NULL(ut_params->obuf, "failed to retrieve obuf");
+	TEST_ASSERT_NULL(ut_params->op, "authentication not failed");
 
 	return 0;
 }
@@ -10940,13 +11196,7 @@ test_authenticated_decryption_fail_when_corruption(
 	ut_params->op = process_crypto_request(ts_params->valid_devs[0],
 			ut_params->op);
 
-	TEST_ASSERT_NOT_NULL(ut_params->op, "failed crypto process");
-	TEST_ASSERT_NOT_EQUAL(ut_params->op->status,
-			RTE_CRYPTO_OP_STATUS_SUCCESS,
-			"authentication not failed");
-
-	ut_params->obuf = ut_params->op->sym->m_src;
-	TEST_ASSERT_NOT_NULL(ut_params->obuf, "failed to retrieve obuf");
+	TEST_ASSERT_NULL(ut_params->op, "authentication not failed");
 
 	return 0;
 }
@@ -11149,6 +11399,7 @@ create_aead_operation_SGL(enum rte_crypto_aead_operation op,
 	const unsigned int auth_tag_len = tdata->auth_tag.len;
 	const unsigned int iv_len = tdata->iv.len;
 	unsigned int aad_len = tdata->aad.len;
+	unsigned int aad_len_pad = 0;
 
 	/* Generate Crypto op data structure */
 	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
@@ -11203,8 +11454,10 @@ create_aead_operation_SGL(enum rte_crypto_aead_operation op,
 
 		rte_memcpy(iv_ptr, tdata->iv.data, iv_len);
 
+		aad_len_pad = RTE_ALIGN_CEIL(aad_len, 16);
+
 		sym_op->aead.aad.data = (uint8_t *)rte_pktmbuf_prepend(
-				ut_params->ibuf, aad_len);
+				ut_params->ibuf, aad_len_pad);
 		TEST_ASSERT_NOT_NULL(sym_op->aead.aad.data,
 				"no room to prepend aad");
 		sym_op->aead.aad.phys_addr = rte_pktmbuf_iova(
@@ -11219,7 +11472,7 @@ create_aead_operation_SGL(enum rte_crypto_aead_operation op,
 	}
 
 	sym_op->aead.data.length = tdata->plaintext.len;
-	sym_op->aead.data.offset = aad_len;
+	sym_op->aead.data.offset = aad_len_pad;
 
 	return 0;
 }
@@ -11252,7 +11505,7 @@ test_authenticated_encryption_SGL(const struct aead_test_data *tdata,
 	int ecx = 0;
 	void *digest_mem = NULL;
 
-	uint32_t prepend_len = tdata->aad.len;
+	uint32_t prepend_len = RTE_ALIGN_CEIL(tdata->aad.len, 16);
 
 	if (tdata->plaintext.len % fragsz != 0) {
 		if (tdata->plaintext.len / fragsz + 1 > SGL_MAX_NO)
@@ -11915,6 +12168,8 @@ static struct unit_test_suite cryptodev_qat_testsuite  = {
 			test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_400B),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_AES_GCM_auth_encrypt_SGL_out_of_place_1500B_2000B),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_AES_GCM_auth_encrypt_SGL_out_of_place_400B_1seg),
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_AES_GCM_authenticated_encryption_test_case_1),
 		TEST_CASE_ST(ut_setup, ut_teardown,
@@ -12288,6 +12543,68 @@ static struct unit_test_suite cryptodev_qat_testsuite  = {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 		   test_verify_aes_cmac_aes_ctr_digest_enc_test_case_1_oop_sgl),
 
+		/** AUTH ZUC + CIPHER SNOW3G */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_zuc_cipher_snow_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_zuc_cipher_snow_test_case_1),
+		/** AUTH AES CMAC + CIPHER SNOW3G */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_aes_cmac_cipher_snow_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_aes_cmac_cipher_snow_test_case_1),
+		/** AUTH ZUC + CIPHER AES CTR */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_zuc_cipher_aes_ctr_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_zuc_cipher_aes_ctr_test_case_1),
+		/** AUTH SNOW3G + CIPHER AES CTR */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_snow_cipher_aes_ctr_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_snow_cipher_aes_ctr_test_case_1),
+		/** AUTH SNOW3G + CIPHER ZUC */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_snow_cipher_zuc_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_snow_cipher_zuc_test_case_1),
+		/** AUTH AES CMAC + CIPHER ZUC */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_aes_cmac_cipher_zuc_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_aes_cmac_cipher_zuc_test_case_1),
+
+		/** AUTH NULL + CIPHER SNOW3G */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_null_cipher_snow_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_null_cipher_snow_test_case_1),
+		/** AUTH NULL + CIPHER ZUC */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_null_cipher_zuc_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_null_cipher_zuc_test_case_1),
+		/** AUTH SNOW3G + CIPHER NULL */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_snow_cipher_null_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_snow_cipher_null_test_case_1),
+		/** AUTH ZUC + CIPHER NULL */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_zuc_cipher_null_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_zuc_cipher_null_test_case_1),
+		/** AUTH NULL + CIPHER AES CTR */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_null_cipher_aes_ctr_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_null_cipher_aes_ctr_test_case_1),
+		/** AUTH AES CMAC + CIPHER NULL */
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_auth_aes_cmac_cipher_null_test_case_1),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_verify_auth_aes_cmac_cipher_null_test_case_1),
+
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/dpdk/app/test/test_cryptodev_aes_test_vectors.h b/dpdk/app/test/test_cryptodev_aes_test_vectors.h
index 8307fcf9ae..66994b659a 100644
--- a/dpdk/app/test/test_cryptodev_aes_test_vectors.h
+++ b/dpdk/app/test/test_cryptodev_aes_test_vectors.h
@@ -358,69 +358,69 @@ static const struct blockcipher_test_data null_test_data_chain_x1_multiple = {
 
 static const uint8_t ciphertext512_aes128cbc_aad[] = {
 	0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
-	0x6F, 0x75, 0x73, 0x79, 0x6D, 0x70, 0xB4, 0xAD,
-	0x09, 0x7C, 0xD7, 0x52, 0xD6, 0xF2, 0xBF, 0xD1,
-	0x9D, 0x79, 0xC6, 0xB6, 0x8F, 0x94, 0xEB, 0xD8,
-	0xBA, 0x5E, 0x01, 0x49, 0x7D, 0xB3, 0xC5, 0xFE,
-	0x18, 0xF4, 0xE3, 0x60, 0x8C, 0x84, 0x68, 0x13,
-	0x33, 0x06, 0x85, 0x60, 0xD3, 0xE7, 0x8A, 0xB5,
-	0x23, 0xA2, 0xDE, 0x52, 0x5C, 0xB6, 0x26, 0x37,
-	0xBB, 0x23, 0x8A, 0x38, 0x07, 0x85, 0xB6, 0x2E,
-	0xC3, 0x69, 0x57, 0x79, 0x6B, 0xE4, 0xD7, 0x86,
-	0x23, 0x72, 0x4C, 0x65, 0x49, 0x08, 0x1E, 0xF3,
-	0xCC, 0x71, 0x4C, 0x45, 0x97, 0x03, 0xBC, 0xA0,
-	0x9D, 0xF0, 0x4F, 0x5D, 0xEC, 0x40, 0x6C, 0xC6,
-	0x52, 0xC0, 0x9D, 0x1C, 0xDC, 0x8B, 0xC2, 0xFA,
-	0x35, 0xA7, 0x3A, 0x00, 0x04, 0x1C, 0xA6, 0x91,
-	0x5D, 0xEB, 0x07, 0xA1, 0xB9, 0x3E, 0xD1, 0xB6,
-	0xCA, 0x96, 0xEC, 0x71, 0xF7, 0x7D, 0xB6, 0x09,
-	0x3D, 0x19, 0x6E, 0x75, 0x03, 0xC3, 0x1A, 0x4E,
-	0x5B, 0x4D, 0xEA, 0xD9, 0x92, 0x96, 0x01, 0xFB,
-	0xA3, 0xC2, 0x6D, 0xC4, 0x17, 0x6B, 0xB4, 0x3B,
-	0x1E, 0x87, 0x54, 0x26, 0x95, 0x63, 0x07, 0x73,
-	0xB6, 0xBA, 0x52, 0xD7, 0xA7, 0xD0, 0x9C, 0x75,
-	0x8A, 0xCF, 0xC4, 0x3C, 0x4A, 0x55, 0x0E, 0x53,
-	0xEC, 0xE0, 0x31, 0x51, 0xB7, 0xB7, 0xD2, 0xB4,
-	0xF3, 0x2B, 0x70, 0x6D, 0x15, 0x9E, 0x57, 0x30,
-	0x72, 0xE5, 0xA4, 0x71, 0x5F, 0xA4, 0xE8, 0x7C,
-	0x46, 0x58, 0x36, 0x71, 0x91, 0x55, 0xAA, 0x99,
-	0x3B, 0x3F, 0xF6, 0xA2, 0x9D, 0x27, 0xBF, 0xC2,
-	0x62, 0x2C, 0x85, 0xB7, 0x51, 0xDD, 0xFD, 0x7B,
-	0x8B, 0xB5, 0xDD, 0x2A, 0x73, 0xF8, 0x93, 0x9A,
-	0x3F, 0xAD, 0x1D, 0xF0, 0x46, 0xD1, 0x76, 0x83,
-	0x71, 0x4E, 0xD3, 0x0D, 0x64, 0x8C, 0xC3, 0xE6,
-	0x03, 0xED, 0xE8, 0x53, 0x23, 0x1A, 0xC7, 0x86,
-	0xEB, 0x87, 0xD6, 0x78, 0xF9, 0xFB, 0x9C, 0x1D,
-	0xE7, 0x4E, 0xC0, 0x70, 0x27, 0x7A, 0x43, 0xE2,
-	0x5D, 0xA4, 0x10, 0x40, 0xBE, 0x61, 0x0D, 0x2B,
-	0x25, 0x08, 0x75, 0x91, 0xB5, 0x5A, 0x26, 0xC8,
-	0x32, 0xA7, 0xC6, 0x88, 0xBF, 0x75, 0x94, 0xCC,
-	0x58, 0xA4, 0xFE, 0x2F, 0xF7, 0x5C, 0xD2, 0x36,
-	0x66, 0x55, 0xF0, 0xEA, 0xF5, 0x64, 0x43, 0xE7,
-	0x6D, 0xE0, 0xED, 0xA1, 0x10, 0x0A, 0x84, 0x07,
-	0x11, 0x88, 0xFA, 0xA1, 0xD3, 0xA0, 0x00, 0x5D,
-	0xEB, 0xB5, 0x62, 0x01, 0x72, 0xC1, 0x9B, 0x39,
-	0x0B, 0xD3, 0xAF, 0x04, 0x19, 0x42, 0xEC, 0xFF,
-	0x4B, 0xB3, 0x5E, 0x87, 0x27, 0xE4, 0x26, 0x57,
-	0x76, 0xCD, 0x36, 0x31, 0x5B, 0x94, 0x74, 0xFF,
-	0x33, 0x91, 0xAA, 0xD1, 0x45, 0x34, 0xC2, 0x11,
-	0xF0, 0x35, 0x44, 0xC9, 0xD5, 0xA2, 0x5A, 0xC2,
-	0xE9, 0x9E, 0xCA, 0xE2, 0x6F, 0xD2, 0x40, 0xB4,
-	0x93, 0x42, 0x78, 0x20, 0x92, 0x88, 0xC7, 0x16,
-	0xCF, 0x15, 0x54, 0x7B, 0xE1, 0x46, 0x38, 0x69,
-	0xB8, 0xE4, 0xF1, 0x81, 0xF0, 0x08, 0x6F, 0x92,
-	0x6D, 0x1A, 0xD9, 0x93, 0xFA, 0xD7, 0x35, 0xFE,
-	0x7F, 0x59, 0x43, 0x1D, 0x3A, 0x3B, 0xFC, 0xD0,
-	0x14, 0x95, 0x1E, 0xB2, 0x04, 0x08, 0x4F, 0xC6,
-	0xEA, 0xE8, 0x22, 0xF3, 0xD7, 0x66, 0x93, 0xAA,
-	0xFD, 0xA0, 0xFE, 0x03, 0x96, 0x54, 0x78, 0x35,
-	0x18, 0xED, 0xB7, 0x2F, 0x40, 0xE3, 0x8E, 0x22,
-	0xC6, 0xDA, 0xB0, 0x8E, 0xA0, 0xA1, 0x62, 0x03,
-	0x63, 0x34, 0x11, 0xF5, 0x9E, 0xAA, 0x6B, 0xC4,
-	0x14, 0x75, 0x4C, 0xF4, 0xD8, 0xD9, 0xF1, 0x76,
-	0xE3, 0xD3, 0x55, 0xCE, 0x22, 0x7D, 0x4A, 0xB7,
-	0xBB, 0x7F, 0x4F, 0x09, 0x88, 0x70, 0x6E, 0x09,
-	0x84, 0x6B, 0x24, 0x19, 0x2C, 0x20, 0x73, 0x75
+	0x1D, 0x7C, 0x76, 0xED, 0xC2, 0x10, 0x3C, 0xB5,
+	0x14, 0x07, 0x3C, 0x33, 0x7B, 0xBE, 0x9E, 0xA9,
+	0x01, 0xC5, 0xAA, 0xA6, 0xB6, 0x7A, 0xE1, 0xDB,
+	0x39, 0xAA, 0xAA, 0xF4, 0xEE, 0xA7, 0x71, 0x71,
+	0x78, 0x0D, 0x5A, 0xD4, 0xF9, 0xCD, 0x75, 0xD1,
+	0x9C, 0x7F, 0xC8, 0x58, 0x46, 0x7A, 0xD1, 0x81,
+	0xEA, 0xCC, 0x08, 0xDC, 0x82, 0x73, 0x22, 0x08,
+	0x11, 0x73, 0x7C, 0xB1, 0x84, 0x6A, 0x8E, 0x67,
+	0x3F, 0x5D, 0xDB, 0x0E, 0xE2, 0xC2, 0xCB, 0x6D,
+	0x88, 0xEC, 0x3F, 0x50, 0x44, 0xD3, 0x47, 0x6E,
+	0xDD, 0x42, 0xDC, 0x2A, 0x5E, 0x5C, 0x50, 0x24,
+	0x57, 0x8A, 0xE7, 0xC5, 0x53, 0x6D, 0x89, 0x33,
+	0x21, 0x65, 0x82, 0xD6, 0xE9, 0xE7, 0x77, 0x10,
+	0xC2, 0x09, 0x91, 0xC1, 0x42, 0x62, 0x36, 0xF4,
+	0x43, 0x37, 0x95, 0xB3, 0x7E, 0x21, 0xC5, 0x3E,
+	0x65, 0xCB, 0xB6, 0xAA, 0xEC, 0xA5, 0xC6, 0x5C,
+	0x4D, 0xBE, 0x14, 0xF1, 0x98, 0xBF, 0x6C, 0x8A,
+	0x9E, 0x9F, 0xD4, 0xB4, 0xF2, 0x22, 0x96, 0x99,
+	0x37, 0x32, 0xB6, 0xC1, 0x04, 0x66, 0x52, 0x37,
+	0x5D, 0x5F, 0x58, 0x92, 0xC9, 0x97, 0xEA, 0x60,
+	0x60, 0x27, 0x57, 0xF9, 0x47, 0x4F, 0xBC, 0xDF,
+	0x05, 0xBD, 0x37, 0x87, 0xBB, 0x09, 0xA5, 0xBE,
+	0xC1, 0xFC, 0x32, 0x86, 0x6A, 0xB7, 0x8B, 0x1E,
+	0x6B, 0xCE, 0x8D, 0x81, 0x63, 0x4C, 0xF2, 0x7F,
+	0xD1, 0x45, 0x82, 0xE8, 0x0D, 0x1C, 0x4D, 0xA8,
+	0xBF, 0x2D, 0x2B, 0x52, 0xE5, 0xDB, 0xAB, 0xFD,
+	0x04, 0xA2, 0xA1, 0x1E, 0x21, 0x1D, 0x06, 0x9A,
+	0xC2, 0x7D, 0x99, 0xFC, 0xB4, 0x72, 0x89, 0x41,
+	0x55, 0x69, 0xFA, 0x1F, 0x78, 0x2F, 0x35, 0x59,
+	0xD7, 0x59, 0x6D, 0xA6, 0x45, 0xC9, 0x2B, 0x06,
+	0x6C, 0xEC, 0x83, 0x34, 0xA5, 0x08, 0xDB, 0x6F,
+	0xDE, 0x75, 0x21, 0x9B, 0xB0, 0xCB, 0x0A, 0xAE,
+	0x22, 0x99, 0x74, 0x1C, 0x9D, 0x37, 0x0E, 0xC6,
+	0x3A, 0x45, 0x49, 0xE5, 0xE3, 0x21, 0x11, 0xEA,
+	0x34, 0x25, 0xD5, 0x76, 0xB0, 0x30, 0x19, 0x87,
+	0x14, 0x3A, 0x10, 0x6F, 0x6D, 0xDD, 0xE9, 0x60,
+	0x6A, 0x00, 0x6A, 0x4C, 0x5B, 0x85, 0x3E, 0x1A,
+	0x41, 0xFA, 0xDE, 0x2D, 0x2F, 0x2E, 0x5B, 0x79,
+	0x09, 0x66, 0x65, 0xD0, 0xDB, 0x32, 0x05, 0xB5,
+	0xEA, 0xFB, 0x6A, 0xD5, 0x43, 0xF8, 0xBD, 0x98,
+	0x7B, 0x8E, 0x3B, 0x85, 0x89, 0x5D, 0xC5, 0x59,
+	0x54, 0x22, 0x75, 0xA8, 0x60, 0xDC, 0x0A, 0x37,
+	0x8C, 0xD8, 0x05, 0xEA, 0x62, 0x62, 0x71, 0x98,
+	0x0C, 0xCB, 0xCE, 0x0A, 0xD9, 0xE6, 0xE8, 0xA7,
+	0xB3, 0x2D, 0x89, 0xA7, 0x60, 0xF0, 0x42, 0xA7,
+	0x3D, 0x80, 0x44, 0xE7, 0xC1, 0xA6, 0x88, 0xB1,
+	0x4F, 0xC0, 0xB1, 0xAF, 0x40, 0xF3, 0x54, 0x72,
+	0x8F, 0xAF, 0x47, 0x96, 0x19, 0xEB, 0xA5, 0x5C,
+	0x00, 0x3B, 0x36, 0xC8, 0x3F, 0x1E, 0x63, 0x54,
+	0xF3, 0x3D, 0x85, 0x44, 0x9B, 0x9B, 0x20, 0xE3,
+	0x9D, 0xEF, 0x62, 0x21, 0xA1, 0x0B, 0x78, 0xF4,
+	0x2B, 0x89, 0x66, 0x5E, 0x97, 0xC6, 0xC4, 0x55,
+	0x35, 0x32, 0xD7, 0x44, 0x95, 0x9A, 0xE7, 0xF2,
+	0x57, 0x52, 0x5B, 0x92, 0x86, 0x8F, 0x8B, 0xCF,
+	0x41, 0x89, 0xF6, 0x2A, 0xD3, 0x42, 0x87, 0x43,
+	0x56, 0x1F, 0x0E, 0x49, 0xF1, 0x32, 0x6D, 0xA8,
+	0x62, 0xDF, 0x47, 0xBB, 0xB6, 0x53, 0xF8, 0x5C,
+	0x36, 0xDA, 0x34, 0x34, 0x2D, 0x2E, 0x1D, 0x33,
+	0xAF, 0x6A, 0x1E, 0xF1, 0xC9, 0x72, 0xB5, 0x3C,
+	0x64, 0x4C, 0x96, 0x12, 0x78, 0x67, 0x6A, 0xE5,
+	0x8B, 0x05, 0x80, 0xAE, 0x7D, 0xE5, 0x9B, 0x24,
+	0xDB, 0xFF, 0x1E, 0xB8, 0x36, 0x6D, 0x3D, 0x5D,
+	0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
 };
 
 /* AES128-CTR-SHA1 test vector */
diff --git a/dpdk/app/test/test_cryptodev_asym.c b/dpdk/app/test/test_cryptodev_asym.c
index 69df293041..a0802994fa 100644
--- a/dpdk/app/test/test_cryptodev_asym.c
+++ b/dpdk/app/test/test_cryptodev_asym.c
@@ -933,8 +933,9 @@ testsuite_setup(void)
 	}
 
 	/* setup asym session pool */
-	unsigned int session_size =
-		rte_cryptodev_asym_get_private_session_size(dev_id);
+	unsigned int session_size = RTE_MAX(
+		rte_cryptodev_asym_get_private_session_size(dev_id),
+		rte_cryptodev_asym_get_header_session_size());
 	/*
 	 * Create mempool with TEST_NUM_SESSIONS * 2,
 	 * to include the session headers
diff --git a/dpdk/app/test/test_cryptodev_blockcipher.c b/dpdk/app/test/test_cryptodev_blockcipher.c
index 5bfe2d009f..2f91d000a2 100644
--- a/dpdk/app/test/test_cryptodev_blockcipher.c
+++ b/dpdk/app/test/test_cryptodev_blockcipher.c
@@ -93,7 +93,7 @@ test_blockcipher_one_case(const struct blockcipher_test_case *t,
 		uint64_t feat_flags = dev_info.feature_flags;
 		uint64_t oop_flag = RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT;
 
-		if (t->feature_mask && BLOCKCIPHER_TEST_FEATURE_OOP) {
+		if (t->feature_mask & BLOCKCIPHER_TEST_FEATURE_OOP) {
 			if (!(feat_flags & oop_flag)) {
 				printf("Device doesn't support out-of-place "
 					"scatter-gather in input mbuf. "
diff --git a/dpdk/app/test/test_cryptodev_hash_test_vectors.h b/dpdk/app/test/test_cryptodev_hash_test_vectors.h
index cff2831185..394bb6b60b 100644
--- a/dpdk/app/test/test_cryptodev_hash_test_vectors.h
+++ b/dpdk/app/test/test_cryptodev_hash_test_vectors.h
@@ -460,6 +460,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha1_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -473,6 +474,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha1_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -540,6 +542,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha224_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -553,6 +556,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha224_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -596,6 +600,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha256_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -609,6 +614,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha256_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -654,6 +660,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha384_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -667,6 +674,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha384_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -712,6 +720,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha512_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_GEN,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
@@ -724,6 +733,7 @@ static const struct blockcipher_test_case hash_test_cases[] = {
 		.test_data = &sha512_test_vector,
 		.op_mask = BLOCKCIPHER_TEST_OP_AUTH_VERIFY,
 		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL |
+			    BLOCKCIPHER_TEST_TARGET_PMD_QAT |
 			    BLOCKCIPHER_TEST_TARGET_PMD_CCP |
 			    BLOCKCIPHER_TEST_TARGET_PMD_MVSAM |
 #if IMB_VERSION_NUM >= IMB_VERSION(0, 52, 0)
diff --git a/dpdk/app/test/test_cryptodev_mixed_test_vectors.h b/dpdk/app/test/test_cryptodev_mixed_test_vectors.h
index bca47c05c8..f50dcb0457 100644
--- a/dpdk/app/test/test_cryptodev_mixed_test_vectors.h
+++ b/dpdk/app/test/test_cryptodev_mixed_test_vectors.h
@@ -126,9 +126,9 @@ struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_aes_ctr_test_case_1 = {
 			0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
 			0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
 			0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
-			0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
+			0x5A, 0x5A, 0x5A, 0x5A
 		},
-		.len_bits = 128 << 3,
+		.len_bits = 124 << 3,
 	},
 	.ciphertext = {
 		.data = {
@@ -169,4 +169,1320 @@ struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_aes_ctr_test_case_1 = {
 	}
 };
 
+struct mixed_cipher_auth_test_data auth_zuc_cipher_snow_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_ZUC_EIA3,
+	.auth_key = {
+		.data = {
+			0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+			0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+			0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 73 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+	.cipher_key = {
+		.data = {
+			0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+			0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+			0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 77 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+			0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+			0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+			0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+			0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+			0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+			0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+			0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+			0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+			0x00
+		},
+		.len_bits = 73 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x18, 0x46, 0xE1, 0xC5, 0x2C, 0x85, 0x93, 0x22,
+			0x84, 0x80, 0xD6, 0x84, 0x5C, 0x99, 0x55, 0xE0,
+			0xD5, 0x02, 0x41, 0x74, 0x4A, 0xD2, 0x8E, 0x7E,
+			0xB9, 0x79, 0xD3, 0xE5, 0x76, 0x75, 0xD5, 0x59,
+			0x26, 0xD7, 0x06, 0x2D, 0xF4, 0x71, 0x26, 0x40,
+			0xAC, 0x77, 0x62, 0xAC, 0x35, 0x0D, 0xC5, 0x35,
+			0xF8, 0x03, 0x54, 0x52, 0x2E, 0xCA, 0x14, 0xD8,
+			0x2E, 0x6C, 0x0E, 0x7A, 0x09, 0xE7, 0x20, 0xDD,
+			0x7C, 0xE3, 0x28, 0x77, 0x53, 0x65, 0xBA, 0x54,
+			0xE8, 0x25, 0x04, 0x52, 0xFD
+		},
+		.len_bits = 77 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x25, 0x04, 0x52, 0xFD
+		},
+		.len = 4,
+		.offset = 73,
+	},
+	.validDataLen = {
+		.len_bits = 77 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 77 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 73 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_snow_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+	.auth_key = {
+		.data = {
+			0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+			0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+		},
+		.len = 0,
+	},
+	.auth = {
+		.len_bits = 512 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+	.cipher_key = {
+		.data = {
+			0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+			0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+		},
+		.len = 0,
+	},
+	.cipher = {
+		.len_bits = 516 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+			0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+			0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+			0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+			0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+			0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+			0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+			0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+			0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+			0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+			0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+			0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+			0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+			0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+			0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+			0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+			0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+			0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+			0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+			0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+			0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+			0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+			0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+			0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+			0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+			0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+			0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+			0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+			0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+			0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+			0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+			0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+			0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+			0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+			0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+			0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+			0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+			0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+			0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+			0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+			0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+			0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+			0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+			0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+			0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+			0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+			0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+			0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+			0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+			0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+			0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+			0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+			0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+			0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+			0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+			0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
+		},
+		.len_bits = 512 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x8A, 0xA9, 0x74, 0x31, 0xB1, 0xF2, 0xAB, 0x00,
+			0xD6, 0x3D, 0xFA, 0xBD, 0xD9, 0x65, 0x52, 0x80,
+			0xB5, 0x98, 0x20, 0xFF, 0x8D, 0x1C, 0x0F, 0x53,
+			0xDD, 0x79, 0xCC, 0x9D, 0x7A, 0x6D, 0x76, 0x06,
+			0xB6, 0xF4, 0xAC, 0xDA, 0xF2, 0x24, 0x02, 0x58,
+			0x5F, 0xE3, 0xD4, 0xF7, 0x0B, 0x3B, 0x1C, 0x4C,
+			0x0B, 0x4C, 0xC7, 0x4D, 0x3D, 0xFA, 0x28, 0xD9,
+			0xA0, 0x90, 0x3E, 0x91, 0xDC, 0xC4, 0xE1, 0x2E,
+			0x7C, 0xB4, 0xBD, 0xE0, 0x9E, 0xC8, 0x33, 0x42,
+			0x0E, 0x84, 0xEF, 0x3C, 0xF1, 0x8B, 0x2C, 0xBD,
+			0x33, 0x70, 0x22, 0xBA, 0xD4, 0x0B, 0xB2, 0x83,
+			0x7F, 0x27, 0x51, 0x92, 0xD1, 0x40, 0x1E, 0xCD,
+			0x62, 0x0F, 0x61, 0x5F, 0xB4, 0xB1, 0x0D, 0x1A,
+			0x16, 0x1B, 0xE8, 0xA8, 0x2B, 0x45, 0xBA, 0x56,
+			0x30, 0xD0, 0xE3, 0xCA, 0x4D, 0x23, 0xA3, 0x38,
+			0xD6, 0x2C, 0xE4, 0x8D, 0xFF, 0x23, 0x97, 0x9E,
+			0xE9, 0xBD, 0x70, 0xAF, 0x6B, 0x68, 0xA7, 0x21,
+			0x3C, 0xFB, 0xB2, 0x99, 0x4D, 0xE9, 0x70, 0x56,
+			0x36, 0xB8, 0xD7, 0xE0, 0xEB, 0x62, 0xA1, 0x79,
+			0xF9, 0xD6, 0xAD, 0x83, 0x75, 0x54, 0xF5, 0x45,
+			0x82, 0xE8, 0xD6, 0xA9, 0x76, 0x11, 0xC7, 0x81,
+			0x2C, 0xBA, 0x67, 0xB5, 0xDB, 0xE5, 0xF2, 0x6B,
+			0x7D, 0x9F, 0x4E, 0xDC, 0xA1, 0x62, 0xF1, 0xF0,
+			0xAD, 0xD4, 0x7A, 0xA3, 0xF3, 0x76, 0x29, 0xA4,
+			0xB7, 0xF3, 0x31, 0x84, 0xE7, 0x1F, 0x0D, 0x01,
+			0xBD, 0x46, 0x07, 0x51, 0x05, 0x76, 0xE2, 0x95,
+			0xF8, 0x48, 0x18, 0x8A, 0x1E, 0x92, 0x8B, 0xBC,
+			0x30, 0x05, 0xF5, 0xD6, 0x96, 0xEF, 0x78, 0xB6,
+			0xF3, 0xEC, 0x4C, 0xB1, 0x88, 0x8B, 0x63, 0x40,
+			0x07, 0x37, 0xB4, 0x1A, 0xBD, 0xE9, 0x38, 0xB4,
+			0x31, 0x35, 0x9D, 0x0C, 0xF1, 0x24, 0x0E, 0xD2,
+			0xAE, 0x39, 0xA6, 0x41, 0x3C, 0x91, 0x6A, 0x4B,
+			0xEC, 0x46, 0x76, 0xB4, 0x15, 0xC3, 0x58, 0x96,
+			0x69, 0x02, 0x21, 0x37, 0x65, 0xDF, 0xA6, 0x43,
+			0x78, 0x81, 0x8B, 0x39, 0x37, 0xE3, 0xF3, 0xD9,
+			0xA2, 0xAA, 0x3F, 0xA9, 0x21, 0x24, 0x93, 0x4A,
+			0xB0, 0xDE, 0x22, 0x5F, 0xF8, 0xD3, 0xCC, 0x13,
+			0x5C, 0xC2, 0x5C, 0x98, 0x6D, 0xFB, 0x34, 0x26,
+			0xE2, 0xC9, 0x26, 0x23, 0x41, 0xAB, 0xC3, 0x8A,
+			0xEC, 0x62, 0xA9, 0x5B, 0x51, 0xB9, 0x10, 0x9D,
+			0xB1, 0xBB, 0xDE, 0x78, 0xDE, 0xE7, 0xF0, 0x9F,
+			0x91, 0x6C, 0x4D, 0xFC, 0xB3, 0x9C, 0xFF, 0xA4,
+			0x9D, 0xB8, 0xCD, 0xF6, 0xA8, 0x6A, 0xDB, 0x3B,
+			0x82, 0xFE, 0xCD, 0x6B, 0x08, 0x0A, 0x5E, 0x76,
+			0xE9, 0xB3, 0xA2, 0x78, 0x25, 0xDB, 0xB1, 0x76,
+			0x42, 0x2C, 0xFB, 0x20, 0x87, 0x81, 0x76, 0x17,
+			0x99, 0xFD, 0x56, 0x52, 0xE2, 0xB0, 0x8E, 0x1B,
+			0x99, 0xB3, 0x6B, 0x16, 0xC5, 0x4F, 0x0D, 0xBB,
+			0x0E, 0xB7, 0x54, 0x63, 0xD9, 0x67, 0xD9, 0x85,
+			0x1F, 0xA8, 0xF0, 0xF0, 0xB0, 0x41, 0xDC, 0xBC,
+			0x75, 0xEE, 0x23, 0x7D, 0x40, 0xCE, 0xB8, 0x0A,
+			0x6D, 0xC1, 0xD7, 0xCB, 0xAE, 0xCE, 0x91, 0x9E,
+			0x3E, 0x5A, 0x76, 0xF8, 0xC0, 0xF2, 0x7F, 0x0B,
+			0xD2, 0x5F, 0x63, 0xBE, 0xB2, 0x81, 0x8E, 0x6D,
+			0xB3, 0x6B, 0x67, 0x9D, 0xAC, 0xE2, 0xDB, 0x7C,
+			0x11, 0x19, 0x55, 0x55, 0x11, 0xED, 0x7F, 0x4E,
+			0x9E, 0x4B, 0x6E, 0x01, 0x74, 0x4A, 0xE8, 0x78,
+			0xEC, 0xCD, 0xF7, 0xA2, 0x6E, 0xDB, 0xB6, 0x3B,
+			0x4D, 0x2C, 0x09, 0x62, 0x57, 0x6E, 0x38, 0x8A,
+			0x61, 0x17, 0x00, 0xE9, 0x86, 0x7F, 0x3D, 0x93,
+			0xBC, 0xC3, 0x27, 0x90, 0x7E, 0x41, 0x81, 0xBA,
+			0x74, 0x70, 0x19, 0xE8, 0xD2, 0x88, 0x61, 0xDF,
+			0xB4, 0xED, 0xA4, 0x9D, 0x3D, 0xED, 0x95, 0x65,
+			0xCA, 0xFF, 0x8D, 0x58, 0x63, 0x10, 0x9D, 0xBE,
+			0x78, 0x81, 0x47, 0x38
+		},
+		.len_bits = 516 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x78, 0x81, 0x47, 0x38
+		},
+		.len = 4,
+		.offset = 512,
+	},
+	.validDataLen = {
+		.len_bits = 516 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 516 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 512 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_zuc_cipher_aes_ctr_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_ZUC_EIA3,
+	.auth_key = {
+		.data = {
+			0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+			0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+			0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 73 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+	.cipher_key = {
+		.data = {
+			0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+			0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+			0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 77 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+			0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+			0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+			0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+			0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+			0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+			0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+			0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+			0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+			0x00
+		},
+		.len_bits = 73 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x53, 0x92, 0x9F, 0x88, 0x32, 0xA1, 0x6D, 0x66,
+			0x00, 0x32, 0x29, 0xF9, 0x14, 0x75, 0x6D, 0xB3,
+			0xEB, 0x64, 0x25, 0x09, 0xE1, 0x80, 0x31, 0x8C,
+			0xF8, 0x47, 0x64, 0xAA, 0x07, 0x8E, 0x06, 0xBF,
+			0x05, 0xD7, 0x43, 0xEE, 0xFF, 0x11, 0x33, 0x4A,
+			0x82, 0xCF, 0x88, 0x6F, 0x33, 0xB2, 0xB5, 0x67,
+			0x50, 0x0A, 0x74, 0x2D, 0xE4, 0x56, 0x40, 0x31,
+			0xEE, 0xB3, 0x6C, 0x6E, 0x6A, 0x7B, 0x20, 0xBA,
+			0x4E, 0x44, 0x34, 0xC8, 0x62, 0x21, 0x8C, 0x45,
+			0xD7, 0x85, 0x44, 0xF4, 0x7E
+		},
+		.len_bits = 77 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x85, 0x44, 0xF4, 0x7E
+		},
+		.len = 4,
+		.offset = 73,
+	},
+	.validDataLen = {
+		.len_bits = 77 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 77 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 73 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_snow_cipher_aes_ctr_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+	.auth_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 48 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+	.cipher_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 52 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+		},
+		.len_bits = 48 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x91, 0x96, 0x28, 0xB4, 0x89, 0x74, 0xF6, 0x5E,
+			0x98, 0x58, 0xA1, 0xD3, 0x0E, 0xE3, 0xFC, 0x39,
+			0xDB, 0x36, 0xE4, 0x97, 0x74, 0x5B, 0x5E, 0xD4,
+			0x1B, 0x8A, 0xC5, 0x9D, 0xDF, 0x96, 0x97, 0x5F,
+			0x58, 0x4A, 0x75, 0x74, 0x27, 0x07, 0xF3, 0x7F,
+			0xCE, 0x2C, 0x4A, 0x6C, 0xE5, 0x19, 0xE7, 0x8B,
+			0xF3, 0x21, 0x84, 0x6C
+		},
+		.len_bits = 52 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0xF3, 0x21, 0x84, 0x6C
+		},
+		.len = 4,
+		.offset = 48,
+	},
+	.validDataLen = {
+		.len_bits = 52 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 52 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 48 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_snow_cipher_zuc_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+	.auth_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 48 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+	.cipher_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 52 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+		},
+		.len_bits = 48 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x52, 0x11, 0xCD, 0xFF, 0xF8, 0x88, 0x61, 0x1E,
+			0xF5, 0xD2, 0x8E, 0xEB, 0x2A, 0x49, 0x18, 0x1F,
+			0xF4, 0xDA, 0x8B, 0x19, 0x60, 0x0B, 0x92, 0x9E,
+			0x79, 0x2A, 0x5B, 0x0B, 0x7E, 0xC6, 0x22, 0x36,
+			0x74, 0xA4, 0x6C, 0xBC, 0xF5, 0x25, 0x69, 0xAE,
+			0xDA, 0x04, 0xB9, 0xAF, 0x16, 0x42, 0x0F, 0xCB,
+			0x3E, 0xC9, 0x49, 0xE9
+		},
+		.len_bits = 52 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x3E, 0xC9, 0x49, 0xE9
+		},
+		.len = 4,
+		.offset = 48,
+	},
+	.validDataLen = {
+		.len_bits = 52 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 52 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 48 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_zuc_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+	.auth_key = {
+		.data = {
+			0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+			0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+		},
+		.len = 0,
+	},
+	.auth = {
+		.len_bits = 512 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+	.cipher_key = {
+		.data = {
+			0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+			0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+		},
+		.len = 0,
+	},
+	.cipher = {
+		.len_bits = 516 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+			0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+			0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+			0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+			0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+			0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+			0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+			0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+			0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+			0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+			0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+			0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+			0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+			0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+			0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+			0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+			0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+			0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+			0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+			0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+			0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+			0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+			0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+			0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+			0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+			0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+			0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+			0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+			0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+			0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+			0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+			0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+			0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+			0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+			0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+			0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+			0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+			0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+			0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+			0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+			0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+			0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+			0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+			0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+			0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+			0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+			0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+			0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+			0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+			0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+			0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+			0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+			0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+			0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+			0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+			0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
+		},
+		.len_bits = 512 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x3C, 0x89, 0x1C, 0xE5, 0xB7, 0xDE, 0x61, 0x4D,
+			0x05, 0x37, 0x3F, 0x40, 0xC9, 0xCF, 0x10, 0x07,
+			0x7F, 0x18, 0xC5, 0x96, 0x21, 0xA9, 0xCF, 0xF5,
+			0xBB, 0x9C, 0x22, 0x72, 0x00, 0xBE, 0xAC, 0x4B,
+			0x55, 0x02, 0x19, 0x2B, 0x37, 0x64, 0x15, 0x6B,
+			0x54, 0x74, 0xAE, 0x0F, 0xE7, 0x68, 0xB3, 0x92,
+			0x17, 0x26, 0x75, 0xEE, 0x0B, 0xE9, 0x46, 0x3C,
+			0x6E, 0x76, 0x52, 0x14, 0x2B, 0xD0, 0xB6, 0xD0,
+			0x09, 0x07, 0x17, 0x12, 0x58, 0x61, 0xE8, 0x2A,
+			0x7C, 0x55, 0x67, 0x66, 0x49, 0xD1, 0x4E, 0x2F,
+			0x06, 0x96, 0x3A, 0xF7, 0x05, 0xE3, 0x65, 0x47,
+			0x7C, 0xBB, 0x66, 0x25, 0xC4, 0x73, 0xB3, 0x7B,
+			0x3D, 0x1D, 0x59, 0x54, 0x4E, 0x38, 0x9C, 0x4D,
+			0x10, 0x4B, 0x49, 0xA4, 0x92, 0xC7, 0xD7, 0x17,
+			0x6F, 0xC0, 0xEE, 0x8D, 0xBE, 0xA5, 0xE3, 0xB9,
+			0xBA, 0x5E, 0x88, 0x36, 0x06, 0x19, 0xB7, 0x86,
+			0x66, 0x19, 0x90, 0xC4, 0xAE, 0xB3, 0xFE, 0xA7,
+			0xCF, 0x2A, 0xD8, 0x6C, 0x0E, 0xD5, 0x24, 0x2A,
+			0x92, 0x93, 0xB9, 0x12, 0xCB, 0x50, 0x0A, 0x22,
+			0xB0, 0x09, 0x06, 0x17, 0x85, 0xC9, 0x03, 0x70,
+			0x18, 0xF2, 0xD5, 0x6A, 0x66, 0xC2, 0xB6, 0xC6,
+			0xA5, 0xA3, 0x24, 0xEC, 0xB9, 0x07, 0xD5, 0x8A,
+			0xA0, 0x44, 0x54, 0xD7, 0x21, 0x9F, 0x02, 0x83,
+			0x78, 0x7B, 0x78, 0x9C, 0x97, 0x2A, 0x36, 0x51,
+			0xAF, 0xE1, 0x79, 0x81, 0x07, 0x53, 0xE4, 0xA0,
+			0xC7, 0xCF, 0x10, 0x7C, 0xB2, 0xE6, 0xA1, 0xFD,
+			0x81, 0x0B, 0x96, 0x50, 0x5D, 0xFE, 0xB3, 0xC6,
+			0x75, 0x00, 0x0C, 0x56, 0x83, 0x9B, 0x7B, 0xF4,
+			0xE0, 0x3A, 0xC0, 0xE1, 0xA9, 0xEC, 0xAC, 0x47,
+			0x24, 0xF5, 0x12, 0x1B, 0xD0, 0x28, 0x32, 0xE2,
+			0x3B, 0x42, 0xC1, 0x5B, 0x98, 0x98, 0x78, 0x2D,
+			0xC1, 0x69, 0x05, 0x37, 0x24, 0xF0, 0x73, 0xBA,
+			0xBE, 0x57, 0xAC, 0x40, 0x9A, 0x91, 0x42, 0x49,
+			0x31, 0x0F, 0xED, 0x45, 0xA8, 0x25, 0xFF, 0x1B,
+			0xF4, 0x2F, 0x61, 0x7A, 0xB0, 0x60, 0xC6, 0x5E,
+			0x0E, 0xF6, 0x96, 0x35, 0x90, 0xAF, 0x3B, 0x9D,
+			0x4D, 0x6C, 0xE7, 0xF2, 0x4F, 0xC0, 0xBA, 0x57,
+			0x92, 0x18, 0xB7, 0xF5, 0x1D, 0x06, 0x81, 0xF6,
+			0xE3, 0xF4, 0x66, 0x8C, 0x33, 0x74, 0xBE, 0x64,
+			0x8C, 0x18, 0xED, 0x7F, 0x68, 0x2A, 0xE4, 0xAF,
+			0xF1, 0x02, 0x07, 0x51, 0x22, 0x96, 0xC8, 0x9E,
+			0x23, 0x7F, 0x6A, 0xD7, 0x80, 0x0F, 0x2D, 0xFC,
+			0xCC, 0xD0, 0x95, 0x86, 0x00, 0x2A, 0x77, 0xDD,
+			0xA2, 0x60, 0x1E, 0x0F, 0x8E, 0x42, 0x44, 0x37,
+			0x7E, 0x33, 0xC4, 0xE0, 0x04, 0x53, 0xF6, 0x3F,
+			0xDD, 0x1D, 0x5E, 0x24, 0xDA, 0xAE, 0xEF, 0x06,
+			0x06, 0x05, 0x13, 0x3A, 0x1E, 0xFF, 0xAD, 0xAD,
+			0xEE, 0x0F, 0x6F, 0x05, 0xA5, 0xFB, 0x3B, 0xC3,
+			0xDB, 0xA0, 0x20, 0xC1, 0x65, 0x8B, 0x39, 0xAB,
+			0xC9, 0xEC, 0xA8, 0x31, 0x85, 0x6C, 0xD2, 0xE4,
+			0x76, 0x77, 0x76, 0xD5, 0x81, 0x01, 0x73, 0x36,
+			0x08, 0x8C, 0xC3, 0xD4, 0x70, 0x7A, 0xA3, 0xDF,
+			0xAD, 0x3A, 0x00, 0x46, 0x88, 0x65, 0x10, 0xBE,
+			0xD8, 0x1C, 0x19, 0x98, 0xE9, 0x29, 0xDD, 0x58,
+			0x46, 0x31, 0xEB, 0x3D, 0xD0, 0x12, 0x02, 0x83,
+			0x15, 0xDD, 0x70, 0x27, 0x0D, 0xB5, 0xBB, 0x0C,
+			0xE3, 0xF1, 0x02, 0xF2, 0xD7, 0x1D, 0x17, 0x6D,
+			0xDF, 0x2A, 0x42, 0x1F, 0x01, 0x5C, 0x68, 0xB1,
+			0x64, 0x74, 0xCE, 0x74, 0xB1, 0x3C, 0x2F, 0x43,
+			0x5F, 0xB7, 0x7E, 0x3E, 0x6F, 0xE3, 0xDC, 0x03,
+			0xD9, 0x0C, 0xDD, 0x42, 0x65, 0x7F, 0xEA, 0x69,
+			0x6F, 0xDB, 0xD7, 0xFB, 0xFF, 0x4D, 0xB4, 0x48,
+			0xFE, 0x0F, 0x59, 0x24, 0x8F, 0x13, 0xA8, 0x60,
+			0xF7, 0x13, 0xE5, 0xB1, 0x8D, 0xB7, 0x70, 0xEE,
+			0x82, 0x8F, 0xCF, 0x7E
+		},
+		.len_bits = 516 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x82, 0x8F, 0xCF, 0x7E
+		},
+		.len = 4,
+		.offset = 512,
+	},
+	.validDataLen = {
+		.len_bits = 516 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 516 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 512 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_null_cipher_snow_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_NULL,
+	.auth_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 44 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+	.cipher_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 48 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A,
+		},
+		.len_bits = 44 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x95, 0x2E, 0x5A, 0xE1, 0x50, 0xB8, 0x59, 0x2A,
+			0x9B, 0xA0, 0x38, 0xA9, 0x8E, 0x2F, 0xED, 0xAB,
+			0xFD, 0xC8, 0x3B, 0x47, 0x46, 0x0B, 0x50, 0x16,
+			0xEC, 0x88, 0x45, 0xB6, 0x05, 0xC7, 0x54, 0xF8,
+			0xBD, 0x91, 0xAA, 0xB6, 0xA4, 0xDC, 0x64, 0xB4,
+			0xCB, 0xEB, 0x97, 0x06, 0x1C, 0xB5, 0x72, 0x34
+		},
+		.len_bits = 48 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x1C, 0xB5, 0x72, 0x34
+		},
+		.len = 4,
+		.offset = 44,
+	},
+	.validDataLen = {
+		.len_bits = 48 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 48 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 44 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_null_cipher_zuc_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_NULL,
+	.auth_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 48 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_ZUC_EEA3,
+	.cipher_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 52 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+		},
+		.len_bits = 48 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x52, 0x11, 0xCD, 0xFF, 0xF8, 0x88, 0x61, 0x1E,
+			0xF5, 0xD2, 0x8E, 0xEB, 0x2A, 0x49, 0x18, 0x1F,
+			0xF4, 0xDA, 0x8B, 0x19, 0x60, 0x0B, 0x92, 0x9E,
+			0x79, 0x2A, 0x5B, 0x0B, 0x7E, 0xC6, 0x22, 0x36,
+			0x74, 0xA4, 0x6C, 0xBC, 0xF5, 0x25, 0x69, 0xAE,
+			0xDA, 0x04, 0xB9, 0xAF, 0x16, 0x42, 0x0F, 0xCB,
+			0x06, 0x7C, 0x1D, 0x29
+		},
+		.len_bits = 52 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x06, 0x7C, 0x1D, 0x29
+		},
+		.len = 4,
+		.offset = 48,
+	},
+	.validDataLen = {
+		.len_bits = 52 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 52 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 48 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_snow_cipher_null_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+	.auth_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 48 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+	.cipher_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 52 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+		},
+		.len_bits = 48 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09,
+			0x38, 0xB5, 0x54, 0xC0
+		},
+		.len_bits = 52 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x38, 0xB5, 0x54, 0xC0
+		},
+		.len = 4,
+		.offset = 48,
+	},
+	.validDataLen = {
+		.len_bits = 52 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 52 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 48 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_zuc_cipher_null_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_ZUC_EIA3,
+	.auth_key = {
+		.data = {
+			0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+			0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+			0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 73 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+	.cipher_key = {
+		.data = {
+			0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
+			0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0xa9, 0x40, 0x59, 0xda, 0x50, 0x00, 0x00, 0x00,
+			0x29, 0x40, 0x59, 0xda, 0x50, 0x00, 0x80, 0x00
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 77 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+			0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+			0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+			0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+			0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+			0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+			0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+			0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+			0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+			0x00
+		},
+		.len_bits = 73 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
+			0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
+			0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
+			0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
+			0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
+			0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
+			0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
+			0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
+			0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
+			0x00, 0x24, 0xa8, 0x42, 0xb3
+		},
+		.len_bits = 77 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x24, 0xa8, 0x42, 0xb3
+		},
+		.len = 4,
+		.offset = 73,
+	},
+	.validDataLen = {
+		.len_bits = 77 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 77 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 73 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_null_cipher_aes_ctr_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_NULL,
+	.auth_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.auth = {
+		.len_bits = 48 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_AES_CTR,
+	.cipher_key = {
+		.data = {
+			0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9,
+			0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+			0x14, 0x79, 0x3E, 0x41, 0x03, 0x97, 0xE8, 0xFD,
+			0x94, 0x79, 0x3E, 0x41, 0x03, 0x97, 0x68, 0xFD
+		},
+		.len = 16,
+	},
+	.cipher = {
+		.len_bits = 52 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2,
+			0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1,
+			0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29,
+			0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0,
+			0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20,
+			0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09
+		},
+		.len_bits = 48 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x91, 0x96, 0x28, 0xB4, 0x89, 0x74, 0xF6, 0x5E,
+			0x98, 0x58, 0xA1, 0xD3, 0x0E, 0xE3, 0xFC, 0x39,
+			0xDB, 0x36, 0xE4, 0x97, 0x74, 0x5B, 0x5E, 0xD4,
+			0x1B, 0x8A, 0xC5, 0x9D, 0xDF, 0x96, 0x97, 0x5F,
+			0x58, 0x4A, 0x75, 0x74, 0x27, 0x07, 0xF3, 0x7F,
+			0xCE, 0x2C, 0x4A, 0x6C, 0xE5, 0x19, 0xE7, 0x8B,
+			0xCB, 0x94, 0xD0, 0xAC
+		},
+		.len_bits = 52 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0xCB, 0x94, 0xD0, 0xAC
+		},
+		.len = 4,
+		.offset = 48,
+	},
+	.validDataLen = {
+		.len_bits = 52 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 52 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 48 << 3,
+	}
+};
+
+struct mixed_cipher_auth_test_data auth_aes_cmac_cipher_null_test_case_1 = {
+	.auth_algo = RTE_CRYPTO_AUTH_AES_CMAC,
+	.auth_key = {
+		.data = {
+			0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+			0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+		},
+		.len = 16,
+	},
+	.auth_iv = {
+		.data = {
+		},
+		.len = 0,
+	},
+	.auth = {
+		.len_bits = 512 << 3,
+		.offset_bits = 0,
+	},
+	.cipher_algo = RTE_CRYPTO_CIPHER_NULL,
+	.cipher_key = {
+		.data = {
+			0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+			0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+		},
+		.len = 16,
+	},
+	.cipher_iv = {
+		.data = {
+		},
+		.len = 0,
+	},
+	.cipher = {
+		.len_bits = 516 << 3,
+		.offset_bits = 0,
+	},
+	.plaintext = {
+		.data = {
+			0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+			0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+			0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+			0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+			0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+			0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+			0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+			0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+			0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+			0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+			0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+			0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+			0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+			0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+			0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+			0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+			0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+			0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+			0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+			0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+			0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+			0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+			0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+			0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+			0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+			0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+			0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+			0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+			0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+			0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+			0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+			0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+			0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+			0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+			0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+			0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+			0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+			0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+			0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+			0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+			0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+			0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+			0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+			0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+			0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+			0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+			0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+			0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+			0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+			0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+			0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+			0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+			0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+			0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+			0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+			0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75
+		},
+		.len_bits = 512 << 3,
+	},
+	.ciphertext = {
+		.data = {
+			0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C,
+			0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72,
+			0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77,
+			0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20,
+			0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x70, 0x65, 0x6F, 0x70, 0x6C, 0x65, 0x20,
+			0x77, 0x65, 0x72, 0x65, 0x20, 0x64, 0x65, 0x73,
+			0x74, 0x69, 0x74, 0x75, 0x74, 0x65, 0x20, 0x74,
+			0x68, 0x61, 0x74, 0x20, 0x73, 0x61, 0x6D, 0x65,
+			0x20, 0x6E, 0x69, 0x67, 0x68, 0x74, 0x20, 0x65,
+			0x76, 0x65, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x68,
+			0x69, 0x73, 0x20, 0x6F, 0x77, 0x6E, 0x20, 0x70,
+			0x72, 0x6F, 0x73, 0x70, 0x65, 0x72, 0x6F, 0x75,
+			0x73, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x72,
+			0x79, 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D,
+			0x61, 0x6E, 0x79, 0x20, 0x68, 0x6F, 0x6D, 0x65,
+			0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x73,
+			0x68, 0x61, 0x6E, 0x74, 0x69, 0x65, 0x73, 0x2C,
+			0x20, 0x68, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x68, 0x75, 0x73, 0x62, 0x61, 0x6E,
+			0x64, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20,
+			0x64, 0x72, 0x75, 0x6E, 0x6B, 0x20, 0x61, 0x6E,
+			0x64, 0x20, 0x77, 0x69, 0x76, 0x65, 0x73, 0x20,
+			0x73, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x2C, 0x20,
+			0x61, 0x6E, 0x64, 0x20, 0x68, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63, 0x68, 0x69,
+			0x6C, 0x64, 0x72, 0x65, 0x6E, 0x20, 0x77, 0x65,
+			0x72, 0x65, 0x20, 0x62, 0x75, 0x6C, 0x6C, 0x69,
+			0x65, 0x64, 0x2C, 0x20, 0x61, 0x62, 0x75, 0x73,
+			0x65, 0x64, 0x2C, 0x20, 0x6F, 0x72, 0x20, 0x61,
+			0x62, 0x61, 0x6E, 0x64, 0x6F, 0x6E, 0x65, 0x64,
+			0x2E, 0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61,
+			0x6E, 0x79, 0x20, 0x66, 0x61, 0x6D, 0x69, 0x6C,
+			0x69, 0x65, 0x73, 0x20, 0x68, 0x75, 0x6E, 0x67,
+			0x65, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6F, 0x72,
+			0x20, 0x66, 0x6F, 0x6F, 0x64, 0x20, 0x74, 0x68,
+			0x65, 0x79, 0x20, 0x63, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x66, 0x66,
+			0x6F, 0x72, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x62,
+			0x75, 0x79, 0x3F, 0x20, 0x48, 0x6F, 0x77, 0x20,
+			0x6D, 0x61, 0x6E, 0x79, 0x20, 0x68, 0x65, 0x61,
+			0x72, 0x74, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65,
+			0x20, 0x62, 0x72, 0x6F, 0x6B, 0x65, 0x6E, 0x3F,
+			0x20, 0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E,
+			0x79, 0x20, 0x73, 0x75, 0x69, 0x63, 0x69, 0x64,
+			0x65, 0x73, 0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64,
+			0x20, 0x74, 0x61, 0x6B, 0x65, 0x20, 0x70, 0x6C,
+			0x61, 0x63, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74,
+			0x20, 0x73, 0x61, 0x6D, 0x65, 0x20, 0x6E, 0x69,
+			0x67, 0x68, 0x74, 0x2C, 0x20, 0x68, 0x6F, 0x77,
+			0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x70, 0x65,
+			0x6F, 0x70, 0x6C, 0x65, 0x20, 0x77, 0x6F, 0x75,
+			0x6C, 0x64, 0x20, 0x67, 0x6F, 0x20, 0x69, 0x6E,
+			0x73, 0x61, 0x6E, 0x65, 0x3F, 0x20, 0x48, 0x6F,
+			0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79, 0x20, 0x63,
+			0x6F, 0x63, 0x6B, 0x72, 0x6F, 0x61, 0x63, 0x68,
+			0x65, 0x73, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x6C,
+			0x61, 0x6E, 0x64, 0x6C, 0x6F, 0x72, 0x64, 0x73,
+			0x20, 0x77, 0x6F, 0x75, 0x6C, 0x64, 0x20, 0x74,
+			0x72, 0x69, 0x75, 0x6D, 0x70, 0x68, 0x3F, 0x20,
+			0x48, 0x6F, 0x77, 0x20, 0x6D, 0x61, 0x6E, 0x79,
+			0x20, 0x77, 0x69, 0x6E, 0x6E, 0x65, 0x72, 0x73,
+			0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x6C, 0x6F,
+			0x73, 0x65, 0x72, 0x73, 0x2C, 0x20, 0x73, 0x75,
+			0x4C, 0x77, 0x87, 0xA0
+		},
+		.len_bits = 516 << 3,
+	},
+	.digest_enc = {
+		.data = {
+			0x4C, 0x77, 0x87, 0xA0
+		},
+		.len = 4,
+		.offset = 512,
+	},
+	.validDataLen = {
+		.len_bits = 516 << 3,
+	},
+	.validCipherLen = {
+		.len_bits = 516 << 3,
+	},
+	.validAuthLen = {
+		.len_bits = 512 << 3,
+	}
+};
+
 #endif /* TEST_CRYPTODEV_MIXED_TEST_VECTORS_H_ */
diff --git a/dpdk/app/test/test_cycles.c b/dpdk/app/test/test_cycles.c
index c78e6a5b12..97d42f3032 100644
--- a/dpdk/app/test/test_cycles.c
+++ b/dpdk/app/test/test_cycles.c
@@ -79,8 +79,14 @@ REGISTER_TEST_COMMAND(cycles_autotest, test_cycles);
 static int
 test_delay_us_sleep(void)
 {
+	int rv;
+
 	rte_delay_us_callback_register(rte_delay_us_sleep);
-	return check_wait_one_second();
+	rv = check_wait_one_second();
+	/* restore original delay function */
+	rte_delay_us_callback_register(rte_delay_us_block);
+
+	return rv;
 }
 
 REGISTER_TEST_COMMAND(delay_us_sleep_autotest, test_delay_us_sleep);
diff --git a/dpdk/app/test/test_distributor.c b/dpdk/app/test/test_distributor.c
index ba1f81cf8d..acfe728f0c 100644
--- a/dpdk/app/test/test_distributor.c
+++ b/dpdk/app/test/test_distributor.c
@@ -27,7 +27,9 @@ struct worker_params worker_params;
 /* statics - all zero-initialized by default */
 static volatile int quit;      /**< general quit variable for all threads */
 static volatile int zero_quit; /**< var for when we just want thr0 to quit*/
+static volatile int zero_sleep; /**< thr0 has quit basic loop and is sleeping*/
 static volatile unsigned worker_idx;
+static volatile unsigned zero_idx;
 
 struct worker_stats {
 	volatile unsigned handled_packets;
@@ -42,7 +44,8 @@ total_packet_count(void)
 {
 	unsigned i, count = 0;
 	for (i = 0; i < worker_idx; i++)
-		count += worker_stats[i].handled_packets;
+		count += __atomic_load_n(&worker_stats[i].handled_packets,
+				__ATOMIC_RELAXED);
 	return count;
 }
 
@@ -50,7 +53,10 @@ total_packet_count(void)
 static inline void
 clear_packet_count(void)
 {
-	memset(&worker_stats, 0, sizeof(worker_stats));
+	unsigned int i;
+	for (i = 0; i < RTE_MAX_LCORE; i++)
+		__atomic_store_n(&worker_stats[i].handled_packets, 0,
+			__ATOMIC_RELAXED);
 }
 
 /* this is the basic worker function for sanity test
@@ -62,23 +68,18 @@ handle_work(void *arg)
 	struct rte_mbuf *buf[8] __rte_cache_aligned;
 	struct worker_params *wp = arg;
 	struct rte_distributor *db = wp->dist;
-	unsigned int count = 0, num = 0;
+	unsigned int num;
 	unsigned int id = __atomic_fetch_add(&worker_idx, 1, __ATOMIC_RELAXED);
-	int i;
 
-	for (i = 0; i < 8; i++)
-		buf[i] = NULL;
-	num = rte_distributor_get_pkt(db, id, buf, buf, num);
+	num = rte_distributor_get_pkt(db, id, buf, NULL, 0);
 	while (!quit) {
 		__atomic_fetch_add(&worker_stats[id].handled_packets, num,
 				__ATOMIC_RELAXED);
-		count += num;
 		num = rte_distributor_get_pkt(db, id,
 				buf, buf, num);
 	}
 	__atomic_fetch_add(&worker_stats[id].handled_packets, num,
 			__ATOMIC_RELAXED);
-	count += num;
 	rte_distributor_return_pkt(db, id, buf, num);
 	return 0;
 }
@@ -102,6 +103,7 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 	struct rte_mbuf *returns[BURST*2];
 	unsigned int i, count;
 	unsigned int retries;
+	unsigned int processed;
 
 	printf("=== Basic distributor sanity tests ===\n");
 	clear_packet_count();
@@ -115,7 +117,11 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 	for (i = 0; i < BURST; i++)
 		bufs[i]->hash.usr = 0;
 
-	rte_distributor_process(db, bufs, BURST);
+	processed = 0;
+	while (processed < BURST)
+		processed += rte_distributor_process(db, &bufs[processed],
+			BURST - processed);
+
 	count = 0;
 	do {
 
@@ -128,12 +134,14 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 		printf("Line %d: Error, not all packets flushed. "
 				"Expected %u, got %u\n",
 				__LINE__, BURST, total_packet_count());
+		rte_mempool_put_bulk(p, (void *)bufs, BURST);
 		return -1;
 	}
 
 	for (i = 0; i < rte_lcore_count() - 1; i++)
 		printf("Worker %u handled %u packets\n", i,
-				worker_stats[i].handled_packets);
+			__atomic_load_n(&worker_stats[i].handled_packets,
+					__ATOMIC_RELAXED));
 	printf("Sanity test with all zero hashes done.\n");
 
 	/* pick two flows and check they go correctly */
@@ -153,12 +161,15 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 			printf("Line %d: Error, not all packets flushed. "
 					"Expected %u, got %u\n",
 					__LINE__, BURST, total_packet_count());
+			rte_mempool_put_bulk(p, (void *)bufs, BURST);
 			return -1;
 		}
 
 		for (i = 0; i < rte_lcore_count() - 1; i++)
 			printf("Worker %u handled %u packets\n", i,
-					worker_stats[i].handled_packets);
+				__atomic_load_n(
+					&worker_stats[i].handled_packets,
+					__ATOMIC_RELAXED));
 		printf("Sanity test with two hash values done\n");
 	}
 
@@ -179,12 +190,14 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 		printf("Line %d: Error, not all packets flushed. "
 				"Expected %u, got %u\n",
 				__LINE__, BURST, total_packet_count());
+		rte_mempool_put_bulk(p, (void *)bufs, BURST);
 		return -1;
 	}
 
 	for (i = 0; i < rte_lcore_count() - 1; i++)
 		printf("Worker %u handled %u packets\n", i,
-				worker_stats[i].handled_packets);
+			__atomic_load_n(&worker_stats[i].handled_packets,
+					__ATOMIC_RELAXED));
 	printf("Sanity test with non-zero hashes done\n");
 
 	rte_mempool_put_bulk(p, (void *)bufs, BURST);
@@ -194,6 +207,8 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 	clear_packet_count();
 	struct rte_mbuf *many_bufs[BIG_BATCH], *return_bufs[BIG_BATCH];
 	unsigned num_returned = 0;
+	unsigned int num_being_processed = 0;
+	unsigned int return_buffer_capacity = 127;/* RTE_DISTRIB_RETURNS_MASK */
 
 	/* flush out any remaining packets */
 	rte_distributor_flush(db);
@@ -210,16 +225,16 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 	for (i = 0; i < BIG_BATCH/BURST; i++) {
 		rte_distributor_process(db,
 				&many_bufs[i*BURST], BURST);
-		count = rte_distributor_returned_pkts(db,
-				&return_bufs[num_returned],
-				BIG_BATCH - num_returned);
-		num_returned += count;
+		num_being_processed += BURST;
+		do {
+			count = rte_distributor_returned_pkts(db,
+					&return_bufs[num_returned],
+					BIG_BATCH - num_returned);
+			num_being_processed -= count;
+			num_returned += count;
+			rte_distributor_flush(db);
+		} while (num_being_processed + BURST > return_buffer_capacity);
 	}
-	rte_distributor_flush(db);
-	count = rte_distributor_returned_pkts(db,
-		&return_bufs[num_returned],
-			BIG_BATCH - num_returned);
-	num_returned += count;
 	retries = 0;
 	do {
 		rte_distributor_flush(db);
@@ -233,6 +248,7 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 	if (num_returned != BIG_BATCH) {
 		printf("line %d: Missing packets, expected %d\n",
 				__LINE__, num_returned);
+		rte_mempool_put_bulk(p, (void *)many_bufs, BIG_BATCH);
 		return -1;
 	}
 
@@ -247,6 +263,7 @@ sanity_test(struct worker_params *wp, struct rte_mempool *p)
 
 		if (j == BIG_BATCH) {
 			printf("Error: could not find source packet #%u\n", i);
+			rte_mempool_put_bulk(p, (void *)many_bufs, BIG_BATCH);
 			return -1;
 		}
 	}
@@ -270,24 +287,20 @@ handle_work_with_free_mbufs(void *arg)
 	struct rte_mbuf *buf[8] __rte_cache_aligned;
 	struct worker_params *wp = arg;
 	struct rte_distributor *d = wp->dist;
-	unsigned int count = 0;
 	unsigned int i;
-	unsigned int num = 0;
+	unsigned int num;
 	unsigned int id = __atomic_fetch_add(&worker_idx, 1, __ATOMIC_RELAXED);
 
-	for (i = 0; i < 8; i++)
-		buf[i] = NULL;
-	num = rte_distributor_get_pkt(d, id, buf, buf, num);
+	num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
 	while (!quit) {
-		worker_stats[id].handled_packets += num;
-		count += num;
+		__atomic_fetch_add(&worker_stats[id].handled_packets, num,
+				__ATOMIC_RELAXED);
 		for (i = 0; i < num; i++)
 			rte_pktmbuf_free(buf[i]);
-		num = rte_distributor_get_pkt(d,
-				id, buf, buf, num);
+		num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
 	}
-	worker_stats[id].handled_packets += num;
-	count += num;
+	__atomic_fetch_add(&worker_stats[id].handled_packets, num,
+			__ATOMIC_RELAXED);
 	rte_distributor_return_pkt(d, id, buf, num);
 	return 0;
 }
@@ -303,6 +316,7 @@ sanity_test_with_mbuf_alloc(struct worker_params *wp, struct rte_mempool *p)
 	struct rte_distributor *d = wp->dist;
 	unsigned i;
 	struct rte_mbuf *bufs[BURST];
+	unsigned int processed;
 
 	printf("=== Sanity test with mbuf alloc/free (%s) ===\n", wp->name);
 
@@ -313,10 +327,12 @@ sanity_test_with_mbuf_alloc(struct worker_params *wp, struct rte_mempool *p)
 			rte_distributor_process(d, NULL, 0);
 		for (j = 0; j < BURST; j++) {
 			bufs[j]->hash.usr = (i+j) << 1;
-			rte_mbuf_refcnt_set(bufs[j], 1);
 		}
 
-		rte_distributor_process(d, bufs, BURST);
+		processed = 0;
+		while (processed < BURST)
+			processed += rte_distributor_process(d,
+				&bufs[processed], BURST - processed);
 	}
 
 	rte_distributor_flush(d);
@@ -337,55 +353,61 @@ sanity_test_with_mbuf_alloc(struct worker_params *wp, struct rte_mempool *p)
 static int
 handle_work_for_shutdown_test(void *arg)
 {
-	struct rte_mbuf *pkt = NULL;
 	struct rte_mbuf *buf[8] __rte_cache_aligned;
 	struct worker_params *wp = arg;
 	struct rte_distributor *d = wp->dist;
-	unsigned int count = 0;
-	unsigned int num = 0;
-	unsigned int total = 0;
-	unsigned int i;
-	unsigned int returned = 0;
+	unsigned int num;
+	unsigned int zero_id = 0;
+	unsigned int zero_unset;
 	const unsigned int id = __atomic_fetch_add(&worker_idx, 1,
 			__ATOMIC_RELAXED);
 
-	num = rte_distributor_get_pkt(d, id, buf, buf, num);
+	num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
+
+	if (num > 0) {
+		zero_unset = RTE_MAX_LCORE;
+		__atomic_compare_exchange_n(&zero_idx, &zero_unset, id,
+			0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
+	}
+	zero_id = __atomic_load_n(&zero_idx, __ATOMIC_ACQUIRE);
 
 	/* wait for quit single globally, or for worker zero, wait
 	 * for zero_quit */
-	while (!quit && !(id == 0 && zero_quit)) {
-		worker_stats[id].handled_packets += num;
-		count += num;
-		for (i = 0; i < num; i++)
-			rte_pktmbuf_free(buf[i]);
-		num = rte_distributor_get_pkt(d,
-				id, buf, buf, num);
-		total += num;
+	while (!quit && !(id == zero_id && zero_quit)) {
+		__atomic_fetch_add(&worker_stats[id].handled_packets, num,
+				__ATOMIC_RELAXED);
+		num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
+
+		if (num > 0) {
+			zero_unset = RTE_MAX_LCORE;
+			__atomic_compare_exchange_n(&zero_idx, &zero_unset, id,
+				0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
+		}
+		zero_id = __atomic_load_n(&zero_idx, __ATOMIC_ACQUIRE);
 	}
-	worker_stats[id].handled_packets += num;
-	count += num;
-	returned = rte_distributor_return_pkt(d, id, buf, num);
 
-	if (id == 0) {
+	__atomic_fetch_add(&worker_stats[id].handled_packets, num,
+			__ATOMIC_RELAXED);
+	if (id == zero_id) {
+		rte_distributor_return_pkt(d, id, NULL, 0);
+
 		/* for worker zero, allow it to restart to pick up last packet
 		 * when all workers are shutting down.
 		 */
+		__atomic_store_n(&zero_sleep, 1, __ATOMIC_RELEASE);
 		while (zero_quit)
 			usleep(100);
+		__atomic_store_n(&zero_sleep, 0, __ATOMIC_RELEASE);
 
-		num = rte_distributor_get_pkt(d,
-				id, buf, buf, num);
+		num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
 
 		while (!quit) {
-			worker_stats[id].handled_packets += num;
-			count += num;
-			rte_pktmbuf_free(pkt);
-			num = rte_distributor_get_pkt(d, id, buf, buf, num);
+			__atomic_fetch_add(&worker_stats[id].handled_packets,
+					num, __ATOMIC_RELAXED);
+			num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
 		}
-		returned = rte_distributor_return_pkt(d,
-				id, buf, num);
-		printf("Num returned = %d\n", returned);
 	}
+	rte_distributor_return_pkt(d, id, buf, num);
 	return 0;
 }
 
@@ -401,7 +423,10 @@ sanity_test_with_worker_shutdown(struct worker_params *wp,
 {
 	struct rte_distributor *d = wp->dist;
 	struct rte_mbuf *bufs[BURST];
-	unsigned i;
+	struct rte_mbuf *bufs2[BURST];
+	unsigned int i;
+	unsigned int failed = 0;
+	unsigned int processed = 0;
 
 	printf("=== Sanity test of worker shutdown ===\n");
 
@@ -419,7 +444,10 @@ sanity_test_with_worker_shutdown(struct worker_params *wp,
 	for (i = 0; i < BURST; i++)
 		bufs[i]->hash.usr = 1;
 
-	rte_distributor_process(d, bufs, BURST);
+	processed = 0;
+	while (processed < BURST)
+		processed += rte_distributor_process(d, &bufs[processed],
+			BURST - processed);
 	rte_distributor_flush(d);
 
 	/* at this point, we will have processed some packets and have a full
@@ -427,32 +455,45 @@ sanity_test_with_worker_shutdown(struct worker_params *wp,
 	 */
 
 	/* get more buffers to queue up, again setting them to the same flow */
-	if (rte_mempool_get_bulk(p, (void *)bufs, BURST) != 0) {
+	if (rte_mempool_get_bulk(p, (void *)bufs2, BURST) != 0) {
 		printf("line %d: Error getting mbufs from pool\n", __LINE__);
+		rte_mempool_put_bulk(p, (void *)bufs, BURST);
 		return -1;
 	}
 	for (i = 0; i < BURST; i++)
-		bufs[i]->hash.usr = 1;
+		bufs2[i]->hash.usr = 1;
 
 	/* get worker zero to quit */
 	zero_quit = 1;
-	rte_distributor_process(d, bufs, BURST);
+	rte_distributor_process(d, bufs2, BURST);
 
 	/* flush the distributor */
 	rte_distributor_flush(d);
-	rte_delay_us(10000);
+	while (!__atomic_load_n(&zero_sleep, __ATOMIC_ACQUIRE))
+		rte_distributor_flush(d);
+
+	zero_quit = 0;
+	while (__atomic_load_n(&zero_sleep, __ATOMIC_ACQUIRE))
+		rte_delay_us(100);
 
 	for (i = 0; i < rte_lcore_count() - 1; i++)
 		printf("Worker %u handled %u packets\n", i,
-				worker_stats[i].handled_packets);
+			__atomic_load_n(&worker_stats[i].handled_packets,
+					__ATOMIC_RELAXED));
 
 	if (total_packet_count() != BURST * 2) {
 		printf("Line %d: Error, not all packets flushed. "
 				"Expected %u, got %u\n",
 				__LINE__, BURST * 2, total_packet_count());
-		return -1;
+		failed = 1;
 	}
 
+	rte_mempool_put_bulk(p, (void *)bufs, BURST);
+	rte_mempool_put_bulk(p, (void *)bufs2, BURST);
+
+	if (failed)
+		return -1;
+
 	printf("Sanity test with worker shutdown passed\n\n");
 	return 0;
 }
@@ -466,7 +507,9 @@ test_flush_with_worker_shutdown(struct worker_params *wp,
 {
 	struct rte_distributor *d = wp->dist;
 	struct rte_mbuf *bufs[BURST];
-	unsigned i;
+	unsigned int i;
+	unsigned int failed = 0;
+	unsigned int processed;
 
 	printf("=== Test flush fn with worker shutdown (%s) ===\n", wp->name);
 
@@ -481,7 +524,10 @@ test_flush_with_worker_shutdown(struct worker_params *wp,
 	for (i = 0; i < BURST; i++)
 		bufs[i]->hash.usr = 0;
 
-	rte_distributor_process(d, bufs, BURST);
+	processed = 0;
+	while (processed < BURST)
+		processed += rte_distributor_process(d, &bufs[processed],
+			BURST - processed);
 	/* at this point, we will have processed some packets and have a full
 	 * backlog for the other ones at worker 0.
 	 */
@@ -492,20 +538,31 @@ test_flush_with_worker_shutdown(struct worker_params *wp,
 	/* flush the distributor */
 	rte_distributor_flush(d);
 
-	rte_delay_us(10000);
+	while (!__atomic_load_n(&zero_sleep, __ATOMIC_ACQUIRE))
+		rte_distributor_flush(d);
 
 	zero_quit = 0;
+
+	while (__atomic_load_n(&zero_sleep, __ATOMIC_ACQUIRE))
+		rte_delay_us(100);
+
 	for (i = 0; i < rte_lcore_count() - 1; i++)
 		printf("Worker %u handled %u packets\n", i,
-				worker_stats[i].handled_packets);
+			__atomic_load_n(&worker_stats[i].handled_packets,
+					__ATOMIC_RELAXED));
 
 	if (total_packet_count() != BURST) {
 		printf("Line %d: Error, not all packets flushed. "
 				"Expected %u, got %u\n",
 				__LINE__, BURST, total_packet_count());
-		return -1;
+		failed = 1;
 	}
 
+	rte_mempool_put_bulk(p, (void *)bufs, BURST);
+
+	if (failed)
+		return -1;
+
 	printf("Flush test with worker shutdown passed\n\n");
 	return 0;
 }
@@ -571,21 +628,34 @@ quit_workers(struct worker_params *wp, struct rte_mempool *p)
 	const unsigned num_workers = rte_lcore_count() - 1;
 	unsigned i;
 	struct rte_mbuf *bufs[RTE_MAX_LCORE];
-	rte_mempool_get_bulk(p, (void *)bufs, num_workers);
+	struct rte_mbuf *returns[RTE_MAX_LCORE];
+	if (rte_mempool_get_bulk(p, (void *)bufs, num_workers) != 0) {
+		printf("line %d: Error getting mbufs from pool\n", __LINE__);
+		return;
+	}
 
 	zero_quit = 0;
 	quit = 1;
-	for (i = 0; i < num_workers; i++)
+	for (i = 0; i < num_workers; i++) {
 		bufs[i]->hash.usr = i << 1;
-	rte_distributor_process(d, bufs, num_workers);
-
-	rte_mempool_put_bulk(p, (void *)bufs, num_workers);
+		rte_distributor_process(d, &bufs[i], 1);
+	}
 
 	rte_distributor_process(d, NULL, 0);
 	rte_distributor_flush(d);
 	rte_eal_mp_wait_lcore();
+
+	while (rte_distributor_returned_pkts(d, returns, RTE_MAX_LCORE))
+		;
+
+	rte_distributor_clear_returns(d);
+	rte_mempool_put_bulk(p, (void *)bufs, num_workers);
+
 	quit = 0;
 	worker_idx = 0;
+	zero_idx = RTE_MAX_LCORE;
+	zero_quit = 0;
+	zero_sleep = 0;
 }
 
 static int
diff --git a/dpdk/app/test/test_event_crypto_adapter.c b/dpdk/app/test/test_event_crypto_adapter.c
index 8d42462d87..1c0a0fa5e3 100644
--- a/dpdk/app/test/test_event_crypto_adapter.c
+++ b/dpdk/app/test/test_event_crypto_adapter.c
@@ -171,7 +171,6 @@ test_op_forward_mode(uint8_t session_less)
 	struct rte_event ev;
 	uint32_t cap;
 	int ret;
-	uint8_t cipher_key[17];
 
 	memset(&m_data, 0, sizeof(m_data));
 
@@ -183,15 +182,9 @@ test_op_forward_mode(uint8_t session_less)
 	/* Setup Cipher Parameters */
 	cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 	cipher_xform.next = NULL;
-
-	cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_NULL;
 	cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
 
-	cipher_xform.cipher.key.data = cipher_key;
-	cipher_xform.cipher.key.length = 16;
-	cipher_xform.cipher.iv.offset = IV_OFFSET;
-	cipher_xform.cipher.iv.length = 16;
-
 	op = rte_crypto_op_alloc(params.op_mpool,
 			RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	TEST_ASSERT_NOT_NULL(op,
@@ -209,8 +202,8 @@ test_op_forward_mode(uint8_t session_less)
 				&cipher_xform, params.session_priv_mpool);
 		TEST_ASSERT_SUCCESS(ret, "Failed to init session\n");
 
-		ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID,
-							evdev, &cap);
+		ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID,
+							&cap);
 		TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 		if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_SESSION_PRIVATE_DATA) {
@@ -296,7 +289,7 @@ test_sessionless_with_op_forward_mode(void)
 	uint32_t cap;
 	int ret;
 
-	ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+	ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID, &cap);
 	TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 	if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
@@ -321,7 +314,7 @@ test_session_with_op_forward_mode(void)
 	uint32_t cap;
 	int ret;
 
-	ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+	ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID, &cap);
 	TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 	if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
@@ -378,7 +371,6 @@ test_op_new_mode(uint8_t session_less)
 	struct rte_mbuf *m;
 	uint32_t cap;
 	int ret;
-	uint8_t cipher_key[17];
 
 	memset(&m_data, 0, sizeof(m_data));
 
@@ -390,15 +382,9 @@ test_op_new_mode(uint8_t session_less)
 	/* Setup Cipher Parameters */
 	cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 	cipher_xform.next = NULL;
-
-	cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+	cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_NULL;
 	cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
 
-	cipher_xform.cipher.key.data = cipher_key;
-	cipher_xform.cipher.key.length = 16;
-	cipher_xform.cipher.iv.offset = IV_OFFSET;
-	cipher_xform.cipher.iv.length = 16;
-
 	op = rte_crypto_op_alloc(params.op_mpool,
 			RTE_CRYPTO_OP_TYPE_SYMMETRIC);
 	TEST_ASSERT_NOT_NULL(op, "Failed to allocate crypto_op!\n");
@@ -410,8 +396,8 @@ test_op_new_mode(uint8_t session_less)
 				params.session_mpool);
 		TEST_ASSERT_NOT_NULL(sess, "Session creation failed\n");
 
-		ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID,
-							evdev, &cap);
+		ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID,
+							&cap);
 		TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 		if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_SESSION_PRIVATE_DATA) {
@@ -460,7 +446,7 @@ test_sessionless_with_op_new_mode(void)
 	uint32_t cap;
 	int ret;
 
-	ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+	ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID, &cap);
 	TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 	if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
@@ -486,7 +472,7 @@ test_session_with_op_new_mode(void)
 	uint32_t cap;
 	int ret;
 
-	ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+	ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID, &cap);
 	TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 	if (!(cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_OP_FWD) &&
@@ -564,7 +550,9 @@ configure_cryptodev(void)
 
 	params.session_mpool = rte_cryptodev_sym_session_pool_create(
 			"CRYPTO_ADAPTER_SESSION_MP",
-			MAX_NB_SESSIONS, 0, 0, 0, SOCKET_ID_ANY);
+			MAX_NB_SESSIONS, 0, 0,
+			sizeof(union rte_event_crypto_metadata),
+			SOCKET_ID_ANY);
 	TEST_ASSERT_NOT_NULL(params.session_mpool,
 			"session mempool allocation failed\n");
 
@@ -706,7 +694,7 @@ test_crypto_adapter_create(void)
 
 	/* Create adapter with default port creation callback */
 	ret = rte_event_crypto_adapter_create(TEST_ADAPTER_ID,
-					      TEST_CDEV_ID,
+					      evdev,
 					      &conf, 0);
 	TEST_ASSERT_SUCCESS(ret, "Failed to create event crypto adapter\n");
 
@@ -719,7 +707,7 @@ test_crypto_adapter_qp_add_del(void)
 	uint32_t cap;
 	int ret;
 
-	ret = rte_event_crypto_adapter_caps_get(TEST_ADAPTER_ID, evdev, &cap);
+	ret = rte_event_crypto_adapter_caps_get(evdev, TEST_CDEV_ID, &cap);
 	TEST_ASSERT_SUCCESS(ret, "Failed to get adapter capabilities\n");
 
 	if (cap & RTE_EVENT_CRYPTO_ADAPTER_CAP_INTERNAL_PORT_QP_EV_BIND) {
diff --git a/dpdk/app/test/test_event_eth_tx_adapter.c b/dpdk/app/test/test_event_eth_tx_adapter.c
index 3af749280a..7073030902 100644
--- a/dpdk/app/test/test_event_eth_tx_adapter.c
+++ b/dpdk/app/test/test_event_eth_tx_adapter.c
@@ -45,7 +45,7 @@ static uint64_t eid = ~0ULL;
 static uint32_t tid;
 
 static inline int
-port_init_common(uint8_t port, const struct rte_eth_conf *port_conf,
+port_init_common(uint16_t port, const struct rte_eth_conf *port_conf,
 		struct rte_mempool *mp)
 {
 	const uint16_t rx_ring_size = RING_SIZE, tx_ring_size = RING_SIZE;
@@ -104,7 +104,7 @@ port_init_common(uint8_t port, const struct rte_eth_conf *port_conf,
 }
 
 static inline int
-port_init(uint8_t port, struct rte_mempool *mp)
+port_init(uint16_t port, struct rte_mempool *mp)
 {
 	struct rte_eth_conf conf = { 0 };
 	return port_init_common(port, &conf, mp);
diff --git a/dpdk/app/test/test_eventdev.c b/dpdk/app/test/test_eventdev.c
index 427dbbf77f..43ccb1ce97 100644
--- a/dpdk/app/test/test_eventdev.c
+++ b/dpdk/app/test/test_eventdev.c
@@ -996,9 +996,13 @@ test_eventdev_common(void)
 static int
 test_eventdev_selftest_impl(const char *pmd, const char *opts)
 {
-	rte_vdev_init(pmd, opts);
+	int ret = 0;
+
 	if (rte_event_dev_get_dev_id(pmd) == -ENODEV)
+		ret = rte_vdev_init(pmd, opts);
+	if (ret)
 		return TEST_SKIPPED;
+
 	return rte_event_dev_selftest(rte_event_dev_get_dev_id(pmd));
 }
 
@@ -1017,7 +1021,7 @@ test_eventdev_selftest_octeontx(void)
 static int
 test_eventdev_selftest_octeontx2(void)
 {
-	return test_eventdev_selftest_impl("otx2_eventdev", "");
+	return test_eventdev_selftest_impl("event_octeontx2", "");
 }
 
 static int
diff --git a/dpdk/app/test/test_fib_perf.c b/dpdk/app/test/test_fib_perf.c
index 573087c3c0..dd2e54db8b 100644
--- a/dpdk/app/test/test_fib_perf.c
+++ b/dpdk/app/test/test_fib_perf.c
@@ -35,7 +35,7 @@ struct route_rule {
 	uint8_t depth;
 };
 
-struct route_rule large_route_table[MAX_RULE_NUM];
+static struct route_rule large_route_table[MAX_RULE_NUM];
 
 static uint32_t num_route_entries;
 #define NUM_ROUTE_ENTRIES num_route_entries
diff --git a/dpdk/app/test/test_flow_classify.c b/dpdk/app/test/test_flow_classify.c
index ff5265c6af..ef0b6fdd5c 100644
--- a/dpdk/app/test/test_flow_classify.c
+++ b/dpdk/app/test/test_flow_classify.c
@@ -23,7 +23,7 @@
 
 #define FLOW_CLASSIFY_MAX_RULE_NUM 100
 #define MAX_PKT_BURST              32
-#define NB_SOCKETS                 1
+#define NB_SOCKETS                 4
 #define MEMPOOL_CACHE_SIZE         256
 #define MBUF_SIZE                  512
 #define NB_MBUF                    512
diff --git a/dpdk/app/test/test_hash.c b/dpdk/app/test/test_hash.c
index 0052dce2de..2ac298e21e 100644
--- a/dpdk/app/test/test_hash.c
+++ b/dpdk/app/test/test_hash.c
@@ -1142,8 +1142,11 @@ fbk_hash_unit_test(void)
 	handle = rte_fbk_hash_create(&invalid_params_7);
 	RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
 
-	handle = rte_fbk_hash_create(&invalid_params_8);
-	RETURN_IF_ERROR_FBK(handle != NULL, "fbk hash creation should have failed");
+	if (rte_eal_has_hugepages()) {
+		handle = rte_fbk_hash_create(&invalid_params_8);
+		RETURN_IF_ERROR_FBK(handle != NULL,
+					"fbk hash creation should have failed");
+	}
 
 	handle = rte_fbk_hash_create(&invalid_params_same_name_1);
 	RETURN_IF_ERROR_FBK(handle == NULL, "fbk hash creation should have succeeded");
diff --git a/dpdk/app/test/test_hash_readwrite_lf.c b/dpdk/app/test/test_hash_readwrite_lf_perf.c
similarity index 99%
rename from dpdk/app/test/test_hash_readwrite_lf.c
rename to dpdk/app/test/test_hash_readwrite_lf_perf.c
index 97c304054c..7bfc067f4e 100644
--- a/dpdk/app/test/test_hash_readwrite_lf.c
+++ b/dpdk/app/test/test_hash_readwrite_lf_perf.c
@@ -1241,7 +1241,7 @@ test_hash_add_ks_lookup_hit_extbkt(struct rwc_perf *rwc_perf_results,
 }
 
 static int
-test_hash_readwrite_lf_main(void)
+test_hash_readwrite_lf_perf_main(void)
 {
 	/*
 	 * Variables used to choose different tests.
@@ -1254,7 +1254,7 @@ test_hash_readwrite_lf_main(void)
 	int ext_bkt = 0;
 
 	if (rte_lcore_count() < 2) {
-		printf("Not enough cores for hash_readwrite_lf_autotest, expecting at least 2\n");
+		printf("Not enough cores for hash_readwrite_lf_perf_autotest, expecting at least 2\n");
 		return TEST_SKIPPED;
 	}
 
@@ -1431,4 +1431,5 @@ test_hash_readwrite_lf_main(void)
 	return 0;
 }
 
-REGISTER_TEST_COMMAND(hash_readwrite_lf_autotest, test_hash_readwrite_lf_main);
+REGISTER_TEST_COMMAND(hash_readwrite_lf_perf_autotest,
+	test_hash_readwrite_lf_perf_main);
diff --git a/dpdk/app/test/test_ipsec.c b/dpdk/app/test/test_ipsec.c
index 7dc83fee7e..6a4bd12f7f 100644
--- a/dpdk/app/test/test_ipsec.c
+++ b/dpdk/app/test/test_ipsec.c
@@ -237,7 +237,7 @@ fill_crypto_xform(struct ipsec_unitest_params *ut_params,
 }
 
 static int
-check_cryptodev_capablity(const struct ipsec_unitest_params *ut,
+check_cryptodev_capability(const struct ipsec_unitest_params *ut,
 		uint8_t dev_id)
 {
 	struct rte_cryptodev_sym_capability_idx cap_idx;
@@ -302,7 +302,7 @@ testsuite_setup(void)
 
 	/* Find first valid crypto device */
 	for (i = 0; i < nb_devs; i++) {
-		rc = check_cryptodev_capablity(ut_params, i);
+		rc = check_cryptodev_capability(ut_params, i);
 		if (rc == 0) {
 			ts_params->valid_dev = i;
 			ts_params->valid_dev_found = 1;
@@ -743,7 +743,7 @@ create_sa(enum rte_security_session_action_type action_type,
 	ut->ss[j].type = action_type;
 	rc = create_session(ut, &ts->qp_conf, ts->valid_dev, j);
 	if (rc != 0)
-		return TEST_FAILED;
+		return rc;
 
 	rc = rte_ipsec_sa_init(ut->ss[j].sa, &ut->sa_prm, sz);
 	rc = (rc > 0 && (uint32_t)rc <= sz) ? 0 : -EINVAL;
@@ -1167,6 +1167,34 @@ test_ipsec_dump_buffers(struct ipsec_unitest_params *ut_params, int i)
 	}
 }
 
+static void
+destroy_dummy_sec_session(struct ipsec_unitest_params *ut,
+	uint32_t j)
+{
+	rte_security_session_destroy(&dummy_sec_ctx,
+					ut->ss[j].security.ses);
+	ut->ss[j].security.ctx = NULL;
+}
+
+static void
+destroy_crypto_session(struct ipsec_unitest_params *ut,
+	uint8_t crypto_dev, uint32_t j)
+{
+	rte_cryptodev_sym_session_clear(crypto_dev, ut->ss[j].crypto.ses);
+	rte_cryptodev_sym_session_free(ut->ss[j].crypto.ses);
+	memset(&ut->ss[j], 0, sizeof(ut->ss[j]));
+}
+
+static void
+destroy_session(struct ipsec_unitest_params *ut,
+	uint8_t crypto_dev, uint32_t j)
+{
+	if (ut->ss[j].type == RTE_SECURITY_ACTION_TYPE_NONE)
+		return destroy_crypto_session(ut, crypto_dev, j);
+	else
+		return destroy_dummy_sec_session(ut, j);
+}
+
 static void
 destroy_sa(uint32_t j)
 {
@@ -1175,9 +1203,8 @@ destroy_sa(uint32_t j)
 
 	rte_ipsec_sa_fini(ut->ss[j].sa);
 	rte_free(ut->ss[j].sa);
-	rte_cryptodev_sym_session_clear(ts->valid_dev, ut->ss[j].crypto.ses);
-	rte_cryptodev_sym_session_free(ut->ss[j].crypto.ses);
-	memset(&ut->ss[j], 0, sizeof(ut->ss[j]));
+
+	destroy_session(ut, ts->valid_dev, j);
 }
 
 static int
@@ -1219,7 +1246,7 @@ test_ipsec_crypto_inb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -1321,7 +1348,7 @@ test_ipsec_crypto_outb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate input mbuf data */
@@ -1430,7 +1457,7 @@ test_ipsec_inline_crypto_inb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate inbound mbuf data */
@@ -1508,7 +1535,7 @@ test_ipsec_inline_proto_inb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate inbound mbuf data */
@@ -1616,7 +1643,7 @@ test_ipsec_inline_crypto_outb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -1694,7 +1721,7 @@ test_ipsec_inline_proto_outb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -1770,7 +1797,7 @@ test_ipsec_lksd_proto_inb_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -1883,7 +1910,7 @@ test_ipsec_replay_inb_inside_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate inbound mbuf data */
@@ -1976,7 +2003,7 @@ test_ipsec_replay_inb_outside_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -2076,7 +2103,7 @@ test_ipsec_replay_inb_repeat_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -2177,7 +2204,7 @@ test_ipsec_replay_inb_inside_burst_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate inbound mbuf data */
@@ -2310,7 +2337,7 @@ test_ipsec_crypto_inb_burst_2sa_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa 0 failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* create second rte_ipsec_sa */
@@ -2320,7 +2347,7 @@ test_ipsec_crypto_inb_burst_2sa_null_null(int i)
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa 1 failed, cfg %d\n", i);
 		destroy_sa(0);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
@@ -2396,7 +2423,7 @@ test_ipsec_crypto_inb_burst_2sa_4grp_null_null(int i)
 			test_cfg[i].replay_win_sz, test_cfg[i].flags, 0);
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa 0 failed, cfg %d\n", i);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* create second rte_ipsec_sa */
@@ -2406,7 +2433,7 @@ test_ipsec_crypto_inb_burst_2sa_4grp_null_null(int i)
 	if (rc != 0) {
 		RTE_LOG(ERR, USER1, "create_sa 1 failed, cfg %d\n", i);
 		destroy_sa(0);
-		return TEST_FAILED;
+		return rc;
 	}
 
 	/* Generate test mbuf data */
diff --git a/dpdk/app/test/test_kvargs.c b/dpdk/app/test/test_kvargs.c
index a42056f361..2a2dae43a0 100644
--- a/dpdk/app/test/test_kvargs.c
+++ b/dpdk/app/test/test_kvargs.c
@@ -142,7 +142,7 @@ static int test_valid_kvargs(void)
 	valid_keys = valid_keys_list;
 	kvlist = rte_kvargs_parse(args, valid_keys);
 	if (kvlist == NULL) {
-		printf("rte_kvargs_parse() error");
+		printf("rte_kvargs_parse() error\n");
 		goto fail;
 	}
 	if (strcmp(kvlist->pairs[0].value, "[0,1]") != 0) {
@@ -157,6 +157,40 @@ static int test_valid_kvargs(void)
 	}
 	rte_kvargs_free(kvlist);
 
+	/* test using empty string (it is valid) */
+	args = "";
+	kvlist = rte_kvargs_parse(args, NULL);
+	if (kvlist == NULL) {
+		printf("rte_kvargs_parse() error\n");
+		goto fail;
+	}
+	if (rte_kvargs_count(kvlist, NULL) != 0) {
+		printf("invalid count value\n");
+		goto fail;
+	}
+	rte_kvargs_free(kvlist);
+
+	/* test using empty elements (it is valid) */
+	args = "foo=1,,check=value2,,";
+	kvlist = rte_kvargs_parse(args, NULL);
+	if (kvlist == NULL) {
+		printf("rte_kvargs_parse() error\n");
+		goto fail;
+	}
+	if (rte_kvargs_count(kvlist, NULL) != 2) {
+		printf("invalid count value\n");
+		goto fail;
+	}
+	if (rte_kvargs_count(kvlist, "foo") != 1) {
+		printf("invalid count value for 'foo'\n");
+		goto fail;
+	}
+	if (rte_kvargs_count(kvlist, "check") != 1) {
+		printf("invalid count value for 'check'\n");
+		goto fail;
+	}
+	rte_kvargs_free(kvlist);
+
 	return 0;
 
  fail:
@@ -179,11 +213,11 @@ static int test_invalid_kvargs(void)
 	const char *args_list[] = {
 		"wrong-key=x",     /* key not in valid_keys_list */
 		"foo=1,foo=",      /* empty value */
-		"foo=1,,foo=2",    /* empty key/value */
 		"foo=1,foo",       /* no value */
 		"foo=1,=2",        /* no key */
 		"foo=[1,2",        /* no closing bracket in value */
 		",=",              /* also test with a smiley */
+		"foo=[",           /* no value in list and no closing bracket */
 		NULL };
 	const char **args;
 	const char *valid_keys_list[] = { "foo", "check", NULL };
@@ -197,8 +231,8 @@ static int test_invalid_kvargs(void)
 			rte_kvargs_free(kvlist);
 			goto fail;
 		}
-		return 0;
 	}
+	return 0;
 
  fail:
 	printf("while processing <%s>", *args);
diff --git a/dpdk/app/test/test_lpm_perf.c b/dpdk/app/test/test_lpm_perf.c
index a2578fe90e..489719c40b 100644
--- a/dpdk/app/test/test_lpm_perf.c
+++ b/dpdk/app/test/test_lpm_perf.c
@@ -34,7 +34,7 @@ struct route_rule {
 	uint8_t depth;
 };
 
-struct route_rule large_route_table[MAX_RULE_NUM];
+static struct route_rule large_route_table[MAX_RULE_NUM];
 
 static uint32_t num_route_entries;
 #define NUM_ROUTE_ENTRIES num_route_entries
diff --git a/dpdk/app/test/test_malloc.c b/dpdk/app/test/test_malloc.c
index a16e28cc32..57f796f9e5 100644
--- a/dpdk/app/test/test_malloc.c
+++ b/dpdk/app/test/test_malloc.c
@@ -746,6 +746,18 @@ test_malloc_bad_params(void)
 	if (bad_ptr != NULL)
 		goto err_return;
 
+	/* rte_malloc expected to return null with size will cause overflow */
+	align = RTE_CACHE_LINE_SIZE;
+	size = (size_t)-8;
+
+	bad_ptr = rte_malloc(type, size, align);
+	if (bad_ptr != NULL)
+		goto err_return;
+
+	bad_ptr = rte_realloc(NULL, size, align);
+	if (bad_ptr != NULL)
+		goto err_return;
+
 	return 0;
 
 err_return:
diff --git a/dpdk/app/test/test_mbuf.c b/dpdk/app/test/test_mbuf.c
index 61ecffc184..a5bd1693b2 100644
--- a/dpdk/app/test/test_mbuf.c
+++ b/dpdk/app/test/test_mbuf.c
@@ -1144,7 +1144,7 @@ test_refcnt_mbuf(void)
 		tref += refcnt_lcore[slave];
 
 	if (tref != refcnt_lcore[master])
-		rte_panic("refernced mbufs: %u, freed mbufs: %u\n",
+		rte_panic("referenced mbufs: %u, freed mbufs: %u\n",
 		          tref, refcnt_lcore[master]);
 
 	rte_mempool_dump(stdout, refcnt_pool);
@@ -2481,9 +2481,13 @@ test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
 
 	offset3 = rte_mbuf_dynfield_register_offset(&dynfield3,
 				offsetof(struct rte_mbuf, dynfield1[1]));
-	if (offset3 != offsetof(struct rte_mbuf, dynfield1[1]))
-		GOTO_FAIL("failed to register dynamic field 3, offset=%d: %s",
-			offset3, strerror(errno));
+	if (offset3 != offsetof(struct rte_mbuf, dynfield1[1])) {
+		if (rte_errno == EBUSY)
+			printf("mbuf test error skipped: dynfield is busy\n");
+		else
+			GOTO_FAIL("failed to register dynamic field 3, offset="
+				"%d: %s", offset3, strerror(errno));
+	}
 
 	printf("dynfield: offset=%d, offset2=%d, offset3=%d\n",
 		offset, offset2, offset3);
@@ -2519,7 +2523,7 @@ test_mbuf_dyn(struct rte_mempool *pktmbuf_pool)
 	flag3 = rte_mbuf_dynflag_register_bitnum(&dynflag3,
 						rte_bsf64(PKT_LAST_FREE));
 	if (flag3 != rte_bsf64(PKT_LAST_FREE))
-		GOTO_FAIL("failed to register dynamic flag 3, flag2=%d: %s",
+		GOTO_FAIL("failed to register dynamic flag 3, flag3=%d: %s",
 			flag3, strerror(errno));
 
 	printf("dynflag: flag=%d, flag2=%d, flag3=%d\n", flag, flag2, flag3);
diff --git a/dpdk/app/test/test_mcslock.c b/dpdk/app/test/test_mcslock.c
index e9359df2ee..b70dd4775b 100644
--- a/dpdk/app/test/test_mcslock.c
+++ b/dpdk/app/test/test_mcslock.c
@@ -37,10 +37,6 @@
  *   lock multiple times.
  */
 
-RTE_DEFINE_PER_LCORE(rte_mcslock_t, _ml_me);
-RTE_DEFINE_PER_LCORE(rte_mcslock_t, _ml_try_me);
-RTE_DEFINE_PER_LCORE(rte_mcslock_t, _ml_perf_me);
-
 rte_mcslock_t *p_ml;
 rte_mcslock_t *p_ml_try;
 rte_mcslock_t *p_ml_perf;
@@ -53,7 +49,7 @@ static int
 test_mcslock_per_core(__attribute__((unused)) void *arg)
 {
 	/* Per core me node. */
-	rte_mcslock_t ml_me = RTE_PER_LCORE(_ml_me);
+	rte_mcslock_t ml_me;
 
 	rte_mcslock_lock(&p_ml, &ml_me);
 	printf("MCS lock taken on core %u\n", rte_lcore_id());
@@ -77,7 +73,7 @@ load_loop_fn(void *func_param)
 	const unsigned int lcore = rte_lcore_id();
 
 	/**< Per core me node. */
-	rte_mcslock_t ml_perf_me = RTE_PER_LCORE(_ml_perf_me);
+	rte_mcslock_t ml_perf_me;
 
 	/* wait synchro */
 	while (rte_atomic32_read(&synchro) == 0)
@@ -151,8 +147,8 @@ static int
 test_mcslock_try(__attribute__((unused)) void *arg)
 {
 	/**< Per core me node. */
-	rte_mcslock_t ml_me     = RTE_PER_LCORE(_ml_me);
-	rte_mcslock_t ml_try_me = RTE_PER_LCORE(_ml_try_me);
+	rte_mcslock_t ml_me;
+	rte_mcslock_t ml_try_me;
 
 	/* Locked ml_try in the master lcore, so it should fail
 	 * when trying to lock it in the slave lcore.
@@ -178,8 +174,8 @@ test_mcslock(void)
 	int i;
 
 	/* Define per core me node. */
-	rte_mcslock_t ml_me     = RTE_PER_LCORE(_ml_me);
-	rte_mcslock_t ml_try_me = RTE_PER_LCORE(_ml_try_me);
+	rte_mcslock_t ml_me;
+	rte_mcslock_t ml_try_me;
 
 	/*
 	 * Test mcs lock & unlock on each core
diff --git a/dpdk/app/test/test_pmd_perf.c b/dpdk/app/test/test_pmd_perf.c
index d61be58bb3..de7e726429 100644
--- a/dpdk/app/test/test_pmd_perf.c
+++ b/dpdk/app/test/test_pmd_perf.c
@@ -151,7 +151,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 					if (link_mbps == 0)
 						link_mbps = link.link_speed;
 				} else
@@ -609,10 +609,10 @@ poll_burst(void *args)
 static int
 exec_burst(uint32_t flags, int lcore)
 {
-	unsigned i, portid, nb_tx = 0;
+	unsigned int portid, nb_tx = 0;
 	struct lcore_conf *conf;
 	uint32_t pkt_per_port;
-	int num, idx = 0;
+	int num, i, idx = 0;
 	int diff_tsc;
 
 	conf = &lcore_conf[lcore];
@@ -631,16 +631,14 @@ exec_burst(uint32_t flags, int lcore)
 		rte_atomic64_set(&start, 1);
 
 	/* start xmit */
+	i = 0;
 	while (num) {
 		nb_tx = RTE_MIN(MAX_PKT_BURST, num);
-		for (i = 0; i < conf->nb_ports; i++) {
-			portid = conf->portlist[i];
-			nb_tx = rte_eth_tx_burst(portid, 0,
-					 &tx_burst[idx], nb_tx);
-			idx += nb_tx;
-			num -= nb_tx;
-		}
-
+		portid = conf->portlist[i];
+		nb_tx = rte_eth_tx_burst(portid, 0, &tx_burst[idx], nb_tx);
+		idx += nb_tx;
+		num -= nb_tx;
+		i = (i >= conf->nb_ports - 1) ? 0 : (i + 1);
 	}
 
 	sleep(5);
diff --git a/dpdk/app/test/test_rcu_qsbr.c b/dpdk/app/test/test_rcu_qsbr.c
index b60dc5099c..5542b3c175 100644
--- a/dpdk/app/test/test_rcu_qsbr.c
+++ b/dpdk/app/test/test_rcu_qsbr.c
@@ -273,13 +273,13 @@ static int
 test_rcu_qsbr_start(void)
 {
 	uint64_t token;
-	int i;
+	unsigned int i;
 
 	printf("\nTest rte_rcu_qsbr_start()\n");
 
 	rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
 
-	for (i = 0; i < 3; i++)
+	for (i = 0; i < num_cores; i++)
 		rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[i]);
 
 	token = rte_rcu_qsbr_start(t[0]);
@@ -293,14 +293,18 @@ test_rcu_qsbr_check_reader(void *arg)
 {
 	struct rte_rcu_qsbr *temp;
 	uint8_t read_type = (uint8_t)((uintptr_t)arg);
+	unsigned int i;
 
 	temp = t[read_type];
 
 	/* Update quiescent state counter */
-	rte_rcu_qsbr_quiescent(temp, enabled_core_ids[0]);
-	rte_rcu_qsbr_quiescent(temp, enabled_core_ids[1]);
-	rte_rcu_qsbr_thread_unregister(temp, enabled_core_ids[2]);
-	rte_rcu_qsbr_quiescent(temp, enabled_core_ids[3]);
+	for (i = 0; i < num_cores; i++) {
+		if (i % 2 == 0)
+			rte_rcu_qsbr_quiescent(temp, enabled_core_ids[i]);
+		else
+			rte_rcu_qsbr_thread_unregister(temp,
+							enabled_core_ids[i]);
+	}
 	return 0;
 }
 
@@ -311,7 +315,8 @@ test_rcu_qsbr_check_reader(void *arg)
 static int
 test_rcu_qsbr_check(void)
 {
-	int i, ret;
+	int ret;
+	unsigned int i;
 	uint64_t token;
 
 	printf("\nTest rte_rcu_qsbr_check()\n");
@@ -329,7 +334,7 @@ test_rcu_qsbr_check(void)
 	ret = rte_rcu_qsbr_check(t[0], token, true);
 	TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Blocking QSBR check");
 
-	for (i = 0; i < 3; i++)
+	for (i = 0; i < num_cores; i++)
 		rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[i]);
 
 	ret = rte_rcu_qsbr_check(t[0], token, false);
@@ -344,7 +349,7 @@ test_rcu_qsbr_check(void)
 	/* Threads are offline, hence this should pass */
 	TEST_RCU_QSBR_RETURN_IF_ERROR((ret == 0), "Non-blocking QSBR check");
 
-	for (i = 0; i < 3; i++)
+	for (i = 0; i < num_cores; i++)
 		rte_rcu_qsbr_thread_unregister(t[0], enabled_core_ids[i]);
 
 	ret = rte_rcu_qsbr_check(t[0], token, true);
@@ -352,7 +357,7 @@ test_rcu_qsbr_check(void)
 
 	rte_rcu_qsbr_init(t[0], RTE_MAX_LCORE);
 
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < num_cores; i++)
 		rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[i]);
 
 	token = rte_rcu_qsbr_start(t[0]);
@@ -591,7 +596,7 @@ test_rcu_qsbr_thread_offline(void)
 static int
 test_rcu_qsbr_dump(void)
 {
-	int i;
+	unsigned int i;
 
 	printf("\nTest rte_rcu_qsbr_dump()\n");
 
@@ -608,7 +613,7 @@ test_rcu_qsbr_dump(void)
 
 	rte_rcu_qsbr_thread_register(t[0], enabled_core_ids[0]);
 
-	for (i = 1; i < 3; i++)
+	for (i = 1; i < num_cores; i++)
 		rte_rcu_qsbr_thread_register(t[1], enabled_core_ids[i]);
 
 	rte_rcu_qsbr_dump(stdout, t[0]);
@@ -758,7 +763,7 @@ test_rcu_qsbr_sw_sv_3qs(void)
 {
 	uint64_t token[3];
 	uint32_t c;
-	int i;
+	int i, num_readers;
 	int32_t pos[3];
 
 	writer_done = 0;
@@ -781,7 +786,11 @@ test_rcu_qsbr_sw_sv_3qs(void)
 	thread_info[0].ih = 0;
 
 	/* Reader threads are launched */
-	for (i = 0; i < 4; i++)
+	/* Keep the number of reader threads low to reduce
+	 * the execution time.
+	 */
+	num_readers = num_cores < 4 ? num_cores : 4;
+	for (i = 0; i < num_readers; i++)
 		rte_eal_remote_launch(test_rcu_qsbr_reader, &thread_info[0],
 					enabled_core_ids[i]);
 
@@ -814,7 +823,7 @@ test_rcu_qsbr_sw_sv_3qs(void)
 
 	/* Check the quiescent state status */
 	rte_rcu_qsbr_check(t[0], token[0], true);
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < num_readers; i++) {
 		c = hash_data[0][0][enabled_core_ids[i]];
 		if (c != COUNTER_VALUE && c != 0) {
 			printf("Reader lcore %d did not complete #0 = %d\n",
@@ -832,7 +841,7 @@ test_rcu_qsbr_sw_sv_3qs(void)
 
 	/* Check the quiescent state status */
 	rte_rcu_qsbr_check(t[0], token[1], true);
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < num_readers; i++) {
 		c = hash_data[0][3][enabled_core_ids[i]];
 		if (c != COUNTER_VALUE && c != 0) {
 			printf("Reader lcore %d did not complete #3 = %d\n",
@@ -850,7 +859,7 @@ test_rcu_qsbr_sw_sv_3qs(void)
 
 	/* Check the quiescent state status */
 	rte_rcu_qsbr_check(t[0], token[2], true);
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < num_readers; i++) {
 		c = hash_data[0][6][enabled_core_ids[i]];
 		if (c != COUNTER_VALUE && c != 0) {
 			printf("Reader lcore %d did not complete #6 = %d\n",
@@ -869,7 +878,7 @@ test_rcu_qsbr_sw_sv_3qs(void)
 	writer_done = 1;
 
 	/* Wait and check return value from reader threads */
-	for (i = 0; i < 4; i++)
+	for (i = 0; i < num_readers; i++)
 		if (rte_eal_wait_lcore(enabled_core_ids[i]) < 0)
 			goto error;
 	rte_hash_free(h[0]);
@@ -899,6 +908,12 @@ test_rcu_qsbr_mw_mv_mqs(void)
 	unsigned int i, j;
 	unsigned int test_cores;
 
+	if (RTE_MAX_LCORE < 5 || num_cores < 4) {
+		printf("Not enough cores for %s, expecting at least 5\n",
+			__func__);
+		return TEST_SKIPPED;
+	}
+
 	writer_done = 0;
 	test_cores = num_cores / 4;
 	test_cores = test_cores * 4;
@@ -984,11 +999,6 @@ test_rcu_qsbr_main(void)
 {
 	uint16_t core_id;
 
-	if (rte_lcore_count() < 5) {
-		printf("Not enough cores for rcu_qsbr_autotest, expecting at least 5\n");
-		return TEST_SKIPPED;
-	}
-
 	num_cores = 0;
 	RTE_LCORE_FOREACH_SLAVE(core_id) {
 		enabled_core_ids[num_cores] = core_id;
diff --git a/dpdk/app/test/test_ring.c b/dpdk/app/test/test_ring.c
index aaf1e70ad8..4825c9e2e9 100644
--- a/dpdk/app/test/test_ring.c
+++ b/dpdk/app/test/test_ring.c
@@ -696,7 +696,7 @@ test_ring_basic_ex(void)
 
 	printf("%u ring entries are now free\n", rte_ring_free_count(rp));
 
-	for (i = 0; i < RING_SIZE; i ++) {
+	for (i = 0; i < RING_SIZE - 1; i ++) {
 		rte_ring_enqueue(rp, obj[i]);
 	}
 
@@ -705,7 +705,7 @@ test_ring_basic_ex(void)
 		goto fail_test;
 	}
 
-	for (i = 0; i < RING_SIZE; i ++) {
+	for (i = 0; i < RING_SIZE - 1; i ++) {
 		rte_ring_dequeue(rp, &obj[i]);
 	}
 
diff --git a/dpdk/app/test/test_ring_perf.c b/dpdk/app/test/test_ring_perf.c
index 70ee46ffe6..3cf27965de 100644
--- a/dpdk/app/test/test_ring_perf.c
+++ b/dpdk/app/test/test_ring_perf.c
@@ -296,12 +296,13 @@ load_loop_fn(void *p)
 static int
 run_on_all_cores(struct rte_ring *r)
 {
-	uint64_t total = 0;
+	uint64_t total;
 	struct thread_params param;
 	unsigned int i, c;
 
 	memset(&param, 0, sizeof(struct thread_params));
 	for (i = 0; i < RTE_DIM(bulk_sizes); i++) {
+		total = 0;
 		printf("\nBulk enq/dequeue count on size %u\n", bulk_sizes[i]);
 		param.size = bulk_sizes[i];
 		param.r = r;
diff --git a/dpdk/app/test/test_service_cores.c b/dpdk/app/test/test_service_cores.c
index a922c7ddcc..2a4978e29a 100644
--- a/dpdk/app/test/test_service_cores.c
+++ b/dpdk/app/test/test_service_cores.c
@@ -114,6 +114,7 @@ unregister_all(void)
 	}
 
 	rte_service_lcore_reset_all();
+	rte_eal_mp_wait_lcore();
 
 	return TEST_SUCCESS;
 }
diff --git a/dpdk/app/test/test_table_pipeline.c b/dpdk/app/test/test_table_pipeline.c
index 441338ac01..bc412c3081 100644
--- a/dpdk/app/test/test_table_pipeline.c
+++ b/dpdk/app/test/test_table_pipeline.c
@@ -190,11 +190,13 @@ check_pipeline_invalid_params(void)
 		goto fail;
 	}
 
-	p = rte_pipeline_create(&pipeline_params_3);
-	if (p != NULL) {
-		RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with invalid "
-			"socket\n", __func__);
-		goto fail;
+	if (rte_eal_has_hugepages()) {
+		p = rte_pipeline_create(&pipeline_params_3);
+		if (p != NULL) {
+			RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with "
+				"invalid socket\n", __func__);
+			goto fail;
+		}
 	}
 
 	/* Check pipeline consistency */
diff --git a/dpdk/buildtools/call-sphinx-build.py b/dpdk/buildtools/call-sphinx-build.py
new file mode 100755
index 0000000000..b9a3994e17
--- /dev/null
+++ b/dpdk/buildtools/call-sphinx-build.py
@@ -0,0 +1,31 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2019 Intel Corporation
+#
+
+import sys
+import os
+from os.path import join
+from subprocess import run, PIPE
+from distutils.version import StrictVersion
+
+(sphinx, src, dst) = sys.argv[1:]  # assign parameters to variables
+
+# for sphinx version >= 1.7 add parallelism using "-j auto"
+ver = run([sphinx, '--version'], stdout=PIPE).stdout.decode().split()[-1]
+sphinx_cmd = [sphinx]
+if StrictVersion(ver) >= StrictVersion('1.7'):
+    sphinx_cmd += ['-j', 'auto']
+
+# find all the files sphinx will process so we can write them as dependencies
+srcfiles = []
+for root, dirs, files in os.walk(src):
+    srcfiles.extend([join(root, f) for f in files])
+
+# run sphinx, putting the html output in a "html" directory
+process = run(sphinx_cmd + ['-b', 'html', src, join(dst, 'html')], check=True)
+print(str(process.args) + ' Done OK')
+
+# create a gcc format .d file giving all the dependencies of this doc build
+with open(join(dst, '.html.d'), 'w') as d:
+    d.write('html: ' + ' '.join(srcfiles) + '\n')
diff --git a/dpdk/buildtools/meson.build b/dpdk/buildtools/meson.build
index 6ef2c5721c..ea13d9fc3f 100644
--- a/dpdk/buildtools/meson.build
+++ b/dpdk/buildtools/meson.build
@@ -3,17 +3,21 @@
 
 subdir('pmdinfogen')
 
+pkgconf = find_program('pkg-config', 'pkgconf', required: false)
 pmdinfo = find_program('gen-pmdinfo-cfile.sh')
 
 check_experimental_syms = find_program('check-experimental-syms.sh')
+ldflags_ibverbs_static = find_program('options-ibverbs-static.sh')
 
 # set up map-to-def script using python, either built-in or external
 python3 = import('python').find_installation(required: false)
 if python3.found()
-	map_to_def_cmd = [python3, files('map_to_def.py')]
+	py3 = [python3]
 else
-	map_to_def_cmd = ['meson', 'runpython', files('map_to_def.py')]
+	py3 = ['meson', 'runpython']
 endif
+map_to_def_cmd = py3 + files('map_to_def.py')
+sphinx_wrapper = py3 + files('call-sphinx-build.py')
 
 # stable ABI always starts with "DPDK_"
 is_experimental_cmd = [find_program('grep', 'findstr'), '^DPDK_']
diff --git a/dpdk/buildtools/options-ibverbs-static.sh b/dpdk/buildtools/options-ibverbs-static.sh
index 0f285a343b..0740a711ff 100755
--- a/dpdk/buildtools/options-ibverbs-static.sh
+++ b/dpdk/buildtools/options-ibverbs-static.sh
@@ -9,6 +9,13 @@
 #
 # PKG_CONFIG_PATH may be required to be set if libibverbs.pc is not installed.
 
-pkg-config --libs-only-l --static libibverbs |
+lib='libibverbs'
+deps='pthread|nl'
+
+pkg-config --libs --static $lib |
 	tr '[:space:]' '\n' |
-	sed -r '/^-l(pthread|nl)/! s,(^-l)(.*),\1:lib\2.a,'
+	sed -r "/^-l($deps)/! s,(^-l)(.*),\1:lib\2.a," |   # explicit .a
+	sed -n '/^-[Ll]/p' |   # extra link options may break with make
+	tac |
+	awk "/^-l:$lib.a/&&c++ {next} 1" | # drop first duplicates of main lib
+	tac
diff --git a/dpdk/buildtools/pkg-config/meson.build b/dpdk/buildtools/pkg-config/meson.build
new file mode 100644
index 0000000000..39a8fd1c8e
--- /dev/null
+++ b/dpdk/buildtools/pkg-config/meson.build
@@ -0,0 +1,59 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation
+
+pkg = import('pkgconfig')
+pkg_extra_cflags = ['-include', 'rte_config.h'] + machine_args
+if is_freebsd
+	pkg_extra_cflags += ['-D__BSD_VISIBLE']
+endif
+
+# When calling pkg-config --static --libs, pkg-config will always output the
+# regular libs first, and then the extra libs from Libs.private field,
+# since the assumption is that those are additional dependencies for building
+# statically that the .a files depend upon. The output order of .pc fields is:
+#   Libs   Libs.private   Requires   Requires.private
+# The fields Requires* are for package names.
+# The flags of the DPDK libraries must be defined in Libs* fields.
+# However, the DPDK drivers are linked only in static builds (Libs.private),
+# and those need to come *before* the regular libraries (Libs field).
+# This requirement is satisfied by moving the regular libs in a separate file
+# included in the field Requires (after Libs.private).
+# Another requirement is to allow linking dependencies as shared libraries,
+# while linking static DPDK libraries and drivers. It is satisfied by
+# listing the static files in Libs.private with the explicit syntax -l:libfoo.a.
+# As a consequence, the regular DPDK libraries are already listed as static
+# in the field Libs.private. The second occurences of DPDK libraries,
+# included from Requires and used for shared library linkage case,
+# are skipped in the case of static linkage thanks to the flag --as-needed.
+
+
+pkg.generate(name: 'dpdk-libs',
+	filebase: 'libdpdk-libs',
+	description: '''Internal-only DPDK pkgconfig file. Not for direct use.
+Use libdpdk.pc instead of this file to query DPDK compile/link arguments''',
+	version: meson.project_version(),
+	subdirs: [get_option('include_subdir_arch'), '.'],
+	extra_cflags: pkg_extra_cflags,
+	libraries: ['-Wl,--as-needed'] + dpdk_libraries,
+	libraries_private: dpdk_extra_ldflags)
+
+platform_flags = []
+if not is_windows
+	platform_flags += ['-Wl,--export-dynamic'] # ELF only
+endif
+pkg.generate(name: 'DPDK', # main DPDK pkgconfig file
+	filebase: 'libdpdk',
+	version: meson.project_version(),
+	description: '''The Data Plane Development Kit (DPDK).
+Note that CFLAGS might contain an -march flag higher than typical baseline.
+This is required for a number of static inline functions in the public headers.''',
+	requires: ['libdpdk-libs', libbsd], # may need libbsd for string funcs
+	                  # if libbsd is not enabled, then this is blank
+	libraries_private: ['-Wl,--whole-archive'] +
+			dpdk_drivers + dpdk_static_libraries +
+			['-Wl,--no-whole-archive'] + platform_flags
+)
+
+# For static linking with dependencies as shared libraries,
+# the internal static libraries must be flagged explicitly.
+run_command(py3, 'set-static-linker-flags.py', check: true)
diff --git a/dpdk/buildtools/pkg-config/set-static-linker-flags.py b/dpdk/buildtools/pkg-config/set-static-linker-flags.py
new file mode 100644
index 0000000000..2745db34c2
--- /dev/null
+++ b/dpdk/buildtools/pkg-config/set-static-linker-flags.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation
+
+# Script to fix flags for static linking in pkgconfig files from meson
+# Should be called from meson build itself
+import os
+import sys
+
+
+def fix_ldflag(f):
+    if not f.startswith('-lrte_'):
+        return f
+    return '-l:lib' + f[2:] + '.a'
+
+
+def fix_libs_private(line):
+    if not line.startswith('Libs.private'):
+        return line
+    ldflags = [fix_ldflag(flag) for flag in line.split()]
+    return ' '.join(ldflags) + '\n'
+
+
+def process_pc_file(filepath):
+    print('Processing', filepath)
+    with open(filepath) as src:
+        lines = src.readlines()
+    with open(filepath, 'w') as dst:
+        dst.writelines([fix_libs_private(line) for line in lines])
+
+
+if 'MESON_BUILD_ROOT' not in os.environ:
+    print('This script must be called from a meson build environment')
+    sys.exit(1)
+for root, dirs, files in os.walk(os.environ['MESON_BUILD_ROOT']):
+    pc_files = [f for f in files if f.endswith('.pc')]
+    for f in pc_files:
+        process_pc_file(os.path.join(root, f))
diff --git a/dpdk/buildtools/pmdinfogen/pmdinfogen.h b/dpdk/buildtools/pmdinfogen/pmdinfogen.h
index c8a9e2136a..467216d12b 100644
--- a/dpdk/buildtools/pmdinfogen/pmdinfogen.h
+++ b/dpdk/buildtools/pmdinfogen/pmdinfogen.h
@@ -82,7 +82,7 @@ if ((fend) == ELFDATA2LSB) \
 	___x = le##width##toh(x); \
 else \
 	___x = be##width##toh(x); \
-	___x; \
+___x; \
 })
 
 #define TO_NATIVE(fend, width, x) CONVERT_NATIVE(fend, width, x)
diff --git a/dpdk/config/common_base b/dpdk/config/common_base
index 7dec7ed457..3406146372 100644
--- a/dpdk/config/common_base
+++ b/dpdk/config/common_base
@@ -328,7 +328,6 @@ CONFIG_RTE_LIBRTE_ICE_PMD=y
 CONFIG_RTE_LIBRTE_ICE_DEBUG_RX=n
 CONFIG_RTE_LIBRTE_ICE_DEBUG_TX=n
 CONFIG_RTE_LIBRTE_ICE_DEBUG_TX_FREE=n
-CONFIG_RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC=y
 CONFIG_RTE_LIBRTE_ICE_16BYTE_RX_DESC=n
 
 # Compile burst-oriented IAVF PMD driver
@@ -352,7 +351,7 @@ CONFIG_RTE_LIBRTE_MLX4_DEBUG=n
 
 #
 # Compile burst-oriented Mellanox ConnectX-4, ConnectX-5,
-# ConnectX-6 & Bluefield (MLX5) PMD
+# ConnectX-6 & BlueField (MLX5) PMD
 #
 CONFIG_RTE_LIBRTE_MLX5_PMD=n
 CONFIG_RTE_LIBRTE_MLX5_DEBUG=n
@@ -573,7 +572,6 @@ CONFIG_RTE_CRYPTO_MAX_DEVS=64
 # Compile PMD for ARMv8 Crypto device
 #
 CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO=n
-CONFIG_RTE_LIBRTE_PMD_ARMV8_CRYPTO_DEBUG=n
 
 #
 # Compile NXP CAAM JR crypto Driver
diff --git a/dpdk/config/defconfig_arm-armv7a-linuxapp-gcc b/dpdk/config/defconfig_arm-armv7a-linuxapp-gcc
index c91423f0e6..749f9924d5 100644
--- a/dpdk/config/defconfig_arm-armv7a-linuxapp-gcc
+++ b/dpdk/config/defconfig_arm-armv7a-linuxapp-gcc
@@ -45,7 +45,6 @@ CONFIG_RTE_LIBRTE_CXGBE_PMD=n
 CONFIG_RTE_LIBRTE_E1000_PMD=n
 CONFIG_RTE_LIBRTE_ENIC_PMD=n
 CONFIG_RTE_LIBRTE_FM10K_PMD=n
-CONFIG_RTE_LIBRTE_I40E_PMD=n
 CONFIG_RTE_LIBRTE_IXGBE_PMD=n
 CONFIG_RTE_LIBRTE_MLX4_PMD=n
 CONFIG_RTE_LIBRTE_VMXNET3_PMD=n
diff --git a/dpdk/config/defconfig_arm64-graviton2-linux-gcc b/dpdk/config/defconfig_arm64-graviton2-linux-gcc
new file mode 120000
index 0000000000..80ac94d54d
--- /dev/null
+++ b/dpdk/config/defconfig_arm64-graviton2-linux-gcc
@@ -0,0 +1 @@
+defconfig_arm64-graviton2-linuxapp-gcc
\ No newline at end of file
diff --git a/dpdk/config/defconfig_arm64-graviton2-linuxapp-gcc b/dpdk/config/defconfig_arm64-graviton2-linuxapp-gcc
new file mode 100644
index 0000000000..e99fef3073
--- /dev/null
+++ b/dpdk/config/defconfig_arm64-graviton2-linuxapp-gcc
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) Amazon.com, Inc or its affiliates
+#
+
+#include "defconfig_arm64-armv8a-linux-gcc"
+
+CONFIG_RTE_MACHINE="graviton2"
+CONFIG_RTE_MAX_LCORE=64
+CONFIG_RTE_CACHE_LINE_SIZE=64
+CONFIG_RTE_MAX_MEM_MB=1048576
+CONFIG_RTE_MAX_NUMA_NODES=1
+CONFIG_RTE_EAL_NUMA_AWARE_HUGEPAGES=n
+CONFIG_RTE_LIBRTE_VHOST_NUMA=n
diff --git a/dpdk/config/defconfig_graviton2 b/dpdk/config/defconfig_graviton2
new file mode 120000
index 0000000000..80ac94d54d
--- /dev/null
+++ b/dpdk/config/defconfig_graviton2
@@ -0,0 +1 @@
+defconfig_arm64-graviton2-linuxapp-gcc
\ No newline at end of file
diff --git a/dpdk/config/meson.build b/dpdk/config/meson.build
index 364a8d7394..b1f728ee86 100644
--- a/dpdk/config/meson.build
+++ b/dpdk/config/meson.build
@@ -14,6 +14,10 @@ foreach env:supported_exec_envs
 	set_variable('is_' + env, exec_env == env)
 endforeach
 
+# MS linker requires special treatment.
+# TODO: use cc.get_linker_id() with Meson >= 0.54
+is_ms_linker = is_windows and (cc.get_id() == 'clang')
+
 # set the major version, which might be used by drivers and libraries
 # depending on the configuration options
 pver = meson.project_version().split('.')
@@ -50,9 +54,11 @@ eal_pmd_path = join_paths(get_option('prefix'), driver_install_path)
 # driver .so files often depend upon the bus drivers for their connect bus,
 # e.g. ixgbe depends on librte_bus_pci. This means that the bus drivers need
 # to be in the library path, so symlink the drivers from the main lib directory.
-meson.add_install_script('../buildtools/symlink-drivers-solibs.sh',
-		get_option('libdir'),
-		pmd_subdir_opt)
+if not is_windows
+	meson.add_install_script('../buildtools/symlink-drivers-solibs.sh',
+			get_option('libdir'),
+			pmd_subdir_opt)
+endif
 
 # set the machine type and cflags for it
 if meson.is_cross_build()
@@ -98,14 +104,18 @@ dpdk_conf.set('RTE_TOOLCHAIN_' + toolchain.to_upper(), 1)
 
 dpdk_conf.set('RTE_ARCH_64', cc.sizeof('void *') == 8)
 
-add_project_link_arguments('-Wl,--no-as-needed', language: 'c')
+if not is_windows
+	add_project_link_arguments('-Wl,--no-as-needed', language: 'c')
+endif
 
-# use pthreads
-add_project_link_arguments('-pthread', language: 'c')
-dpdk_extra_ldflags += '-pthread'
+# use pthreads if available for the platform
+if not is_ms_linker
+	add_project_link_arguments('-pthread', language: 'c')
+	dpdk_extra_ldflags += '-pthread'
+endif
 
 # on some OS, maths functions are in a separate library
-if cc.find_library('libm', required : false).found()
+if cc.find_library('m', required : false).found()
 	# some libs depend on maths lib
 	add_project_link_arguments('-lm', language: 'c')
 	dpdk_extra_ldflags += '-lm'
@@ -136,18 +146,25 @@ if numa_dep.found() and cc.has_header('numaif.h')
 	dpdk_extra_ldflags += '-lnuma'
 endif
 
+has_libfdt = 0
+fdt_dep = cc.find_library('libfdt', required: false)
+if fdt_dep.found() and cc.has_header('fdt.h')
+	dpdk_conf.set10('RTE_HAS_LIBFDT', true)
+	has_libfdt = 1
+	add_project_link_arguments('-lfdt', language: 'c')
+	dpdk_extra_ldflags += '-lfdt'
+endif
+
 # check for libbsd
-libbsd = dependency('libbsd', required: false)
+libbsd = dependency('libbsd', required: false, method: 'pkg-config')
 if libbsd.found()
 	dpdk_conf.set('RTE_USE_LIBBSD', 1)
 endif
 
 # check for pcap
-pcap_dep = dependency('pcap', required: false)
-if pcap_dep.found()
-	# pcap got a pkg-config file only in 1.9.0 and before that meson uses
-	# an internal pcap-config finder, which is not compatible with
-	# cross-compilation, so try to fallback to find_library
+pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
+if not pcap_dep.found()
+	# pcap got a pkg-config file only in 1.9.0
 	pcap_dep = cc.find_library('pcap', required: false)
 endif
 if pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
@@ -166,6 +183,7 @@ warning_flags = [
 	# additional warnings in alphabetical order
 	'-Wcast-qual',
 	'-Wdeprecated',
+	'-Wformat',
 	'-Wformat-nonliteral',
 	'-Wformat-security',
 	'-Wmissing-declarations',
@@ -183,6 +201,10 @@ warning_flags = [
 	'-Wno-packed-not-aligned',
 	'-Wno-missing-field-initializers'
 ]
+if cc.get_id() == 'gcc' and cc.version().version_compare('>=10.0')
+# FIXME: Bugzilla 396
+	warning_flags += '-Wno-zero-length-bounds'
+endif
 if not dpdk_conf.get('RTE_ARCH_64')
 # for 32-bit, don't warn about casting a 32-bit pointer to 64-bit int - it's fine!!
 	warning_flags += '-Wno-pointer-to-int-cast'
@@ -202,6 +224,11 @@ dpdk_conf.set('RTE_LIBEAL_USE_HPET', get_option('use_hpet'))
 dpdk_conf.set('RTE_MAX_VFIO_GROUPS', 64)
 dpdk_conf.set('RTE_DRIVER_MEMPOOL_BUCKET_SIZE_KB', 64)
 dpdk_conf.set('RTE_LIBRTE_DPAA2_USE_PHYS_IOVA', true)
+if dpdk_conf.get('RTE_ARCH_64')
+	dpdk_conf.set('RTE_MAX_MEM_MB', 524288)
+else # for 32-bit we need smaller reserved memory areas
+	dpdk_conf.set('RTE_MAX_MEM_MB', 2048)
+endif
 
 
 compile_time_cpuflags = []
@@ -231,6 +258,16 @@ if is_freebsd
 	add_project_arguments('-D__BSD_VISIBLE', language: 'c')
 endif
 
+if is_windows
+	# Minimum supported API is Windows 7.
+	add_project_arguments('-D_WIN32_WINNT=0x0601', language: 'c')
+
+	# Use MinGW-w64 stdio, because DPDK assumes ANSI-compliant formatting.
+	if cc.get_id() == 'gcc'
+		add_project_arguments('-D__USE_MINGW_ANSI_STDIO', language: 'c')
+	endif
+endif
+
 if get_option('b_lto')
 	if cc.has_argument('-ffat-lto-objects')
 		add_project_arguments('-ffat-lto-objects', language: 'c')
@@ -243,3 +280,12 @@ if get_option('b_lto')
 		add_project_link_arguments('-Wno-lto-type-mismatch', language: 'c')
 	endif
 endif
+
+if get_option('default_library') == 'both'
+	error( '''
+    Unsupported value "both" for "default_library" option.
+
+    NOTE: DPDK always builds both shared and static libraries.  Please set
+    "default_library" to either "static" or "shared" to select default linkage
+    for apps and any examples.''')
+endif
diff --git a/dpdk/config/rte_config.h b/dpdk/config/rte_config.h
index d30786bc08..8ec0a58f19 100644
--- a/dpdk/config/rte_config.h
+++ b/dpdk/config/rte_config.h
@@ -38,7 +38,6 @@
 #define RTE_MAX_MEM_MB_PER_LIST 32768
 #define RTE_MAX_MEMSEG_PER_TYPE 32768
 #define RTE_MAX_MEM_MB_PER_TYPE 65536
-#define RTE_MAX_MEM_MB 524288
 #define RTE_MAX_MEMZONE 2560
 #define RTE_MAX_TAILQ 32
 #define RTE_LOG_DP_LEVEL RTE_LOG_INFO
@@ -95,11 +94,18 @@
 #define RTE_SCHED_PORT_N_GRINDERS 8
 #undef RTE_SCHED_VECTOR
 
+#ifdef RTE_LIBRTE_CRYPTO_SCHEDULER_PMD
+#define RTE_LIBRTE_PMD_CRYPTO_SCHEDULER 1
+#endif
+
 /* KNI defines */
 #define RTE_KNI_PREEMPT_DEFAULT 1
 
 /****** driver defines ********/
 
+/* Packet prefetching in PMDs */
+#define RTE_PMD_PACKET_PREFETCH 1
+
 /* QuickAssist device */
 /* Max. number of QuickAssist devices which can be attached */
 #define RTE_PMD_QAT_MAX_PCI_DEVICES 48
diff --git a/dpdk/config/x86/meson.build b/dpdk/config/x86/meson.build
index 8b0fa3e6f1..adc857ba28 100644
--- a/dpdk/config/x86/meson.build
+++ b/dpdk/config/x86/meson.build
@@ -15,11 +15,9 @@ if not is_windows
 endif
 
 # we require SSE4.2 for DPDK
-sse_errormsg = '''SSE4.2 instruction set is required for DPDK.
-Please set the machine type to "nehalem" or "corei7" or higher value'''
-
 if cc.get_define('__SSE4_2__', args: machine_args) == ''
-	error(sse_errormsg)
+	message('SSE 4.2 not enabled by default, explicitly enabling')
+	machine_args += '-msse4'
 endif
 
 base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2']
diff --git a/dpdk/devtools/check-forbidden-tokens.awk b/dpdk/devtools/check-forbidden-tokens.awk
index 8c89de3d4e..61ba707c9b 100755
--- a/dpdk/devtools/check-forbidden-tokens.awk
+++ b/dpdk/devtools/check-forbidden-tokens.awk
@@ -54,7 +54,7 @@ BEGIN {
 	}
 	for (i in deny_folders) {
 		re = "^\\+\\+\\+ b/" deny_folders[i];
-		if ($0 ~ deny_folders[i]) {
+		if ($0 ~ re) {
 			in_file = 1
 			last_file = $0
 		}
@@ -62,7 +62,7 @@ BEGIN {
 }
 END {
 	if (count > 0) {
-		print "Warning in " substr(last_file,6) ":"
+		print "Warning in " substr(last_file,7) ":"
 		print MESSAGE
 		exit RET_ON_FAIL
 	}
diff --git a/dpdk/devtools/check-symbol-change.sh b/dpdk/devtools/check-symbol-change.sh
index c5434f3bb0..ed2178e36e 100755
--- a/dpdk/devtools/check-symbol-change.sh
+++ b/dpdk/devtools/check-symbol-change.sh
@@ -17,13 +17,11 @@ build_map_changes()
 		# map files are altered, and all section/symbol names
 		# appearing between a triggering of this rule and the
 		# next trigger of this rule are associated with this file
-		/[-+] a\/.*\.map/ {map=$2; in_map=1}
+		/[-+] [ab]\/.*\.map/ {map=$2; in_map=1; next}
 
-		# Same pattern as above, only it matches on anything that
-		# does not end in 'map', indicating we have left the map chunk.
-		# When we hit this, turn off the in_map variable, which
-		# supresses the subordonate rules below
-		/[-+] a\/.*\.[^map]/ {in_map=0}
+		# The previous rule catches all .map files, anything else
+		# indicates we left the map chunk.
+		/[-+] [ab]\// {in_map=0}
 
 		# Triggering this rule, which starts a line and ends it
 		# with a { identifies a versioned section.  The section name is
diff --git a/dpdk/devtools/checkpatches.sh b/dpdk/devtools/checkpatches.sh
index b16bace927..9902e2a9bc 100755
--- a/dpdk/devtools/checkpatches.sh
+++ b/dpdk/devtools/checkpatches.sh
@@ -70,6 +70,14 @@ check_forbidden_additions() { # <patch>
 		-f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
 		"$1" || res=1
 
+	# links must prefer https over http
+	awk -v FOLDERS='doc' \
+		-v EXPRESSIONS='http://.*dpdk.org' \
+		-v RET_ON_FAIL=1 \
+		-v MESSAGE='Using non https link to dpdk.org' \
+		-f $(dirname $(readlink -f $0))/check-forbidden-tokens.awk \
+		"$1" || res=1
+
 	return $res
 }
 
diff --git a/dpdk/devtools/cocci.sh b/dpdk/devtools/cocci.sh
index 8b17a8ceba..ab9a6efe9a 100755
--- a/dpdk/devtools/cocci.sh
+++ b/dpdk/devtools/cocci.sh
@@ -1,34 +1,6 @@
 #! /bin/sh
-
-# BSD LICENSE
-#
-# Copyright 2015 EZchip Semiconductor Ltd.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#   * Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer.
-#   * Redistributions in binary form must reproduce the above copyright
-#     notice, this list of conditions and the following disclaimer in
-#     the documentation and/or other materials provided with the
-#     distribution.
-#   * Neither the name of EZchip Semiconductor nor the names of its
-#     contributors may be used to endorse or promote products derived
-#     from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2015-2020 Mellanox Technologies, Ltd
 
 # Apply coccinelle transforms.
 
diff --git a/dpdk/devtools/git-log-fixes.sh b/dpdk/devtools/git-log-fixes.sh
index e37ee22600..6d468d6731 100755
--- a/dpdk/devtools/git-log-fixes.sh
+++ b/dpdk/devtools/git-log-fixes.sh
@@ -94,11 +94,23 @@ stable_tag () # <hash>
 	fi
 }
 
+# print a marker for fixes tag presence
+fixes_tag () # <hash>
+{
+        if git log --format='%b' -1 $1 | grep -qi '^Fixes: *' ; then
+                echo 'F'
+        else
+                echo '-'
+        fi
+}
+
 git log --oneline --reverse $range |
 while read id headline ; do
 	origins=$(origin_filter $id)
 	stable=$(stable_tag $id)
-	[ "$stable" = "S" ] || [ -n "$origins" ] || echo "$headline" | grep -q fix || continue
+	fixes=$(fixes_tag $id)
+	[ "$stable" = "S" ] || [ "$fixes" = "F" ] || [ -n "$origins" ] || \
+		echo "$headline" | grep -q fix || continue
 	version=$(commit_version $id)
 	if [ -n "$origins" ] ; then
 		origver="$(origin_version $origins)"
@@ -108,5 +120,5 @@ while read id headline ; do
 	else
 		origver='N/A'
 	fi
-	printf '%s %7s %s %s (%s)\n' $version $id $stable "$headline" "$origver"
+	printf '%s %7s %s %s %s (%s)\n' $version $id $stable $fixes "$headline" "$origver"
 done
diff --git a/dpdk/devtools/test-build.sh b/dpdk/devtools/test-build.sh
index be565a1bea..52305fbb8c 100755
--- a/dpdk/devtools/test-build.sh
+++ b/dpdk/devtools/test-build.sh
@@ -149,7 +149,7 @@ config () # <directory> <target> <options>
 		! echo $3 | grep -q '+debug' || ( \
 		sed -ri=""  's,(RTE_LOG_DP_LEVEL=).*,\1RTE_LOG_DEBUG,' $1/.config
 		sed -ri=""           's,(_DEBUG.*=)n,\1y,' $1/.config
-		sed -ri=""            's,(_STAT.*=)n,\1y,' $1/.config
+		sed -ri=""  's,(_STAT)([S_].*=|=)n,\1\2y,' $1/.config
 		sed -ri="" 's,(TEST_PMD_RECORD_.*=)n,\1y,' $1/.config )
 
 		# Automatic configuration
diff --git a/dpdk/devtools/test-meson-builds.sh b/dpdk/devtools/test-meson-builds.sh
index 688567714b..8678a3d824 100755
--- a/dpdk/devtools/test-meson-builds.sh
+++ b/dpdk/devtools/test-meson-builds.sh
@@ -38,20 +38,21 @@ else
 fi
 
 default_path=$PATH
-default_pkgpath=$PKG_CONFIG_PATH
 default_cppflags=$CPPFLAGS
 default_cflags=$CFLAGS
 default_ldflags=$LDFLAGS
+default_meson_options=$DPDK_MESON_OPTIONS
 
 load_env () # <target compiler>
 {
 	targetcc=$1
+	# reset variables before target-specific config
 	export PATH=$default_path
-	export PKG_CONFIG_PATH=$default_pkgpath
+	unset PKG_CONFIG_PATH # global default makes no sense
 	export CPPFLAGS=$default_cppflags
 	export CFLAGS=$default_cflags
 	export LDFLAGS=$default_ldflags
-	unset DPDK_MESON_OPTIONS
+	export DPDK_MESON_OPTIONS=$default_meson_options
 	command -v $targetcc >/dev/null 2>&1 || return 1
 	DPDK_TARGET=$($targetcc -v 2>&1 | sed -n 's,^Target: ,,p')
 	. $srcdir/devtools/load-devel-config
@@ -134,19 +135,17 @@ done
 
 # Test installation of the x86-default target, to be used for checking
 # the sample apps build using the pkg-config file for cflags and libs
+load_env cc
 build_path=$(readlink -f $builds_dir/build-x86-default)
 export DESTDIR=$build_path/install-root
 $ninja_cmd -C $build_path install
-
-load_env cc
 pc_file=$(find $DESTDIR -name libdpdk.pc)
 export PKG_CONFIG_PATH=$(dirname $pc_file):$PKG_CONFIG_PATH
-
 # if pkg-config defines the necessary flags, test building some examples
 if pkg-config --define-prefix libdpdk >/dev/null 2>&1; then
 	export PKGCONF="pkg-config --define-prefix"
 	for example in cmdline helloworld l2fwd l3fwd skeleton timer; do
 		echo "## Building $example"
-		$MAKE -C $DESTDIR/usr/local/share/dpdk/examples/$example clean all
+		$MAKE -C $DESTDIR/usr/local/share/dpdk/examples/$example clean shared static
 	done
 fi
diff --git a/dpdk/doc/api/doxy-api-index.md b/dpdk/doc/api/doxy-api-index.md
index dff496be09..5568dbc616 100644
--- a/dpdk/doc/api/doxy-api-index.md
+++ b/dpdk/doc/api/doxy-api-index.md
@@ -1,4 +1,4 @@
-API {#index}
+API
 ===
 
 <!--
@@ -107,8 +107,6 @@ The public API headers are grouped by topics:
   [GRO]                (@ref rte_gro.h),
   [GSO]                (@ref rte_gso.h),
   [frag/reass]         (@ref rte_ip_frag.h),
-  [LPM IPv4 route]     (@ref rte_lpm.h),
-  [LPM IPv6 route]     (@ref rte_lpm6.h),
   [VXLAN]              (@ref rte_vxlan.h)
 
 - **QoS**:
@@ -116,6 +114,14 @@ The public API headers are grouped by topics:
   [scheduler]          (@ref rte_sched.h),
   [RED congestion]     (@ref rte_red.h)
 
+- **routing**:
+  [LPM IPv4 route]     (@ref rte_lpm.h),
+  [LPM IPv6 route]     (@ref rte_lpm6.h),
+  [RIB IPv4]           (@ref rte_rib.h),
+  [RIB IPv6]           (@ref rte_rib6.h),
+  [FIB IPv4]           (@ref rte_fib.h),
+  [FIB IPv6]           (@ref rte_fib6.h)
+
 - **hashes**:
   [hash]               (@ref rte_hash.h),
   [jhash]              (@ref rte_jhash.h),
diff --git a/dpdk/doc/api/doxy-api.conf.in b/dpdk/doc/api/doxy-api.conf.in
index 1c4392eecc..12f0a26a90 100644
--- a/dpdk/doc/api/doxy-api.conf.in
+++ b/dpdk/doc/api/doxy-api.conf.in
@@ -3,6 +3,7 @@
 
 PROJECT_NAME            = DPDK
 PROJECT_NUMBER          = @VERSION@
+USE_MDFILE_AS_MAINPAGE  = @TOPDIR@/doc/api/doxy-api-index.md
 INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \
                           @TOPDIR@/drivers/bus/vdev \
                           @TOPDIR@/drivers/crypto/scheduler \
diff --git a/dpdk/doc/api/meson.build b/dpdk/doc/api/meson.build
index 1c48b7672e..c72b880e10 100644
--- a/dpdk/doc/api/meson.build
+++ b/dpdk/doc/api/meson.build
@@ -3,53 +3,54 @@
 
 doxygen = find_program('doxygen', required: get_option('enable_docs'))
 
-if doxygen.found()
-	# due to the CSS customisation script, which needs to run on a file that
-	# is in a subdirectory that is created at build time and thus it cannot
-	# be an individual custom_target, we need to wrap the doxygen call in a
-	# script to run the CSS modification afterwards
-	generate_doxygen = find_program('generate_doxygen.sh')
-	generate_examples = find_program('generate_examples.sh')
-	generate_css = find_program('doxy-html-custom.sh')
-
-	inputdir = join_paths(meson.source_root(), 'examples')
-	htmldir = join_paths('share', 'doc', 'dpdk')
-
-	# due to the following bug: https://github.com/mesonbuild/meson/issues/4107
-	# if install is set to true it will override build_by_default and it will
-	# cause the target to always be built. If install were to be always set to
-	# false it would be impossible to install the docs.
-	# So use a configure option for now.
-	example = custom_target('examples.dox',
-		input: inputdir,
-		output: 'examples.dox',
-		command: [generate_examples, '@INPUT@', '@OUTPUT@'],
-		install: get_option('enable_docs'),
-		install_dir: htmldir,
-		build_by_default: get_option('enable_docs'))
-
-	cdata = configuration_data()
-	cdata.set('VERSION', meson.project_version())
-	cdata.set('API_EXAMPLES', join_paths(meson.build_root(), 'doc', 'api', 'examples.dox'))
-	cdata.set('OUTPUT', join_paths(meson.build_root(), 'doc', 'api'))
-	cdata.set('HTML_OUTPUT', 'api')
-	cdata.set('TOPDIR', meson.source_root())
-	cdata.set('STRIP_FROM_PATH', meson.source_root())
-
-	doxy_conf = configure_file(input: 'doxy-api.conf.in',
-		output: 'doxy-api.conf',
-		configuration: cdata,
-		install: false)
-
-	doxy_build = custom_target('doxygen',
-		depends: example,
-		input: doxy_conf,
-		output: 'api',
-		command: [generate_doxygen, '@INPUT@', '@OUTPUT@', generate_css],
-		install: get_option('enable_docs'),
-		install_dir: htmldir,
-		build_by_default: get_option('enable_docs'))
-
-	doc_targets += doxy_build
-	doc_target_names += 'Doxygen_API'
+if not doxygen.found()
+  subdir_done()
 endif
+
+# due to the CSS customisation script, which needs to run on a file that
+# is in a subdirectory that is created at build time and thus it cannot
+# be an individual custom_target, we need to wrap the doxygen call in a
+# script to run the CSS modification afterwards
+generate_doxygen = find_program('generate_doxygen.sh')
+generate_examples = find_program('generate_examples.sh')
+generate_css = find_program('doxy-html-custom.sh')
+
+inputdir = join_paths(meson.source_root(), 'examples')
+htmldir = join_paths('share', 'doc', 'dpdk')
+
+# due to the following bug: https://github.com/mesonbuild/meson/issues/4107
+# if install is set to true it will override build_by_default and it will
+# cause the target to always be built. If install were to be always set to
+# false it would be impossible to install the docs.
+# So use a configure option for now.
+example = custom_target('examples.dox',
+	input: inputdir,
+	output: 'examples.dox',
+	command: [generate_examples, '@INPUT@', '@OUTPUT@'],
+	install: get_option('enable_docs'),
+	install_dir: htmldir,
+	build_by_default: get_option('enable_docs'))
+
+cdata = configuration_data()
+cdata.set('VERSION', meson.project_version())
+cdata.set('API_EXAMPLES', join_paths(meson.build_root(), 'doc', 'api', 'examples.dox'))
+cdata.set('OUTPUT', join_paths(meson.build_root(), 'doc', 'api'))
+cdata.set('HTML_OUTPUT', 'api')
+cdata.set('TOPDIR', meson.source_root())
+cdata.set('STRIP_FROM_PATH', meson.source_root())
+
+doxy_conf = configure_file(input: 'doxy-api.conf.in',
+	output: 'doxy-api.conf',
+	configuration: cdata)
+
+doxy_build = custom_target('doxygen',
+	depends: example,
+	input: doxy_conf,
+	output: 'api',
+	command: [generate_doxygen, '@INPUT@', '@OUTPUT@', generate_css],
+	install: get_option('enable_docs'),
+	install_dir: htmldir,
+	build_by_default: get_option('enable_docs'))
+
+doc_targets += doxy_build
+doc_target_names += 'Doxygen_API'
diff --git a/dpdk/doc/build-sdk-meson.txt b/dpdk/doc/build-sdk-meson.txt
index fc7fe37b54..8fb60a7c11 100644
--- a/dpdk/doc/build-sdk-meson.txt
+++ b/dpdk/doc/build-sdk-meson.txt
@@ -1,3 +1,6 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2018 Intel Corporation.
+
 INSTALLING DPDK USING THE MESON BUILD SYSTEM
 ---------------------------------------------
 
@@ -94,14 +97,17 @@ Examples of setting the same options using meson configure::
 
 	meson configure -Dmax_lcores=8
 
-NOTE: once meson has been run to configure a build in a directory, it
-cannot be run again on the same directory. Instead ``meson configure``
-should be used to change the build settings within the directory, and when
-``ninja`` is called to do the build itself, it will trigger the necessary
-re-scan from meson.
+.. note::
+
+        once meson has been run to configure a build in a directory, it
+        cannot be run again on the same directory. Instead ``meson configure``
+        should be used to change the build settings within the directory, and when
+        ``ninja`` is called to do the build itself, it will trigger the necessary
+        re-scan from meson.
 
-NOTE: machine=default uses a config that works on all supported architectures
-regardless of the capabilities of the machine where the build is happening.
+.. note::
+        machine=default uses a config that works on all supported architectures
+        regardless of the capabilities of the machine where the build is happening.
 
 As well as those settings taken from ``meson configure``, other options
 such as the compiler to use can be passed via environment variables. For
@@ -109,9 +115,11 @@ example::
 
 	CC=clang meson clang-build
 
-NOTE: for more comprehensive overriding of compilers or other environment
-settings, the tools for cross-compilation may be considered. However, for
-basic overriding of the compiler etc., the above form works as expected.
+.. note::
+
+        for more comprehensive overriding of compilers or other environment
+        settings, the tools for cross-compilation may be considered. However, for
+        basic overriding of the compiler etc., the above form works as expected.
 
 
 Performing the Build
@@ -182,7 +190,7 @@ From examples/helloworld/Makefile::
 	PC_FILE := $(shell pkg-config --path libdpdk)
 	CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
 	LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
-	LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+	LDFLAGS_STATIC = $(shell pkg-config --static --libs libdpdk)
 
 	build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 		$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/doc/guides/compressdevs/qat_comp.rst b/dpdk/doc/guides/compressdevs/qat_comp.rst
index 6421f767c4..757611a30c 100644
--- a/dpdk/doc/guides/compressdevs/qat_comp.rst
+++ b/dpdk/doc/guides/compressdevs/qat_comp.rst
@@ -37,7 +37,10 @@ Limitations
 -----------
 
 * Compressdev level 0, no compression, is not supported.
-* Queue pairs are not thread-safe (that is, within a single queue pair, RX and TX from different lcores is not supported).
+* Queue-pairs are thread-safe on Intel CPUs but Queues are not (that is, within a single
+  queue-pair all enqueues to the TX queue must be done from one thread and all dequeues
+  from the RX queue must be done from one thread, but enqueues and dequeues may be done
+  in different threads.)
 * No BSD support as BSD QAT kernel driver not available.
 * When using Deflate dynamic huffman encoding for compression, the input size (op.src.length)
   must be < CONFIG_RTE_PMD_QAT_COMP_IM_BUFFER_SIZE from the config file,
diff --git a/dpdk/doc/guides/conf.py b/dpdk/doc/guides/conf.py
index e2b52e2df9..c1a82be95b 100644
--- a/dpdk/doc/guides/conf.py
+++ b/dpdk/doc/guides/conf.py
@@ -237,7 +237,7 @@ def generate_overview_table(output_filename, table_id, section, table_name, titl
                                                                 ini_filename))
                 continue
 
-            if value is not '':
+            if value:
                 # Get the first letter only.
                 ini_data[ini_filename][name] = value[0]
 
@@ -314,16 +314,22 @@ def print_table_css(outfile, table_id):
          cursor: default;
          overflow: hidden;
       }
+      table#idx p {
+         margin: 0;
+         line-height: inherit;
+      }
       table#idx th, table#idx td {
          text-align: center;
+         border: solid 1px #ddd;
       }
       table#idx th {
-         font-size: 72%;
+         padding: 0.5em 0;
+      }
+      table#idx th, table#idx th p {
+         font-size: 11px;
          white-space: pre-wrap;
          vertical-align: top;
-         padding: 0.5em 0;
          min-width: 0.9em;
-         width: 2em;
       }
       table#idx col:first-child {
          width: 0;
@@ -332,9 +338,11 @@ def print_table_css(outfile, table_id):
          vertical-align: bottom;
       }
       table#idx td {
-         font-size: 70%;
          padding: 1px;
       }
+      table#idx td, table#idx td p {
+         font-size: 11px;
+      }
       table#idx td:first-child {
          padding-left: 1em;
          text-align: left;
@@ -410,4 +418,8 @@ def setup(app):
         # Process the numref references once the doctree has been created.
         app.connect('doctree-resolved', process_numref)
 
-    app.add_stylesheet('css/custom.css')
+    try:
+        # New function in sphinx 1.8
+        app.add_css_file('css/custom.css')
+    except:
+        app.add_stylesheet('css/custom.css')
diff --git a/dpdk/doc/guides/contributing/abi_policy.rst b/dpdk/doc/guides/contributing/abi_policy.rst
index 05ca95980b..87942c8ac3 100644
--- a/dpdk/doc/guides/contributing/abi_policy.rst
+++ b/dpdk/doc/guides/contributing/abi_policy.rst
@@ -27,8 +27,8 @@ General Guidelines
 #. The removal of symbols is considered an :ref:`ABI breakage <abi_breakages>`,
    once approved these will form part of the next ABI version.
 #. Libraries or APIs marked as :ref:`experimental <experimental_apis>` may
-   change without constraint, as they are not considered part of an ABI version.
-   Experimental libraries have the major ABI version ``0``.
+   be changed or removed without prior notice, as they are not considered part
+   of an ABI version.
 #. Updates to the :ref:`minimum hardware requirements <hw_rqmts>`, which drop
    support for hardware which was previously supported, should be treated as an
    ABI change.
@@ -220,19 +220,18 @@ Examples of ABI Changes
 The following are examples of allowable ABI changes occurring between
 declarations of major ABI versions.
 
-* DPDK 19.11 release, defines the function ``rte_foo()``, and ``rte_foo()``
-  as part of the major ABI version ``20``.
+* DPDK 19.11 release defines the function ``rte_foo()`` ; ``rte_foo()``
+  is part of the major ABI version ``20``.
 
-* DPDK 20.02 release defines a new function ``rte_foo(uint8_t bar)``, and
-  this is not a problem as long as the symbol ``rte_foo@DPDK20`` is
+* DPDK 20.02 release defines a new function ``rte_foo(uint8_t bar)``.
+  This is not a problem as long as the symbol ``rte_foo@DPDK20`` is
   preserved through :ref:`abi_versioning`.
 
   - The new function may be marked with the ``__rte_experimental`` tag for a
     number of releases, as described in the section :ref:`experimental_apis`.
 
-  - Once ``rte_foo(uint8_t bar)`` becomes non-experimental ``rte_foo()`` is then
-    declared as ``__rte_depreciated``, with an associated deprecation notice
-    provided.
+  - Once ``rte_foo(uint8_t bar)`` becomes non-experimental, ``rte_foo()`` is
+    declared as ``__rte_deprecated`` and an deprecation notice is provided.
 
 * DPDK 19.11 is not re-released to include ``rte_foo(uint8_t bar)``, the new
   version of ``rte_foo`` only exists from DPDK 20.02 onwards as described in the
@@ -242,13 +241,13 @@ declarations of major ABI versions.
   rte_baz()``. This function may or may not exist in the DPDK 20.05 release.
 
 * An application ``dPacket`` wishes to use ``rte_foo(uint8_t bar)``, before the
-  declaration of the DPDK ``21`` major API version. The application can only
+  declaration of the DPDK ``21`` major ABI version. The application can only
   ensure its runtime dependencies are met by specifying ``DPDK (>= 20.2)`` as
-  an explicit package dependency, as the soname only may only indicate the
+  an explicit package dependency, as the soname can only indicate the
   supported major ABI version.
 
 * At the release of DPDK 20.11, the function ``rte_foo(uint8_t bar)`` becomes
-  formally part of then new major ABI version DPDK 21.0 and ``rte_foo()`` may be
+  formally part of then new major ABI version DPDK ``21`` and ``rte_foo()`` may be
   removed.
 
 .. _deprecation_notices:
@@ -290,7 +289,7 @@ APIs
 ~~~~
 
 APIs marked as ``experimental`` are not considered part of an ABI version and
-may change without warning at any time. Since changes to APIs are most likely
+may be changed or removed without prior notice. Since changes to APIs are most likely
 immediately after their introduction, as users begin to take advantage of those
 new APIs and start finding issues with them, new DPDK APIs will be automatically
 marked as ``experimental`` to allow for a period of stabilization before they
@@ -321,7 +320,5 @@ Libraries
 ~~~~~~~~~
 
 Libraries marked as ``experimental`` are entirely not considered part of an ABI
-version, and may change without warning at any time. Experimental libraries
-always have a major version of ``0`` to indicate they exist outside of
-:ref:`abi_versioning` , with the minor version incremented with each ABI change
-to library.
+version.
+All functions in such libraries may be changed or removed without prior notice.
diff --git a/dpdk/doc/guides/contributing/abi_versioning.rst b/dpdk/doc/guides/contributing/abi_versioning.rst
index a21f4e7a41..ea9d99606b 100644
--- a/dpdk/doc/guides/contributing/abi_versioning.rst
+++ b/dpdk/doc/guides/contributing/abi_versioning.rst
@@ -200,7 +200,7 @@ private, is safe), but it also requires modifying the code as follows
 Note also that, being a public function, the header file prototype must also be
 changed, as must all the call sites, to reflect the new ABI footprint.  We will
 maintain previous ABI versions that are accessible only to previously compiled
-binaries
+binaries.
 
 The addition of a parameter to the function is ABI breaking as the function is
 public, and existing application may use it in its current form. However, the
@@ -266,12 +266,12 @@ This file needs to be modified as follows
 
    } DPDK_20;
 
-The addition of the new block tells the linker that a new version node is
-available (DPDK_21), which contains the symbol rte_acl_create, and inherits
+The addition of the new block tells the linker that a new version node
+``DPDK_21`` is available, which contains the symbol rte_acl_create, and inherits
 the symbols from the DPDK_20 node. This list is directly translated into a
-list of exported symbols when DPDK is compiled as a shared library
+list of exported symbols when DPDK is compiled as a shared library.
 
-Next, we need to specify in the code which function map to the rte_acl_create
+Next, we need to specify in the code which function maps to the rte_acl_create
 symbol at which versions.  First, at the site of the initial symbol definition,
 we need to update the function so that it is uniquely named, and not in conflict
 with the public symbol name
@@ -288,24 +288,29 @@ with the public symbol name
         ...
 
 Note that the base name of the symbol was kept intact, as this is conducive to
-the macros used for versioning symbols and we have annotated the function as an
-implementation of versioned symbol.  That is our next step, mapping this new
-symbol name to the initial symbol name at version node 20.  Immediately after
-the function, we add this line of code
+the macros used for versioning symbols and we have annotated the function as
+``__vsym``, an implementation of a versioned symbol . That is our next step,
+mapping this new symbol name to the initial symbol name at version node 20.
+Immediately after the function, we add the VERSION_SYMBOL macro.
 
 .. code-block:: c
 
+   #include <rte_function_versioning.h>
+
+   ...
    VERSION_SYMBOL(rte_acl_create, _v20, 20);
 
 Remembering to also add the rte_function_versioning.h header to the requisite c
-file where these changes are being made. The above macro instructs the linker to
+file where these changes are being made. The macro instructs the linker to
 create a new symbol ``rte_acl_create@DPDK_20``, which matches the symbol created
 in older builds, but now points to the above newly named function. We have now
 mapped the original rte_acl_create symbol to the original function (but with a
 new name).
 
-Next, we need to create the 21 version of the symbol. We create a new function
-name, with a different suffix, and implement it appropriately
+Please see the section :ref:`Enabling versioning macros
+<enabling_versioning_macros>` to enable this macro in the meson/ninja build.
+Next, we need to create the new ``v21`` version of the symbol. We create a new
+function name, with the ``v21`` suffix, and implement it appropriately.
 
 .. code-block:: c
 
@@ -320,35 +325,58 @@ name, with a different suffix, and implement it appropriately
    }
 
 This code serves as our new API call. Its the same as our old call, but adds the
-new parameter in place. Next we need to map this function to the symbol
-``rte_acl_create@DPDK_21``. To do this, we modify the public prototype of the
-call in the header file, adding the macro there to inform all including
-applications, that on re-link, the default rte_acl_create symbol should point to
-this function. Note that we could do this by simply naming the function above
-rte_acl_create, and the linker would chose the most recent version tag to apply
-in the version script, but we can also do this in the header file
+new parameter in place. Next we need to map this function to the new default
+symbol ``rte_acl_create@DPDK_21``. To do this, immediately after the function,
+we add the BIND_DEFAULT_SYMBOL macro.
+
+.. code-block:: c
+
+   #include <rte_function_versioning.h>
+
+   ...
+   BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 21);
+
+The macro instructs the linker to create the new default symbol
+``rte_acl_create@DPDK_21``, which points to the above newly named function.
+
+We finally modify the prototype of the call in the public header file,
+such that it contains both versions of the symbol and the public API.
 
 .. code-block:: c
 
    struct rte_acl_ctx *
-   -rte_acl_create(const struct rte_acl_param *param);
-   +rte_acl_create_v21(const struct rte_acl_param *param, int debug);
-   +BIND_DEFAULT_SYMBOL(rte_acl_create, _v21, 21);
-
-The BIND_DEFAULT_SYMBOL macro explicitly tells applications that include this
-header, to link to the rte_acl_create_v21 function and apply the DPDK_21
-version node to it.  This method is more explicit and flexible than just
-re-implementing the exact symbol name, and allows for other features (such as
-linking to the old symbol version by default, when the new ABI is to be opt-in
-for a period.
-
-One last thing we need to do.  Note that we've taken what was a public symbol,
-and duplicated it into two uniquely and differently named symbols.  We've then
-mapped each of those back to the public symbol ``rte_acl_create`` with different
-version tags.  This only applies to dynamic linking, as static linking has no
-notion of versioning.  That leaves this code in a position of no longer having a
-symbol simply named ``rte_acl_create`` and a static build will fail on that
-missing symbol.
+   rte_acl_create(const struct rte_acl_param *param);
+
+   struct rte_acl_ctx * __vsym
+   rte_acl_create_v20(const struct rte_acl_param *param);
+
+   struct rte_acl_ctx * __vsym
+   rte_acl_create_v21(const struct rte_acl_param *param, int debug);
+
+
+And that's it, on the next shared library rebuild, there will be two versions of
+rte_acl_create, an old DPDK_20 version, used by previously built applications,
+and a new DPDK_21 version, used by future built applications.
+
+.. note::
+
+   **Before you leave**, please take care reviewing the sections on
+   :ref:`mapping static symbols <mapping_static_symbols>`,
+   :ref:`enabling versioning macros <enabling_versioning_macros>`,
+   and :ref:`ABI deprecation <abi_deprecation>`.
+
+
+.. _mapping_static_symbols:
+
+Mapping static symbols
+______________________
+
+Now we've taken what was a public symbol, and duplicated it into two uniquely
+and differently named symbols. We've then mapped each of those back to the
+public symbol ``rte_acl_create`` with different version tags. This only applies
+to dynamic linking, as static linking has no notion of versioning. That leaves
+this code in a position of no longer having a symbol simply named
+``rte_acl_create`` and a static build will fail on that missing symbol.
 
 To correct this, we can simply map a function of our choosing back to the public
 symbol in the static build with the ``MAP_STATIC_SYMBOL`` macro.  Generally the
@@ -369,15 +397,31 @@ defined, we add this
 That tells the compiler that, when building a static library, any calls to the
 symbol ``rte_acl_create`` should be linked to ``rte_acl_create_v21``
 
-That's it, on the next shared library rebuild, there will be two versions of
-rte_acl_create, an old DPDK_20 version, used by previously built applications,
-and a new DPDK_21 version, used by future built applications.
 
+.. _enabling_versioning_macros:
+
+Enabling versioning macros
+__________________________
+
+Finally, we need to indicate to the meson/ninja build system
+to enable versioning macros when building the
+library or driver. In the libraries or driver where we have added symbol
+versioning, in the ``meson.build`` file we add the following
+
+.. code-block:: none
+
+   use_function_versioning = true
+
+at the start of the head of the file. This will indicate to the tool-chain to
+enable the function version macros when building. There is no corresponding
+directive required for the ``make`` build system.
+
+.. _abi_deprecation:
 
 Deprecating part of a public API
 ________________________________
 
-Lets assume that you've done the above update, and in preparation for the next
+Lets assume that you've done the above updates, and in preparation for the next
 major ABI version you decide you would like to retire the old version of the
 function. After having gone through the ABI deprecation announcement process,
 removal is easy. Start by removing the symbol from the requisite version map
@@ -421,8 +465,8 @@ Next remove the corresponding versioned export.
 
 
 Note that the internal function definition could also be removed, but its used
-in our example by the newer version v21, so we leave it in place and declare it
-as static. This is a coding style choice.
+in our example by the newer version ``v21``, so we leave it in place and declare
+it as static. This is a coding style choice.
 
 .. _deprecating_entire_abi:
 
diff --git a/dpdk/doc/guides/contributing/documentation.rst b/dpdk/doc/guides/contributing/documentation.rst
index 27e4b13be1..3924771cf0 100644
--- a/dpdk/doc/guides/contributing/documentation.rst
+++ b/dpdk/doc/guides/contributing/documentation.rst
@@ -82,7 +82,7 @@ added to by the developer.
 * **API documentation**
 
   The API documentation explains how to use the public DPDK functions.
-  The `API index page <http://doc.dpdk.org/api/>`_ shows the generated API documentation with related groups of functions.
+  The `API index page <https://doc.dpdk.org/api/>`_ shows the generated API documentation with related groups of functions.
 
   The API documentation should be updated via Doxygen comments when new functions are added.
 
@@ -561,14 +561,14 @@ Hyperlinks
 ~~~~~~~~~~
 
 * Links to external websites can be plain URLs.
-  The following is rendered as http://dpdk.org::
+  The following is rendered as https://dpdk.org::
 
-     http://dpdk.org
+     https://dpdk.org
 
 * They can contain alternative text.
-  The following is rendered as `Check out DPDK <http://dpdk.org>`_::
+  The following is rendered as `Check out DPDK <https://dpdk.org>`_::
 
-     `Check out DPDK <http://dpdk.org>`_
+     `Check out DPDK <https://dpdk.org>`_
 
 * An internal link can be generated by placing labels in the document with the format ``.. _label_name``.
 
@@ -666,7 +666,7 @@ The following are some guidelines for use of Doxygen in the DPDK API documentati
        */
 
   In the API documentation the functions will be rendered as links, see the
-  `online section of the rte_ethdev.h docs <http://doc.dpdk.org/api/rte__ethdev_8h.html>`_ that contains the above text.
+  `online section of the rte_ethdev.h docs <https://doc.dpdk.org/api/rte__ethdev_8h.html>`_ that contains the above text.
 
 * The ``@see`` keyword can be used to create a *see also* link to another file or library.
   This directive should be placed on one line at the bottom of the documentation section.
diff --git a/dpdk/doc/guides/contributing/patches.rst b/dpdk/doc/guides/contributing/patches.rst
index 0686450e45..5ca037757e 100644
--- a/dpdk/doc/guides/contributing/patches.rst
+++ b/dpdk/doc/guides/contributing/patches.rst
@@ -28,9 +28,9 @@ The DPDK development process has the following features:
 * All sub-repositories are merged into main repository for ``-rc1`` and ``-rc2`` versions of the release.
 * After the ``-rc2`` release all patches should target the main repository.
 
-The mailing list for DPDK development is `dev@dpdk.org <http://mails.dpdk.org/archives/dev/>`_.
-Contributors will need to `register for the mailing list <http://mails.dpdk.org/listinfo/dev>`_ in order to submit patches.
-It is also worth registering for the DPDK `Patchwork <http://patches.dpdk.org/project/dpdk/list/>`_
+The mailing list for DPDK development is `dev@dpdk.org <https://mails.dpdk.org/archives/dev/>`_.
+Contributors will need to `register for the mailing list <https://mails.dpdk.org/listinfo/dev>`_ in order to submit patches.
+It is also worth registering for the DPDK `Patchwork <https://patches.dpdk.org/project/dpdk/list/>`_
 
 If you are using the GitHub service, you can link your repository to
 the ``travis-ci.org`` build service.  When you push patches to your GitHub
@@ -130,12 +130,12 @@ The source code can be cloned using either of the following:
 main repository::
 
     git clone git://dpdk.org/dpdk
-    git clone http://dpdk.org/git/dpdk
+    git clone https://dpdk.org/git/dpdk
 
-sub-repositories (`list <http://git.dpdk.org/next>`_)::
+sub-repositories (`list <https://git.dpdk.org/next>`_)::
 
     git clone git://dpdk.org/next/dpdk-next-*
-    git clone http://dpdk.org/git/next/dpdk-next-*
+    git clone https://dpdk.org/git/next/dpdk-next-*
 
 Make your Changes
 -----------------
@@ -182,7 +182,7 @@ A good way of thinking about whether a patch should be split is to consider whet
 applied without dependencies as a backport.
 
 It is better to keep the related documentation changes in the same patch
-file as the code, rather than one big documentation patch at then end of a
+file as the code, rather than one big documentation patch at the end of a
 patchset. This makes it easier for future maintenance and development of the
 code.
 
@@ -320,7 +320,7 @@ Patch for Stable Releases
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 All fix patches to the master branch that are candidates for backporting
-should also be CCed to the `stable@dpdk.org <http://mails.dpdk.org/listinfo/stable>`_
+should also be CCed to the `stable@dpdk.org <https://mails.dpdk.org/listinfo/stable>`_
 mailing list.
 In the commit message body the Cc: stable@dpdk.org should be inserted as follows::
 
@@ -423,7 +423,7 @@ are loaded from the following files, in order of preference::
    ~/.config/dpdk/devel.config
    /etc/dpdk/devel.config.
 
-Once the environment variable the script can be run as follows::
+Once the environment variable is set, the script can be run as follows::
 
    devtools/checkpatches.sh ~/patch/
 
@@ -548,7 +548,7 @@ If the patch is in relation to a previous email thread you can add it to the sam
    git send-email --to dev@dpdk.org --in-reply-to <1234-foo@bar.com> 000*.patch
 
 The Message ID can be found in the raw text of emails or at the top of each Patchwork patch,
-`for example <http://patches.dpdk.org/patch/7646/>`_.
+`for example <https://patches.dpdk.org/patch/7646/>`_.
 Shallow threading (``--thread --no-chain-reply-to``) is preferred for a patch series.
 
 Once submitted your patches will appear on the mailing list and in Patchwork.
diff --git a/dpdk/doc/guides/contributing/stable.rst b/dpdk/doc/guides/contributing/stable.rst
index 4d38bb8606..021c762fc6 100644
--- a/dpdk/doc/guides/contributing/stable.rst
+++ b/dpdk/doc/guides/contributing/stable.rst
@@ -51,7 +51,7 @@ agreement and a commitment from a maintainer. The current policy is that each
 year's November (X.11) release will be maintained as an LTS for 2 years.
 
 After the X.11 release, an LTS branch will be created for it at
-http://git.dpdk.org/dpdk-stable where bugfixes will be backported to.
+https://git.dpdk.org/dpdk-stable where bugfixes will be backported to.
 
 A LTS release may align with the declaration of a new major ABI version,
 please read the :doc:`abi_policy` for more information.
@@ -107,7 +107,7 @@ The Stable and LTS release are coordinated on the stable@dpdk.org mailing
 list.
 
 All fix patches to the master branch that are candidates for backporting
-should also be CCed to the `stable@dpdk.org <http://mails.dpdk.org/listinfo/stable>`_
+should also be CCed to the `stable@dpdk.org <https://mails.dpdk.org/listinfo/stable>`_
 mailing list.
 
 
@@ -118,7 +118,7 @@ A Stable Release will be released by:
 
 * Tagging the release with YY.MM.n (year, month, number).
 * Uploading a tarball of the release to dpdk.org.
-* Sending an announcement to the `announce@dpdk.org <http://mails.dpdk.org/listinfo/announce>`_
+* Sending an announcement to the `announce@dpdk.org <https://mails.dpdk.org/listinfo/announce>`_
   list.
 
-Stable releases are available on the `dpdk.org download page <http://core.dpdk.org/download/>`_.
+Stable releases are available on the `dpdk.org download page <https://core.dpdk.org/download/>`_.
diff --git a/dpdk/doc/guides/contributing/vulnerability.rst b/dpdk/doc/guides/contributing/vulnerability.rst
index 5484119d19..da00acd4f0 100644
--- a/dpdk/doc/guides/contributing/vulnerability.rst
+++ b/dpdk/doc/guides/contributing/vulnerability.rst
@@ -36,11 +36,11 @@ Report
 
 Do not use Bugzilla (unsecured).
 Instead, send GPG-encrypted emails
-to `security@dpdk.org <http://core.dpdk.org/security#contact>`_.
+to `security@dpdk.org <https://core.dpdk.org/security#contact>`_.
 Anyone can post to this list.
 In order to reduce the disclosure of a vulnerability in the early stages,
 membership of this list is intentionally limited to a `small number of people
-<http://mails.dpdk.org/roster/security>`_.
+<https://mails.dpdk.org/roster/security>`_.
 
 It is additionally encouraged to GPG-sign one-on-one conversations
 as part of the security process.
@@ -188,7 +188,7 @@ Downstream stakeholders are expected not to deploy or disclose patches
 until the embargo is passed, otherwise they will be removed from the list.
 
 Downstream stakeholders (in `security-prerelease list
-<http://mails.dpdk.org/roster/security-prerelease>`_), are:
+<https://mails.dpdk.org/roster/security-prerelease>`_), are:
 
 * Operating system vendors known to package DPDK
 * Major DPDK users, considered trustworthy by the technical board, who
diff --git a/dpdk/doc/guides/cryptodevs/aesni_gcm.rst b/dpdk/doc/guides/cryptodevs/aesni_gcm.rst
index 151aa30606..a8ea3206ba 100644
--- a/dpdk/doc/guides/cryptodevs/aesni_gcm.rst
+++ b/dpdk/doc/guides/cryptodevs/aesni_gcm.rst
@@ -45,6 +45,19 @@ can be downloaded in `<https://github.com/01org/intel-ipsec-mb/archive/v0.53.zip
     make
     make install
 
+The library requires NASM to be built. Depending on the library version, it might require a minimum NASM version (e.g. v0.53 requires at least NASM 2.13.03).
+
+NASM is packaged for different OS. However, on some OS the version is too old, so a manual installation is required.
+In that case, NASM can be downloaded from
+`NASM website <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_.
+Once it is downloaded, extract it and follow these steps:
+
+.. code-block:: console
+
+    ./configure
+    make
+    make install
+
 As a reference, the following table shows a mapping between the past DPDK versions
 and the external crypto libraries supported by them:
 
diff --git a/dpdk/doc/guides/cryptodevs/aesni_mb.rst b/dpdk/doc/guides/cryptodevs/aesni_mb.rst
index 5d8fb46efe..ca6c169858 100644
--- a/dpdk/doc/guides/cryptodevs/aesni_mb.rst
+++ b/dpdk/doc/guides/cryptodevs/aesni_mb.rst
@@ -72,6 +72,19 @@ can be downloaded from `<https://github.com/01org/intel-ipsec-mb/archive/v0.53.z
     make
     make install
 
+The library requires NASM to be built. Depending on the library version, it might require a minimum NASM version (e.g. v0.53 requires at least NASM 2.13.03).
+
+NASM is packaged for different OS. However, on some OS the version is too old, so a manual installation is required.
+In that case, NASM can be downloaded from
+`NASM website <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_.
+Once it is downloaded, extract it and follow these steps:
+
+.. code-block:: console
+
+    ./configure
+    make
+    make install
+
 As a reference, the following table shows a mapping between the past DPDK versions
 and the Multi-Buffer library version supported by them:
 
diff --git a/dpdk/doc/guides/cryptodevs/features/kasumi.ini b/dpdk/doc/guides/cryptodevs/features/kasumi.ini
index f3d061009b..7ee866e8f4 100644
--- a/dpdk/doc/guides/cryptodevs/features/kasumi.ini
+++ b/dpdk/doc/guides/cryptodevs/features/kasumi.ini
@@ -6,6 +6,7 @@
 [Features]
 Symmetric crypto       = Y
 Sym operation chaining = Y
+OOP LB  In LB  Out     = Y
 
 ;
 ; Supported crypto algorithms of the 'kasumi' crypto driver.
diff --git a/dpdk/doc/guides/cryptodevs/features/octeontx.ini b/dpdk/doc/guides/cryptodevs/features/octeontx.ini
index 1c036c5baf..629e6bfc41 100644
--- a/dpdk/doc/guides/cryptodevs/features/octeontx.ini
+++ b/dpdk/doc/guides/cryptodevs/features/octeontx.ini
@@ -11,6 +11,7 @@ HW Accelerated         = Y
 In Place SGL           = Y
 OOP SGL In LB  Out     = Y
 OOP SGL In SGL Out     = Y
+OOP LB  In LB  Out     = Y
 RSA PRIV OP KEY QT     = Y
 
 ;
diff --git a/dpdk/doc/guides/cryptodevs/features/octeontx2.ini b/dpdk/doc/guides/cryptodevs/features/octeontx2.ini
index 7d07053cb1..6a205870af 100644
--- a/dpdk/doc/guides/cryptodevs/features/octeontx2.ini
+++ b/dpdk/doc/guides/cryptodevs/features/octeontx2.ini
@@ -11,6 +11,7 @@ HW Accelerated         = Y
 In Place SGL           = Y
 OOP SGL In LB  Out     = Y
 OOP SGL In SGL Out     = Y
+OOP LB  In LB  Out     = Y
 RSA PRIV OP KEY QT     = Y
 
 ;
diff --git a/dpdk/doc/guides/cryptodevs/features/qat.ini b/dpdk/doc/guides/cryptodevs/features/qat.ini
index 6e350eb81f..a722419979 100644
--- a/dpdk/doc/guides/cryptodevs/features/qat.ini
+++ b/dpdk/doc/guides/cryptodevs/features/qat.ini
@@ -44,10 +44,15 @@ ZUC EEA3       = Y
 [Auth]
 NULL         = Y
 MD5 HMAC     = Y
+SHA1         = Y
 SHA1 HMAC    = Y
+SHA224       = Y
 SHA224 HMAC  = Y
+SHA256       = Y
 SHA256 HMAC  = Y
+SHA384       = Y
 SHA384 HMAC  = Y
+SHA512       = Y
 SHA512 HMAC  = Y
 AES GMAC     = Y
 SNOW3G UIA2  = Y
diff --git a/dpdk/doc/guides/cryptodevs/features/snow3g.ini b/dpdk/doc/guides/cryptodevs/features/snow3g.ini
index ec2daf6c64..c4a1a84484 100644
--- a/dpdk/doc/guides/cryptodevs/features/snow3g.ini
+++ b/dpdk/doc/guides/cryptodevs/features/snow3g.ini
@@ -6,6 +6,7 @@
 [Features]
 Symmetric crypto       = Y
 Sym operation chaining = Y
+OOP LB  In LB  Out     = Y
 
 ;
 ; Supported crypto algorithms of the 'snow3g' crypto driver.
diff --git a/dpdk/doc/guides/cryptodevs/features/zuc.ini b/dpdk/doc/guides/cryptodevs/features/zuc.ini
index 9b6a4287e8..29cc258aae 100644
--- a/dpdk/doc/guides/cryptodevs/features/zuc.ini
+++ b/dpdk/doc/guides/cryptodevs/features/zuc.ini
@@ -6,6 +6,7 @@
 [Features]
 Symmetric crypto       = Y
 Sym operation chaining = Y
+OOP LB  In LB  Out     = Y
 
 ;
 ; Supported crypto algorithms of the 'zuc' crypto driver.
diff --git a/dpdk/doc/guides/cryptodevs/qat.rst b/dpdk/doc/guides/cryptodevs/qat.rst
index 6197875fe3..c8bc514d61 100644
--- a/dpdk/doc/guides/cryptodevs/qat.rst
+++ b/dpdk/doc/guides/cryptodevs/qat.rst
@@ -52,10 +52,15 @@ Cipher algorithms:
 
 Hash algorithms:
 
+* ``RTE_CRYPTO_AUTH_SHA1``
 * ``RTE_CRYPTO_AUTH_SHA1_HMAC``
+* ``RTE_CRYPTO_AUTH_SHA224``
 * ``RTE_CRYPTO_AUTH_SHA224_HMAC``
+* ``RTE_CRYPTO_AUTH_SHA256``
 * ``RTE_CRYPTO_AUTH_SHA256_HMAC``
+* ``RTE_CRYPTO_AUTH_SHA384``
 * ``RTE_CRYPTO_AUTH_SHA384_HMAC``
+* ``RTE_CRYPTO_AUTH_SHA512``
 * ``RTE_CRYPTO_AUTH_SHA512_HMAC``
 * ``RTE_CRYPTO_AUTH_AES_XCBC_MAC``
 * ``RTE_CRYPTO_AUTH_SNOW3G_UIA2``
@@ -72,6 +77,29 @@ Supported AEAD algorithms:
 * ``RTE_CRYPTO_AEAD_AES_CCM``
 
 
+Supported Chains
+~~~~~~~~~~~~~~~~
+
+All the usual chains are supported and also some mixed chains:
+
+.. table:: Supported hash-cipher chains for wireless digest-encrypted cases
+
+   +------------------+-----------+-------------+----------+----------+
+   | Cipher algorithm | NULL AUTH | SNOW3G UIA2 | ZUC EIA3 | AES CMAC |
+   +==================+===========+=============+==========+==========+
+   | NULL CIPHER      | Y         | 2&3         | 2&3      | Y        |
+   +------------------+-----------+-------------+----------+----------+
+   | SNOW3G UEA2      | 2&3       | Y           | 2&3      | 2&3      |
+   +------------------+-----------+-------------+----------+----------+
+   | ZUC EEA3         | 2&3       | 2&3         | 2&3      | 2&3      |
+   +------------------+-----------+-------------+----------+----------+
+   | AES CTR          | Y         | 2&3         | 2&3      | Y        |
+   +------------------+-----------+-------------+----------+----------+
+
+* The combinations marked as "Y" are supported on all QAT hardware versions.
+* The combinations marked as "2&3" are supported on GEN2/GEN3 QAT hardware only.
+
+
 Limitations
 ~~~~~~~~~~~
 
@@ -81,7 +109,10 @@ Limitations
 * No BSD support as BSD QAT kernel driver not available.
 * ZUC EEA3/EIA3 is not supported by dh895xcc devices
 * Maximum additional authenticated data (AAD) for GCM is 240 bytes long and must be passed to the device in a buffer rounded up to the nearest block-size multiple (x16) and padded with zeros.
-* Queue pairs are not thread-safe (that is, within a single queue pair, RX and TX from different lcores is not supported).
+* Queue-pairs are thread-safe on Intel CPUs but Queues are not (that is, within a single
+  queue-pair all enqueues to the TX queue must be done from one thread and all dequeues
+  from the RX queue must be done from one thread, but enqueues and dequeues may be done
+  in different threads.)
 * A GCM limitation exists, but only in the case where there are multiple
   generations of QAT devices on a single platform.
   To optimise performance, the GCM crypto session should be initialised for the
@@ -93,6 +124,8 @@ Limitations
   enqueued to the device and will be marked as failed. The simplest way to
   mitigate this is to use the bdf whitelist to avoid mixing devices of different
   generations in the same process if planning to use for GCM.
+* The mixed algo feature on GEN2 is not supported by all kernel drivers. Check
+  the notes under the Available Kernel Drivers table below for specific details.
 
 Extra notes on KASUMI F9
 ~~~~~~~~~~~~~~~~~~~~~~~~
@@ -133,7 +166,10 @@ Limitations
 ~~~~~~~~~~~
 
 * Big integers longer than 4096 bits are not supported.
-* Queue pairs are not thread-safe (that is, within a single queue pair, RX and TX from different lcores is not supported).
+* Queue-pairs are thread-safe on Intel CPUs but Queues are not (that is, within a single
+  queue-pair all enqueues to the TX queue must be done from one thread and all dequeues
+  from the RX queue must be done from one thread, but enqueues and dequeues may be done
+  in different threads.)
 * RSA-2560, RSA-3584 are not supported
 
 .. _building_qat:
@@ -237,6 +273,27 @@ allocated while for GEN1 devices, 12 buffers are allocated, plus 1472 bytes over
 	larger than the input size).
 
 
+Running QAT PMD with minimum threshold for burst size
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If only a small number or packets can be enqueued. Each enqueue causes an expensive MMIO write.
+These MMIO write occurrences can be optimised by setting any of the following parameters
+- qat_sym_enq_threshold
+- qat_asym_enq_threshold
+- qat_comp_enq_threshold
+When any of these parameters is set rte_cryptodev_enqueue_burst function will
+return 0 (thereby avoiding an MMIO) if the device is congested and number of packets
+possible to enqueue is smaller.
+
+To use this feature the user must set the parameter on process start as a device additional parameter::
+
+      example: -w 03:01.1,qat_sym_enq_threshold=32,qat_comp_enq_threshold=16
+
+All parameters can be used with the same device regardless of order. Parameters are separated
+by comma. When the same parameter is used more than once first occurrence of the parameter
+is used.
+Maximum threshold that can be set is 32.
+
 Device and driver naming
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -326,6 +383,8 @@ to see the full table)
    | Yes | No  | No  | 3   | C4xxx    | p             | qat_c4xxx     | c4xxx      | 18a0   | 1    | 18a1   | 128    |
    +-----+-----+-----+-----+----------+---------------+---------------+------------+--------+------+--------+--------+
 
+* Note: Symmetric mixed crypto algorithms feature on Gen 2 works only with 01.org driver version 4.9.0+
+
 The first 3 columns indicate the service:
 
 * S = Symmetric crypto service (via cryptodev API)
diff --git a/dpdk/doc/guides/eventdevs/index.rst b/dpdk/doc/guides/eventdevs/index.rst
index 570905b813..bb66a5eacc 100644
--- a/dpdk/doc/guides/eventdevs/index.rst
+++ b/dpdk/doc/guides/eventdevs/index.rst
@@ -5,7 +5,7 @@ Event Device Drivers
 ====================
 
 The following are a list of event device PMDs, which can be used from an
-application trough the eventdev API.
+application through the eventdev API.
 
 .. toctree::
     :maxdepth: 2
diff --git a/dpdk/doc/guides/eventdevs/octeontx2.rst b/dpdk/doc/guides/eventdevs/octeontx2.rst
index fad84cf42d..d4b2515ce5 100644
--- a/dpdk/doc/guides/eventdevs/octeontx2.rst
+++ b/dpdk/doc/guides/eventdevs/octeontx2.rst
@@ -66,7 +66,7 @@ Runtime Config Options
   upper limit for in-flight events.
   For example::
 
-    --dev "0002:0e:00.0,xae_cnt=16384"
+    -w 0002:0e:00.0,xae_cnt=16384
 
 - ``Force legacy mode``
 
@@ -74,7 +74,7 @@ Runtime Config Options
   single workslot mode in SSO and disable the default dual workslot mode.
   For example::
 
-    --dev "0002:0e:00.0,single_ws=1"
+    -w 0002:0e:00.0,single_ws=1
 
 - ``Event Group QoS support``
 
@@ -89,7 +89,7 @@ Runtime Config Options
   default.
   For example::
 
-    --dev "0002:0e:00.0,qos=[1-50-50-50]"
+    -w 0002:0e:00.0,qos=[1-50-50-50]
 
 - ``Selftest``
 
@@ -98,7 +98,7 @@ Runtime Config Options
   The tests are run once the vdev creation is successfully complete.
   For example::
 
-    --dev "0002:0e:00.0,selftest=1"
+    -w 0002:0e:00.0,selftest=1
 
 - ``TIM disable NPA``
 
@@ -107,7 +107,7 @@ Runtime Config Options
   parameter disables NPA and uses software mempool to manage chunks
   For example::
 
-    --dev "0002:0e:00.0,tim_disable_npa=1"
+    -w 0002:0e:00.0,tim_disable_npa=1
 
 - ``TIM modify chunk slots``
 
@@ -118,7 +118,7 @@ Runtime Config Options
   to SSO. The default value is 255 and the max value is 4095.
   For example::
 
-    --dev "0002:0e:00.0,tim_chnk_slots=1023"
+    -w 0002:0e:00.0,tim_chnk_slots=1023
 
 - ``TIM enable arm/cancel statistics``
 
@@ -126,7 +126,7 @@ Runtime Config Options
   event timer adapter.
   For example::
 
-    --dev "0002:0e:00.0,tim_stats_ena=1"
+    -w 0002:0e:00.0,tim_stats_ena=1
 
 - ``TIM limit max rings reserved``
 
@@ -136,7 +136,7 @@ Runtime Config Options
   rings.
   For example::
 
-    --dev "0002:0e:00.0,tim_rings_lmt=5"
+    -w 0002:0e:00.0,tim_rings_lmt=5
 
 - ``TIM ring control internal parameters``
 
@@ -146,7 +146,7 @@ Runtime Config Options
   default values.
   For Example::
 
-    --dev "0002:0e:00.0,tim_ring_ctl=[2-1023-1-0]"
+    -w 0002:0e:00.0,tim_ring_ctl=[2-1023-1-0]
 
 Debugging Options
 ~~~~~~~~~~~~~~~~~
diff --git a/dpdk/doc/guides/freebsd_gsg/install_from_ports.rst b/dpdk/doc/guides/freebsd_gsg/install_from_ports.rst
index 29f16cc6c5..dce028bc62 100644
--- a/dpdk/doc/guides/freebsd_gsg/install_from_ports.rst
+++ b/dpdk/doc/guides/freebsd_gsg/install_from_ports.rst
@@ -62,7 +62,7 @@ environmental variables should be set as below:
 .. note::
 
    To install a copy of the DPDK compiled using gcc, please download the
-   official DPDK package from http://core.dpdk.org/download/ and install manually using
+   official DPDK package from https://core.dpdk.org/download/ and install manually using
    the instructions given in the next chapter, :ref:`building_from_source`
 
 An example application can therefore be copied to a user's home directory and
diff --git a/dpdk/doc/guides/linux_gsg/build_dpdk.rst b/dpdk/doc/guides/linux_gsg/build_dpdk.rst
index 4aeb4697d9..c536e354ef 100644
--- a/dpdk/doc/guides/linux_gsg/build_dpdk.rst
+++ b/dpdk/doc/guides/linux_gsg/build_dpdk.rst
@@ -167,60 +167,32 @@ Installation of DPDK Target Environment using Make
    is therefore recommended that DPDK installation is done using meson and
    ninja as described above.
 
-The format of a DPDK target is::
+Get a native target environment automatically::
 
-    ARCH-MACHINE-EXECENV-TOOLCHAIN
-
-where:
-
-* ``ARCH`` can be:  ``i686``, ``x86_64``, ``ppc_64``, ``arm64``
-
-* ``MACHINE`` can be:  ``native``, ``power8``, ``armv8a``
-
-* ``EXECENV`` can be:  ``linux``,  ``freebsd``
-
-* ``TOOLCHAIN`` can be:  ``gcc``,  ``icc``
-
-The targets to be installed depend on the 32-bit and/or 64-bit packages and compilers installed on the host.
-Available targets can be found in the DPDK/config directory.
-The defconfig\_ prefix should not be used.
+   make defconfig O=mybuild
 
 .. note::
 
-    Configuration files are provided with the ``RTE_MACHINE`` optimization level set.
     Within the configuration files, the ``RTE_MACHINE`` configuration value is set to native,
     which means that the compiled software is tuned for the platform on which it is built.
-    For more information on this setting, and its possible values, see the *DPDK Programmers Guide*.
 
-When using the Intel® C++ Compiler (icc), one of the following commands should be invoked for 64-bit or 32-bit use respectively.
-Notice that the shell scripts update the ``$PATH`` variable and therefore should not be performed in the same session.
-Also, verify the compiler's installation directory since the path may be different:
+Or get a specific target environment::
 
-.. code-block:: console
+   make config T=x86_64-native-linux-gcc O=mybuild
 
-    source /opt/intel/bin/iccvars.sh intel64
-    source /opt/intel/bin/iccvars.sh ia32
+The format of a DPDK target is "ARCH-MACHINE-EXECENV-TOOLCHAIN".
+Available targets can be found with::
 
-To install and make targets, use the ``make install T=<target>`` command in the top-level DPDK directory.
+   make help
 
-For example, to compile a 64-bit target using icc, run:
+Customize the target configuration in the generated ``.config`` file.
+Example for enabling the pcap PMD::
 
-.. code-block:: console
+   sed -ri 's,(PMD_PCAP=).*,\1y,' mybuild/.config
 
-    make install T=x86_64-native-linux-icc
+Compile the target::
 
-To compile a 32-bit build using gcc, the make command should be:
-
-.. code-block:: console
-
-    make install T=i686-native-linux-gcc
-
-To prepare a target without building it, for example, if the configuration changes need to be made before compilation,
-use the ``make config T=<target>`` command:
-
-.. code-block:: console
-
-    make config T=x86_64-native-linux-gcc
+   make -j4 O=mybuild
 
 .. warning::
 
@@ -229,15 +201,13 @@ use the ``make config T=<target>`` command:
     If the DPDK is not being built on the target machine,
     the ``RTE_KERNELDIR`` environment variable should be used to point the compilation at a copy of the kernel version to be used on the target machine.
 
-Once the target environment is created, the user may move to the target environment directory and continue to make code changes and re-compile.
-The user may also make modifications to the compile-time DPDK configuration by editing the .config file in the build directory.
-(This is a build-local copy of the defconfig file from the top- level config directory).
+Install the target in a separate directory::
 
-.. code-block:: console
+   make install O=mybuild DESTDIR=myinstall prefix=
+
+The environment is ready to build a DPDK application::
 
-    cd x86_64-native-linux-gcc
-    vi .config
-    make
+   RTE_SDK=$(pwd)/myinstall/share/dpdk RTE_TARGET=x86_64-native-linux-gcc make -C myapp
 
 In addition, the make clean command can be used to remove any existing compiled files for a subsequent full, clean rebuild of the code.
 
@@ -245,5 +215,5 @@ Browsing the Installed DPDK Environment Target
 ----------------------------------------------
 
 Once a target is created it contains all libraries, including poll-mode drivers, and header files for the DPDK environment that are required to build customer applications.
-In addition, the test and testpmd applications are built under the build/app directory, which may be used for testing.
+In addition, the test applications are built under the app directory, which may be used for testing.
 A kmod  directory is also present that contains kernel modules which may be loaded if needed.
diff --git a/dpdk/doc/guides/linux_gsg/build_sample_apps.rst b/dpdk/doc/guides/linux_gsg/build_sample_apps.rst
index 2f606535c3..2c2f5faec5 100644
--- a/dpdk/doc/guides/linux_gsg/build_sample_apps.rst
+++ b/dpdk/doc/guides/linux_gsg/build_sample_apps.rst
@@ -4,7 +4,7 @@
 Compiling and Running Sample Applications
 =========================================
 
-The chapter describes how to compile and run applications in an DPDK environment.
+The chapter describes how to compile and run applications in a DPDK environment.
 It also provides a pointer to where sample applications are stored.
 
 .. note::
@@ -185,7 +185,7 @@ Each bit of the mask corresponds to the equivalent logical core number as report
 Since these logical core numbers, and their mapping to specific cores on specific NUMA sockets, can vary from platform to platform,
 it is recommended that the core layout for each platform be considered when choosing the coremask/corelist to use in each case.
 
-On initialization of the EAL layer by an DPDK application, the logical cores to be used and their socket location are displayed.
+On initialization of the EAL layer by a DPDK application, the logical cores to be used and their socket location are displayed.
 This information can also be determined for all cores on the system by examining the ``/proc/cpuinfo`` file, for example, by running cat ``/proc/cpuinfo``.
 The physical id attribute listed for each processor indicates the CPU socket to which it belongs.
 This can be useful when using other processors to understand the mapping of the logical cores to the sockets.
diff --git a/dpdk/doc/guides/linux_gsg/eal_args.include.rst b/dpdk/doc/guides/linux_gsg/eal_args.include.rst
index ed8b0e35b0..7b2f6b1d43 100644
--- a/dpdk/doc/guides/linux_gsg/eal_args.include.rst
+++ b/dpdk/doc/guides/linux_gsg/eal_args.include.rst
@@ -132,7 +132,7 @@ Debugging options
 
     Specify log level for a specific component. For example::
 
-        --log-level eal:8
+        --log-level lib.eal:debug
 
     Can be specified multiple times.
 
diff --git a/dpdk/doc/guides/linux_gsg/enable_func.rst b/dpdk/doc/guides/linux_gsg/enable_func.rst
index b2bda80bb7..459a952ce3 100644
--- a/dpdk/doc/guides/linux_gsg/enable_func.rst
+++ b/dpdk/doc/guides/linux_gsg/enable_func.rst
@@ -58,22 +58,51 @@ The application can then determine what action to take, if any, if the HPET is n
     if any, and on what is available on the system at runtime.
 
 Running DPDK Applications Without Root Privileges
---------------------------------------------------------
+-------------------------------------------------
 
-.. note::
+In order to run DPDK as non-root, the following Linux filesystem objects'
+permissions should be adjusted to ensure that the Linux account being used to
+run the DPDK application has access to them:
+
+*   All directories which serve as hugepage mount points, for example, ``/dev/hugepages``
+
+*   If the HPET is to be used,  ``/dev/hpet``
+
+When running as non-root user, there may be some additional resource limits
+that are imposed by the system. Specifically, the following resource limits may
+need to be adjusted in order to ensure normal DPDK operation:
+
+* RLIMIT_LOCKS (number of file locks that can be held by a process)
+
+* RLIMIT_NOFILE (number of open file descriptors that can be held open by a process)
+
+* RLIMIT_MEMLOCK (amount of pinned pages the process is allowed to have)
+
+The above limits can usually be adjusted by editing
+``/etc/security/limits.conf`` file, and rebooting.
 
-    The instructions below will allow running DPDK as non-root with older
-    Linux kernel versions. However, since version 4.0, the kernel does not allow
-    unprivileged processes to read the physical address information from
-    the pagemaps file, making it impossible for those processes to use HW
-    devices which require physical addresses
+Additionally, depending on which kernel driver is in use, the relevant
+resources also should be accessible by the user running the DPDK application.
 
-Although applications using the DPDK use network ports and other hardware resources directly,
-with a number of small permission adjustments it is possible to run these applications as a user other than "root".
-To do so, the ownership, or permissions, on the following Linux file system objects should be adjusted to ensure that
-the Linux user account being used to run the DPDK application has access to them:
+For ``vfio-pci`` kernel driver, the following Linux file system objects'
+permissions should be adjusted:
 
-*   All directories which serve as hugepage mount points, for example,   ``/mnt/huge``
+* The VFIO device file, ``/dev/vfio/vfio``
+
+* The directories under ``/dev/vfio`` that correspond to IOMMU group numbers of
+  devices intended to be used by DPDK, for example, ``/dev/vfio/50``
+
+.. note::
+
+    The instructions below will allow running DPDK with ``igb_uio`` or
+    ``uio_pci_generic`` drivers as non-root with older Linux kernel versions.
+    However, since version 4.0, the kernel does not allow unprivileged processes
+    to read the physical address information from the pagemaps file, making it
+    impossible for those processes to be used by non-privileged users. In such
+    cases, using the VFIO driver is recommended.
+
+For ``igb_uio`` or ``uio_pci_generic`` kernel drivers, the following Linux file
+system objects' permissions should be adjusted:
 
 *   The userspace-io device files in  ``/dev``, for example,  ``/dev/uio0``, ``/dev/uio1``, and so on
 
@@ -82,11 +111,6 @@ the Linux user account being used to run the DPDK application has access to them
        /sys/class/uio/uio0/device/config
        /sys/class/uio/uio0/device/resource*
 
-*   If the HPET is to be used,  ``/dev/hpet``
-
-.. note::
-
-    On some Linux installations, ``/dev/hugepages``  is also a hugepage mount point created by default.
 
 Power Management and Power Saving Functionality
 -----------------------------------------------
@@ -112,7 +136,7 @@ In addition, C3 and C6 should be enabled as well for power management. The path
 Using Linux Core Isolation to Reduce Context Switches
 -----------------------------------------------------
 
-While the threads used by an DPDK application are pinned to logical cores on the system,
+While the threads used by a DPDK application are pinned to logical cores on the system,
 it is possible for the Linux scheduler to run other tasks on those cores also.
 To help prevent additional workloads from running on those cores,
 it is possible to use the ``isolcpus`` Linux kernel parameter to isolate them from the general Linux scheduler.
diff --git a/dpdk/doc/guides/linux_gsg/linux_drivers.rst b/dpdk/doc/guides/linux_gsg/linux_drivers.rst
index 238f3e9002..96817e78cd 100644
--- a/dpdk/doc/guides/linux_gsg/linux_drivers.rst
+++ b/dpdk/doc/guides/linux_gsg/linux_drivers.rst
@@ -52,8 +52,8 @@ be loaded as shown below:
 
    If the devices used for DPDK are bound to the ``uio_pci_generic`` kernel module,
    please make sure that the IOMMU is disabled or passthrough. One can add
-   ``intel_iommu=off`` or ``amd_iommu=off`` or ``intel_iommu=on iommu=pt``in GRUB
-   command line on x86_64 systems, or add ``iommu.passthrough=1`` on arm64 system.
+   ``intel_iommu=off`` or ``amd_iommu=off`` or ``intel_iommu=on iommu=pt`` in GRUB
+   command line on x86_64 systems, or add ``iommu.passthrough=1`` on aarch64 system.
 
 Since DPDK release 1.7 onward provides VFIO support, use of UIO is optional
 for platforms that support using VFIO.
@@ -120,7 +120,7 @@ Binding and Unbinding Network Ports to/from the Kernel Modules
     PMDs Which use the bifurcated driver should not be unbind from their kernel drivers. this section is for PMDs which use the UIO or VFIO drivers.
 
 As of release 1.4, DPDK applications no longer automatically unbind all supported network ports from the kernel driver in use.
-Instead, in case the PMD being used use the UIO or VFIO drivers, all ports that are to be used by an DPDK application must be bound to the
+Instead, in case the PMD being used use the UIO or VFIO drivers, all ports that are to be used by a DPDK application must be bound to the
 ``uio_pci_generic``, ``igb_uio`` or ``vfio-pci`` module before the application is run.
 For such PMDs, any network ports under Linux* control will be ignored and cannot be used by the application.
 
diff --git a/dpdk/doc/guides/linux_gsg/nic_perf_intel_platform.rst b/dpdk/doc/guides/linux_gsg/nic_perf_intel_platform.rst
index c554c2159c..b70a151bcc 100644
--- a/dpdk/doc/guides/linux_gsg/nic_perf_intel_platform.rst
+++ b/dpdk/doc/guides/linux_gsg/nic_perf_intel_platform.rst
@@ -1,3 +1,6 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2015 Intel Corporation.
+
 How to get best performance with NICs on Intel platforms
 ========================================================
 
@@ -64,7 +67,7 @@ This aligns with the previous output which showed that each channel has one memo
 Network Interface Card Requirements
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Use a `DPDK supported <http://core.dpdk.org/supported/>`_ high end NIC such as the Intel XL710 40GbE.
+Use a `DPDK supported <https://core.dpdk.org/supported/>`_ high end NIC such as the Intel XL710 40GbE.
 
 Make sure each NIC has been flashed the latest version of NVM/firmware.
 
diff --git a/dpdk/doc/guides/linux_gsg/sys_reqs.rst b/dpdk/doc/guides/linux_gsg/sys_reqs.rst
index 7c47ec04ce..0af0b22813 100644
--- a/dpdk/doc/guides/linux_gsg/sys_reqs.rst
+++ b/dpdk/doc/guides/linux_gsg/sys_reqs.rst
@@ -107,7 +107,7 @@ e.g. :doc:`../nics/index`
 Running DPDK Applications
 -------------------------
 
-To run an DPDK application, some customization may be required on the target machine.
+To run a DPDK application, some customization may be required on the target machine.
 
 System Software
 ~~~~~~~~~~~~~~~
@@ -157,8 +157,36 @@ Without hugepages, high TLB miss rates would occur with the standard 4k page siz
 Reserving Hugepages for DPDK Use
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-The allocation of hugepages should be done at boot time or as soon as possible after system boot
-to prevent memory from being fragmented in physical memory.
+The reservation of hugepages can be performed at run time.
+This is done by echoing the number of hugepages required
+to a ``nr_hugepages`` file in the ``/sys/kernel/`` directory
+corresponding to a specific page size (in Kilobytes).
+For a single-node system, the command to use is as follows
+(assuming that 1024 of 2MB pages are required)::
+
+    echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
+
+On a NUMA machine, the above command will usually divide the number of hugepages
+equally across all NUMA nodes (assuming there is enough memory on all NUMA nodes).
+However, pages can also be reserved explicitly on individual NUMA nodes
+using a ``nr_hugepages`` file in the ``/sys/devices/`` directory::
+
+    echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
+    echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
+
+.. note::
+
+    Some kernel versions may not allow reserving 1 GB hugepages at run time,
+    so reserving them at boot time may be the only option.
+    Please see below for instructions.
+
+**Alternative:**
+
+In the general case, reserving hugepages at run time is perfectly fine,
+but in use cases where having lots of physically contiguous memory is required,
+it is preferable to reserve hugepages at boot time,
+as that will help in preventing physical memory from becoming heavily fragmented.
+
 To reserve hugepages at boot time, a parameter is passed to the Linux kernel on the kernel command line.
 
 For 2 MB pages, just pass the hugepages option to the kernel. For example, to reserve 1024 pages of 2 MB, use::
@@ -187,35 +215,29 @@ the number of hugepages reserved at boot time is generally divided equally betwe
 
 See the Documentation/admin-guide/kernel-parameters.txt file in your Linux source tree for further details of these and other kernel options.
 
-**Alternative:**
-
-For 2 MB pages, there is also the option of allocating hugepages after the system has booted.
-This is done by echoing the number of hugepages required to a nr_hugepages file in the ``/sys/devices/`` directory.
-For a single-node system, the command to use is as follows (assuming that 1024 pages are required)::
-
-    echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
-
-On a NUMA machine, pages should be allocated explicitly on separate nodes::
-
-    echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
-    echo 1024 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
+Using Hugepages with the DPDK
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-.. note::
+If secondary process support is not required, DPDK is able to use hugepages
+without any configuration by using "in-memory" mode.
+Please see :doc:`linux_eal_parameters` for more details.
 
-    For 1G pages, it is not possible to reserve the hugepage memory after the system has booted.
+If secondary process support is required,
+mount points for hugepages need to be created.
+On modern Linux distributions, a default mount point for hugepages
+is provided by the system and is located at ``/dev/hugepages``.
+This mount point will use the default hugepage size
+set by the kernel parameters as described above.
 
-Using Hugepages with the DPDK
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+However, in order to use hugepage sizes other than the default, it is necessary
+to manually create mount points for those hugepage sizes (e.g. 1GB pages).
 
-Once the hugepage memory is reserved, to make the memory available for DPDK use, perform the following steps::
+To make the hugepages of size 1GB available for DPDK use,
+following steps must be performed::
 
     mkdir /mnt/huge
-    mount -t hugetlbfs nodev /mnt/huge
+    mount -t hugetlbfs pagesize=1GB /mnt/huge
 
 The mount point can be made permanent across reboots, by adding the following line to the ``/etc/fstab`` file::
 
-    nodev /mnt/huge hugetlbfs defaults 0 0
-
-For 1GB pages, the page size must be specified as a mount option::
-
-    nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
+    nodev /mnt/huge hugetlbfs pagesize=1GB 0 0
diff --git a/dpdk/doc/guides/meson.build b/dpdk/doc/guides/meson.build
index 7931ef3bb5..732e7ad3a9 100644
--- a/dpdk/doc/guides/meson.build
+++ b/dpdk/doc/guides/meson.build
@@ -3,26 +3,22 @@
 
 sphinx = find_program('sphinx-build', required: get_option('enable_docs'))
 
-if sphinx.found()
-	htmldir = join_paths('share', 'doc', 'dpdk')
-	html_guides_build = custom_target('html_guides_build',
-		input: meson.current_source_dir(),
-		output: 'guides',
-		command: [sphinx, '-b', 'html',
-			'-d', meson.current_build_dir() + '/.doctrees',
-			'@INPUT@', meson.current_build_dir() + '/guides'],
-		build_by_default: get_option('enable_docs'),
-		install: get_option('enable_docs'),
-		install_dir: htmldir)
+if not sphinx.found()
+	subdir_done()
+endif
 
-	doc_targets += html_guides_build
-	doc_target_names += 'HTML_Guides'
+htmldir = join_paths(get_option('datadir'), 'doc', 'dpdk')
+html_guides = custom_target('html_guides',
+	input: files('index.rst'),
+	output: 'html',
+	command: [sphinx_wrapper, sphinx, meson.current_source_dir(), meson.current_build_dir()],
+	depfile: '.html.d',
+	build_by_default: get_option('enable_docs'),
+	install: get_option('enable_docs'),
+	install_dir: htmldir)
 
-	# sphinx leaves a .buildinfo in the target directory, which we don't
-	# want to install. Note that sh -c has to be used, otherwise the
-	# env var does not get expanded if calling rm/install directly.
-	meson.add_install_script('sh', '-c',
-		'rm -f $MESON_INSTALL_DESTDIR_PREFIX/share/doc/dpdk/guides/.buildinfo')
-	meson.add_install_script('sh', '-c',
-		'install -D -m0644 $MESON_SOURCE_ROOT/doc/guides/custom.css $MESON_INSTALL_DESTDIR_PREFIX/share/doc/dpdk/guides/_static/css/custom.css')
-endif
+install_data(files('custom.css'),
+			install_dir: join_paths(htmldir,'_static', 'css'))
+
+doc_targets += html_guides
+doc_target_names += 'HTML_Guides'
diff --git a/dpdk/doc/guides/nics/dpaa2.rst b/dpdk/doc/guides/nics/dpaa2.rst
index fdfa6fdd5a..e54a5ff4d2 100644
--- a/dpdk/doc/guides/nics/dpaa2.rst
+++ b/dpdk/doc/guides/nics/dpaa2.rst
@@ -1,5 +1,5 @@
 ..  SPDX-License-Identifier: BSD-3-Clause
-    Copyright 2016 NXP
+    Copyright 2016,2020 NXP
 
 
 DPAA2 Poll Mode Driver
@@ -300,7 +300,7 @@ The diagram below shows the dpaa2 drivers involved in a networking
 scenario and the objects bound to each driver.  A brief description
 of each driver follows.
 
-.. code-block: console
+.. code-block:: console
 
 
                                        +------------+
diff --git a/dpdk/doc/guides/nics/enic.rst b/dpdk/doc/guides/nics/enic.rst
index 65e536d422..24d2b5713a 100644
--- a/dpdk/doc/guides/nics/enic.rst
+++ b/dpdk/doc/guides/nics/enic.rst
@@ -14,7 +14,7 @@ How to obtain ENIC PMD integrated DPDK
 --------------------------------------
 
 ENIC PMD support is integrated into the DPDK suite. dpdk-<version>.tar.gz
-should be downloaded from http://core.dpdk.org/download/
+should be downloaded from https://core.dpdk.org/download/
 
 
 Configuration information
diff --git a/dpdk/doc/guides/nics/fail_safe.rst b/dpdk/doc/guides/nics/fail_safe.rst
index 6c02d7ef6d..60bbf40f7f 100644
--- a/dpdk/doc/guides/nics/fail_safe.rst
+++ b/dpdk/doc/guides/nics/fail_safe.rst
@@ -49,7 +49,7 @@ The Fail-safe PMD can be used like most other DPDK virtual devices, by passing a
 ``--vdev`` parameter to the EAL when starting the application. The device name
 must start with the *net_failsafe* prefix, followed by numbers or letters. This
 name must be unique for each device. Each fail-safe instance must have at least one
-sub-device, up to ``RTE_MAX_ETHPORTS-1``.
+sub-device, and at most two.
 
 A sub-device can be any legal DPDK device, including possibly another fail-safe
 instance.
diff --git a/dpdk/doc/guides/nics/features/hns3.ini b/dpdk/doc/guides/nics/features/hns3.ini
index 6df789ed10..cd5c08a9d7 100644
--- a/dpdk/doc/guides/nics/features/hns3.ini
+++ b/dpdk/doc/guides/nics/features/hns3.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Link status          = Y
+Rx interrupt         = Y
 MTU update           = Y
 Jumbo frame          = Y
 Promiscuous mode     = Y
diff --git a/dpdk/doc/guides/nics/features/hns3_vf.ini b/dpdk/doc/guides/nics/features/hns3_vf.ini
index 41497c4c2d..fd00ac3e22 100644
--- a/dpdk/doc/guides/nics/features/hns3_vf.ini
+++ b/dpdk/doc/guides/nics/features/hns3_vf.ini
@@ -5,6 +5,7 @@
 ;
 [Features]
 Link status          = Y
+Rx interrupt         = Y
 MTU update           = Y
 Jumbo frame          = Y
 Unicast MAC filter   = Y
diff --git a/dpdk/doc/guides/nics/features/i40e.ini b/dpdk/doc/guides/nics/features/i40e.ini
index e5ae6ded08..c2717cdc47 100644
--- a/dpdk/doc/guides/nics/features/i40e.ini
+++ b/dpdk/doc/guides/nics/features/i40e.ini
@@ -18,7 +18,6 @@ TSO                  = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
-Multicast MAC filter = Y
 RSS hash             = Y
 RSS key update       = Y
 RSS reta update      = Y
diff --git a/dpdk/doc/guides/nics/features/ice.ini b/dpdk/doc/guides/nics/features/ice.ini
index 65923f0bc0..949d09f423 100644
--- a/dpdk/doc/guides/nics/features/ice.ini
+++ b/dpdk/doc/guides/nics/features/ice.ini
@@ -18,7 +18,6 @@ TSO                  = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
-Multicast MAC filter = Y
 RSS hash             = Y
 RSS key update       = Y
 RSS reta update      = Y
diff --git a/dpdk/doc/guides/nics/features/igb.ini b/dpdk/doc/guides/nics/features/igb.ini
index 0351f8495d..167c0cabe8 100644
--- a/dpdk/doc/guides/nics/features/igb.ini
+++ b/dpdk/doc/guides/nics/features/igb.ini
@@ -15,6 +15,7 @@ TSO                  = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
+Multicast MAC filter = Y
 RSS hash             = Y
 RSS key update       = Y
 RSS reta update      = Y
diff --git a/dpdk/doc/guides/nics/features/ixgbe.ini b/dpdk/doc/guides/nics/features/ixgbe.ini
index c412d7af1a..1c7a2a5240 100644
--- a/dpdk/doc/guides/nics/features/ixgbe.ini
+++ b/dpdk/doc/guides/nics/features/ixgbe.ini
@@ -17,6 +17,7 @@ TSO                  = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
 Unicast MAC filter   = Y
+Multicast MAC filter = Y
 RSS hash             = Y
 RSS key update       = Y
 RSS reta update      = Y
diff --git a/dpdk/doc/guides/nics/features/mlx5.ini b/dpdk/doc/guides/nics/features/mlx5.ini
index b0a2f8e5f7..30a4d80ead 100644
--- a/dpdk/doc/guides/nics/features/mlx5.ini
+++ b/dpdk/doc/guides/nics/features/mlx5.ini
@@ -41,6 +41,7 @@ Basic stats          = Y
 Extended stats       = Y
 Stats per queue      = Y
 FW version           = Y
+Module EEPROM dump   = Y
 Multiprocess aware   = Y
 Other kdrv           = Y
 ARMv8                = Y
diff --git a/dpdk/doc/guides/nics/hns3.rst b/dpdk/doc/guides/nics/hns3.rst
index 505488b6ca..567c65d536 100644
--- a/dpdk/doc/guides/nics/hns3.rst
+++ b/dpdk/doc/guides/nics/hns3.rst
@@ -22,13 +22,14 @@ Features of the HNS3 PMD are:
 - Port hardware statistics
 - Jumbo frames
 - Link state information
+- Interrupt mode for RX
 - VLAN stripping
 - NUMA support
 
 Prerequisites
 -------------
 - Get the information about Kunpeng920 chip using
-  `<http://www.hisilicon.com/en/Products/ProductList/Kunpeng>`_.
+  `<https://www.hisilicon.com/en/products/Kunpeng>`_.
 
 - Follow the DPDK :ref:`Getting Started Guide for Linux <linux_gsg>` to setup the basic DPDK environment.
 
diff --git a/dpdk/doc/guides/nics/i40e.rst b/dpdk/doc/guides/nics/i40e.rst
index 38acf5906d..cfeb156935 100644
--- a/dpdk/doc/guides/nics/i40e.rst
+++ b/dpdk/doc/guides/nics/i40e.rst
@@ -69,7 +69,9 @@ to chapter Tested Platforms/Tested NICs in release notes.
    +--------------+-----------------------+------------------+
    | DPDK version | Kernel driver version | Firmware version |
    +==============+=======================+==================+
-   |    19.08     |         2.9.21        |       7.00       |
+   |    19.11     |         2.9.21        |       7.00       |
+   +--------------+-----------------------+------------------+
+   |    19.08     |         2.8.43        |       7.00       |
    +--------------+-----------------------+------------------+
    |    19.05     |         2.7.29        |       6.80       |
    +--------------+-----------------------+------------------+
@@ -580,6 +582,15 @@ When a packet is over maximum frame size, the packet is dropped.
 However, the Rx statistics, when calling `rte_eth_stats_get` incorrectly
 shows it as received.
 
+RX/TX statistics may be incorrect when register overflowed
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The rx_bytes/tx_bytes statistics register is 48 bit length.
+Although this limitation is enlarged to 64 bit length on the software side,
+but there is no way to detect if the overflow occurred more than once.
+So rx_bytes/tx_bytes statistics data is correct when statistics are
+updated at least once between two overflows.
+
 VF & TC max bandwidth setting
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -665,6 +676,15 @@ Use 16 Bytes RX Descriptor Size
 As i40e PMD supports both 16 and 32 bytes RX descriptor sizes, and 16 bytes size can provide helps to high performance of small packets.
 Configuration of ``CONFIG_RTE_LIBRTE_I40E_16BYTE_RX_DESC`` in config files can be changed to use 16 bytes size RX descriptors.
 
+Input set requirement of each pctype for FDIR
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each PCTYPE can only have one specific FDIR input set at one time.
+For example, if creating 2 rte_flow rules with different input set for one PCTYPE,
+it will fail and return the info "Conflict with the first rule's input set",
+which means the current rule's input set conflicts with the first rule's.
+Remove the first rule if want to change the input set of the PCTYPE.
+
 Example of getting best performance with l3fwd example
 ------------------------------------------------------
 
diff --git a/dpdk/doc/guides/nics/ice.rst b/dpdk/doc/guides/nics/ice.rst
index 9b90b389ec..58eb023983 100644
--- a/dpdk/doc/guides/nics/ice.rst
+++ b/dpdk/doc/guides/nics/ice.rst
@@ -54,10 +54,6 @@ Please note that enabling debugging options may affect system performance.
 
   Toggle display of generic debugging messages.
 
-- ``CONFIG_RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC`` (default ``y``)
-
-  Toggle bulk allocation for RX.
-
 - ``CONFIG_RTE_LIBRTE_ICE_16BYTE_RX_DESC`` (default ``n``)
 
   Toggle to use a 16-byte RX descriptor, by default the RX descriptor is 32 byte.
diff --git a/dpdk/doc/guides/nics/ixgbe.rst b/dpdk/doc/guides/nics/ixgbe.rst
index 5c3a7e4f26..6ca2a33f09 100644
--- a/dpdk/doc/guides/nics/ixgbe.rst
+++ b/dpdk/doc/guides/nics/ixgbe.rst
@@ -253,6 +253,16 @@ Before binding ``vfio`` with legacy mode in X550 NICs, use ``modprobe vfio ``
 ``nointxmask=1`` to load ``vfio`` module if the intx is not shared with other
 devices.
 
+UDP with zero checksum is reported as error
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Intel 82599 10 Gigabit Ethernet Controller Specification Update (Revision 2.87)
+Errata: 44 Integrity Error Reported for IPv4/UDP Packets With Zero Checksum
+
+To support UDP zero checksum, the zero and bad UDP checksum packet is marked as
+PKT_RX_L4_CKSUM_UNKNOWN, so the application needs to recompute the checksum to
+validate it.
+
 Inline crypto processing support
 --------------------------------
 
diff --git a/dpdk/doc/guides/nics/mlx4.rst b/dpdk/doc/guides/nics/mlx4.rst
index d0e8a8b2ff..1f1e2f6c77 100644
--- a/dpdk/doc/guides/nics/mlx4.rst
+++ b/dpdk/doc/guides/nics/mlx4.rst
@@ -92,6 +92,10 @@ These options can be modified in the ``.config`` file.
   adds additional run-time checks and debugging messages at the cost of
   lower performance.
 
+This option is available in meson:
+
+- ``ibverbs_link`` can be ``static``, ``shared``, or ``dlopen``.
+
 Environment variables
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -294,11 +298,6 @@ Installing Mellanox OFED
 
 5. Continue with :ref:`section 2 of the Quick Start Guide <QSG_2>`.
 
-Supported NICs
---------------
-
-* Mellanox(R) ConnectX(R)-3 Pro 40G MCX354A-FCC_Ax (2*40G)
-
 .. _qsg:
 
 Quick Start Guide
diff --git a/dpdk/doc/guides/nics/mlx5.rst b/dpdk/doc/guides/nics/mlx5.rst
index 18573cf6a0..bbad7d0d5b 100644
--- a/dpdk/doc/guides/nics/mlx5.rst
+++ b/dpdk/doc/guides/nics/mlx5.rst
@@ -2,12 +2,14 @@
     Copyright 2015 6WIND S.A.
     Copyright 2015 Mellanox Technologies, Ltd
 
+.. include:: <isonum.txt>
+
 MLX5 poll mode driver
 =====================
 
 The MLX5 poll mode driver library (**librte_pmd_mlx5**) provides support
 for **Mellanox ConnectX-4**, **Mellanox ConnectX-4 Lx** , **Mellanox
-ConnectX-5**, **Mellanox ConnectX-6**, **Mellanox ConnectX-6DX** and
+ConnectX-5**, **Mellanox ConnectX-6**, **Mellanox ConnectX-6 Dx** and
 **Mellanox BlueField** families of 10/25/40/50/100/200 Gb/s adapters
 as well as their virtual functions (VF) in SR-IOV context.
 
@@ -107,22 +109,37 @@ Limitations
     process. If the external memory is registered by primary process but has
     different virtual address in secondary process, unexpected error may happen.
 
-- Flow pattern without any specific vlan will match for vlan packets as well:
+- When using Verbs flow engine (``dv_flow_en`` = 0), flow pattern without any
+  specific VLAN will match for VLAN packets as well:
 
   When VLAN spec is not specified in the pattern, the matching rule will be created with VLAN as a wild card.
   Meaning, the flow rule::
 
         flow create 0 ingress pattern eth / vlan vid is 3 / ipv4 / end ...
 
-  Will only match vlan packets with vid=3. and the flow rules::
+  Will only match vlan packets with vid=3. and the flow rule::
+
+        flow create 0 ingress pattern eth / ipv4 / end ...
+
+  Will match any ipv4 packet (VLAN included).
+
+- When using DV flow engine (``dv_flow_en`` = 1), flow pattern without VLAN item
+  will match untagged packets only.
+  The flow rule::
 
         flow create 0 ingress pattern eth / ipv4 / end ...
 
-  Or::
+  Will match untagged packets only.
+  The flow rule::
 
         flow create 0 ingress pattern eth / vlan / ipv4 / end ...
 
-  Will match any ipv4 packet (VLAN included).
+  Will match tagged packets only, with any VLAN ID value.
+  The flow rule::
+
+        flow create 0 ingress pattern eth / vlan vid is 3 / ipv4 / end ...
+
+  Will only match tagged packets with VLAN ID 3.
 
 - VLAN pop offload command:
 
@@ -270,6 +287,10 @@ These options can be modified in the ``.config`` file.
    64. Default armv8a configuration of make build and meson build set it to 128
    then brings performance degradation.
 
+This option is available in meson:
+
+- ``ibverbs_link`` can be ``static``, ``shared``, or ``dlopen``.
+
 Environment variables
 ~~~~~~~~~~~~~~~~~~~~~
 
@@ -315,9 +336,9 @@ Run-time configuration
 
   Supported on:
 
-  - x86_64 with ConnectX-4, ConnectX-4 LX, ConnectX-5, ConnectX-6, ConnectX-6 DX
+  - x86_64 with ConnectX-4, ConnectX-4 Lx, ConnectX-5, ConnectX-6, ConnectX-6 Dx
     and BlueField.
-  - POWER9 and ARMv8 with ConnectX-4 LX, ConnectX-5, ConnectX-6, ConnectX-6 DX
+  - POWER9 and ARMv8 with ConnectX-4 Lx, ConnectX-5, ConnectX-6, ConnectX-6 Dx
     and BlueField.
 
 - ``rxq_cqe_pad_en`` parameter [int]
@@ -348,17 +369,16 @@ Run-time configuration
 
   Supported on:
 
-  - x86_64 with ConnectX-4, ConnectX-4 LX, ConnectX-5, ConnectX-6, ConnectX-6 DX
+  - x86_64 with ConnectX-4, ConnectX-4 Lx, ConnectX-5, ConnectX-6, ConnectX-6 Dx
     and BlueField.
-  - POWER8 and ARMv8 with ConnectX-4 LX, ConnectX-5, ConnectX-6, ConnectX-6 DX
+  - POWER8 and ARMv8 with ConnectX-4 Lx, ConnectX-5, ConnectX-6, ConnectX-6 Dx
     and BlueField.
 
 - ``mprq_en`` parameter [int]
 
   A nonzero value enables configuring Multi-Packet Rx queues. Rx queue is
   configured as Multi-Packet RQ if the total number of Rx queues is
-  ``rxqs_min_mprq`` or more and Rx scatter isn't configured. Disabled by
-  default.
+  ``rxqs_min_mprq`` or more. Disabled by default.
 
   Multi-Packet Rx Queue (MPRQ a.k.a Striding RQ) can further save PCIe bandwidth
   by posting a single large buffer for multiple packets. Instead of posting a
@@ -383,6 +403,20 @@ Run-time configuration
 
   The size of Rx queue should be bigger than the number of strides.
 
+- ``mprq_log_stride_size`` parameter [int]
+
+  Log 2 of the size of a stride for Multi-Packet Rx queue. Configuring a smaller
+  stride size can save some memory and reduce probability of a depletion of all
+  available strides due to unreleased packets by an application. If configured
+  value is not in the range of device capability, the default value will be set
+  with a warning message. The default value is 11 which is 2048 bytes per a
+  stride, valid only if ``mprq_en`` is set. With ``mprq_log_stride_size`` set
+  it is possible for a packet to span across multiple strides. This mode allows
+  support of jumbo frames (9K) with MPRQ. The memcopy of some packets (or part
+  of a packet if Rx scatter is configured) may be required in case there is no
+  space left for a head room at the end of a stride which incurs some
+  performance penalty.
+
 - ``mprq_max_memcpy_len`` parameter [int]
 
   The maximum length of packet to memcpy in case of Multi-Packet Rx queue. Rx
@@ -453,14 +487,14 @@ Run-time configuration
   If ``txq_inline_min`` key is not present, the value may be queried by the
   driver from the NIC via DevX if this feature is available. If there is no DevX
   enabled/supported the value 18 (supposing L2 header including VLAN) is set
-  for ConnectX-4 and ConnectX-4LX, and 0 is set by default for ConnectX-5
+  for ConnectX-4 and ConnectX-4 Lx, and 0 is set by default for ConnectX-5
   and newer NICs. If packet is shorter the ``txq_inline_min`` value, the entire
   packet is inlined.
 
   For ConnectX-4 NIC, driver does not allow specifying value below 18
   (minimal L2 header, including VLAN), error will be raised.
 
-  For ConnectX-4LX NIC, it is allowed to specify values below 18, but
+  For ConnectX-4 Lx NIC, it is allowed to specify values below 18, but
   it is not recommended and may prevent NIC from sending packets over
   some configurations.
 
@@ -543,7 +577,7 @@ Run-time configuration
 - ``txq_mpw_en`` parameter [int]
 
   A nonzero value enables Enhanced Multi-Packet Write (eMPW) for ConnectX-5,
-  ConnectX-6, ConnectX-6 DX and BlueField. eMPW allows the TX burst function to pack
+  ConnectX-6, ConnectX-6 Dx and BlueField. eMPW allows the TX burst function to pack
   up multiple packets in a single descriptor session in order to save PCI bandwidth
   and improve performance at the cost of a slightly higher CPU usage. When
   ``txq_inline_mpw`` is set along with ``txq_mpw_en``, TX burst function copies
@@ -559,16 +593,17 @@ Run-time configuration
   The rdma core library can map doorbell register in two ways, depending on the
   environment variable "MLX5_SHUT_UP_BF":
 
-  - As regular cached memory, if the variable is either missing or set to zero.
+  - As regular cached memory (usually with write combining attribute), if the
+    variable is either missing or set to zero.
   - As non-cached memory, if the variable is present and set to not "0" value.
 
   The type of mapping may slightly affect the Tx performance, the optimal choice
   is strongly relied on the host architecture and should be deduced practically.
 
   If ``tx_db_nc`` is set to zero, the doorbell is forced to be mapped to regular
-  memory, the PMD will perform the extra write memory barrier after writing to
-  doorbell, it might increase the needed CPU clocks per packet to send, but
-  latency might be improved.
+  memory (with write combining), the PMD will perform the extra write memory barrier
+  after writing to doorbell, it might increase the needed CPU clocks per packet
+  to send, but latency might be improved.
 
   If ``tx_db_nc`` is set to one, the doorbell is forced to be mapped to non
   cached memory, the PMD will not perform the extra write memory barrier
@@ -589,7 +624,7 @@ Run-time configuration
 
 - ``tx_vec_en`` parameter [int]
 
-  A nonzero value enables Tx vector on ConnectX-5, ConnectX-6, ConnectX-6 DX
+  A nonzero value enables Tx vector on ConnectX-5, ConnectX-6, ConnectX-6 Dx
   and BlueField NICs if the number of global Tx queues on the port is less than
   ``txqs_max_vec``. The parameter is deprecated and ignored.
 
@@ -658,7 +693,7 @@ Run-time configuration
   +------+-----------+-----------+-------------+-------------+
   | 1    | 24 bits   | vary 0-32 | 32 bits     | yes         |
   +------+-----------+-----------+-------------+-------------+
-  | 2    | vary 0-32 | 32 bits   | 32 bits     | yes         |
+  | 2    | vary 0-24 | 32 bits   | 32 bits     | yes         |
   +------+-----------+-----------+-------------+-------------+
 
   If there is no E-Switch configuration the ``dv_xmeta_en`` parameter is
@@ -670,6 +705,17 @@ Run-time configuration
   of the extensive metadata features. The legacy Verbs supports FLAG and
   MARK metadata actions over NIC Rx steering domain only.
 
+  Setting META value to zero in flow action means there is no item provided
+  and receiving datapath will not report in mbufs the metadata are present.
+  Setting MARK value to zero in flow action means the zero FDIR ID value
+  will be reported on packet receiving.
+
+  For the MARK action the last 16 values in the full range are reserved for
+  internal PMD purposes (to emulate FLAG action). The valid range for the
+  MARK action values is 0-0xFFEF for the 16-bit mode and 0-xFFFFEF
+  for the 24-bit mode, the flows with the MARK action value outside
+  the specified range will be rejected.
+
 - ``dv_flow_en`` parameter [int]
 
   A nonzero value enables the DV flow steering assuming it is supported
@@ -886,7 +932,7 @@ Mellanox OFED/EN
   - ConnectX-5: **16.21.1000** and above.
   - ConnectX-5 Ex: **16.21.1000** and above.
   - ConnectX-6: **20.99.5374** and above.
-  - ConnectX-6 DX: **22.27.0090** and above.
+  - ConnectX-6 Dx: **22.27.0090** and above.
   - BlueField: **18.25.1010** and above.
 
 While these libraries and kernel modules are available on OpenFabrics
@@ -911,28 +957,43 @@ required from that distribution.
 Supported NICs
 --------------
 
-* Mellanox(R) ConnectX(R)-4 10G MCX4111A-XCAT (1x10G)
-* Mellanox(R) ConnectX(R)-4 10G MCX4121A-XCAT (2x10G)
-* Mellanox(R) ConnectX(R)-4 25G MCX4111A-ACAT (1x25G)
-* Mellanox(R) ConnectX(R)-4 25G MCX4121A-ACAT (2x25G)
-* Mellanox(R) ConnectX(R)-4 40G MCX4131A-BCAT (1x40G)
-* Mellanox(R) ConnectX(R)-4 40G MCX413A-BCAT (1x40G)
-* Mellanox(R) ConnectX(R)-4 40G MCX415A-BCAT (1x40G)
-* Mellanox(R) ConnectX(R)-4 50G MCX4131A-GCAT (1x50G)
-* Mellanox(R) ConnectX(R)-4 50G MCX413A-GCAT (1x50G)
-* Mellanox(R) ConnectX(R)-4 50G MCX414A-BCAT (2x50G)
-* Mellanox(R) ConnectX(R)-4 50G MCX415A-GCAT (2x50G)
-* Mellanox(R) ConnectX(R)-4 50G MCX416A-BCAT (2x50G)
-* Mellanox(R) ConnectX(R)-4 50G MCX416A-GCAT (2x50G)
-* Mellanox(R) ConnectX(R)-4 50G MCX415A-CCAT (1x100G)
-* Mellanox(R) ConnectX(R)-4 100G MCX416A-CCAT (2x100G)
-* Mellanox(R) ConnectX(R)-4 Lx 10G MCX4121A-XCAT (2x10G)
-* Mellanox(R) ConnectX(R)-4 Lx 25G MCX4121A-ACAT (2x25G)
-* Mellanox(R) ConnectX(R)-5 100G MCX556A-ECAT (2x100G)
-* Mellanox(R) ConnectX(R)-5 Ex EN 100G MCX516A-CDAT (2x100G)
-* Mellanox(R) ConnectX(R)-6 200G MCX654106A-HCAT (4x200G)
-* Mellanox(R) ConnectX(R)-6DX EN 100G MCX623106AN-CDAT (2*100g)
-* Mellanox(R) ConnectX(R)-6DX EN 200G MCX623105AN-VDAT (1*200g)
+The following Mellanox device families are supported by the same mlx5 driver:
+
+  - ConnectX-4
+  - ConnectX-4 Lx
+  - ConnectX-5
+  - ConnectX-5 Ex
+  - ConnectX-6
+  - ConnectX-6 Dx
+  - BlueField
+
+Below are detailed device names:
+
+* Mellanox\ |reg| ConnectX\ |reg|-4 10G MCX4111A-XCAT (1x10G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 10G MCX412A-XCAT (2x10G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 25G MCX4111A-ACAT (1x25G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 25G MCX412A-ACAT (2x25G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 40G MCX413A-BCAT (1x40G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 40G MCX4131A-BCAT (1x40G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 40G MCX415A-BCAT (1x40G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX413A-GCAT (1x50G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX4131A-GCAT (1x50G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX414A-BCAT (2x50G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX415A-GCAT (1x50G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX416A-BCAT (2x50G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX416A-GCAT (2x50G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 50G MCX415A-CCAT (1x100G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 100G MCX416A-CCAT (2x100G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 Lx 10G MCX4111A-XCAT (1x10G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 Lx 10G MCX4121A-XCAT (2x10G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 Lx 25G MCX4111A-ACAT (1x25G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 Lx 25G MCX4121A-ACAT (2x25G)
+* Mellanox\ |reg| ConnectX\ |reg|-4 Lx 40G MCX4131A-BCAT (1x40G)
+* Mellanox\ |reg| ConnectX\ |reg|-5 100G MCX556A-ECAT (2x100G)
+* Mellanox\ |reg| ConnectX\ |reg|-5 Ex EN 100G MCX516A-CDAT (2x100G)
+* Mellanox\ |reg| ConnectX\ |reg|-6 200G MCX654106A-HCAT (2x200G)
+* Mellanox\ |reg| ConnectX\ |reg|-6 Dx EN 100G MCX623106AN-CDAT (2x100G)
+* Mellanox\ |reg| ConnectX\ |reg|-6 Dx EN 200G MCX623105AN-VDAT (1x200G)
 
 Quick Start Guide on OFED/EN
 ----------------------------
@@ -1195,6 +1256,19 @@ Supported hardware offloads
    |                       | |  ConnectX-5   | | ConnectX-5    |
    +-----------------------+-----------------+-----------------+
 
+Notes for metadata
+------------------
+
+MARK and META items are interrelated with datapath - they might move from/to
+the applications in mbuf fields. Hence, zero value for these items has the
+special meaning - it means "no metadata are provided", not zero values are
+treated by applications and PMD as valid ones.
+
+Moreover in the flow engine domain the value zero is acceptable to match and
+set, and we should allow to specify zero values as rte_flow parameters for the
+META and MARK items and actions. In the same time zero mask has no meaning and
+should be rejected on validation stage.
+
 Notes for testpmd
 -----------------
 
diff --git a/dpdk/doc/guides/nics/nfp.rst b/dpdk/doc/guides/nics/nfp.rst
index 5f2a0698f6..020e37d131 100644
--- a/dpdk/doc/guides/nics/nfp.rst
+++ b/dpdk/doc/guides/nics/nfp.rst
@@ -102,22 +102,39 @@ directory per firmware application. Options 1 and 2 for firmware filenames allow
 more than one SmartNIC, same type of SmartNIC or different ones, and to upload a
 different firmware to each SmartNIC.
 
+   .. Note::
+      Currently the NFP PMD supports using the PF with Agilio Basic Firmware. See
+      https://help.netronome.com/support/solutions for more information on the
+      various firmwares supported by the Netronome Agilio CX smartNIC.
 
 PF multiport support
 --------------------
 
-Some NFP cards support several physical ports with just one single PCI device.
-The DPDK core is designed with a 1:1 relationship between PCI devices and DPDK
-ports, so NFP PMD PF support requires handling the multiport case specifically.
-During NFP PF initialization, the PMD will extract the information about the
-number of PF ports from the firmware and will create as many DPDK ports as
-needed.
+The NFP PMD can work with up to 8 ports on the same PF device. The number of
+available ports is firmware and hardware dependent, and the driver looks for a
+firmware symbol during initialization to know how many can be used.
 
-Because the unusual relationship between a single PCI device and several DPDK
-ports, there are some limitations when using more than one PF DPDK port: there
-is no support for RX interrupts and it is not possible either to use those PF
-ports with the device hotplug functionality.
+DPDK apps work with ports, and a port is usually a PF or a VF PCI device.
+However, with the NFP PF multiport there is just one PF PCI device. Supporting
+this particular configuration requires the PMD to create ports in a special way,
+although once they are created, DPDK apps should be able to use them as normal
+PCI ports.
 
+NFP ports belonging to same PF can be seen inside PMD initialization with a
+suffix added to the PCI ID: wwww:xx:yy.z_port_n. For example, a PF with PCI ID
+0000:03:00.0 and four ports is seen by the PMD code as:
+
+   .. code-block:: console
+
+      0000:03:00.0_port_0
+      0000:03:00.0_port_1
+      0000:03:00.0_port_2
+      0000:03:00.0_port_3
+
+   .. Note::
+
+      There are some limitations with multiport support: RX interrupts and
+      device hot-plugging are not supported.
 
 PF multiprocess support
 -----------------------
diff --git a/dpdk/doc/guides/nics/pcap_ring.rst b/dpdk/doc/guides/nics/pcap_ring.rst
index cf230ae40a..8fdb49179a 100644
--- a/dpdk/doc/guides/nics/pcap_ring.rst
+++ b/dpdk/doc/guides/nics/pcap_ring.rst
@@ -166,7 +166,7 @@ Forward packets through two network interfaces:
 .. code-block:: console
 
     $RTE_TARGET/app/testpmd -l 0-3 -n 4 \
-        --vdev 'net_pcap0,iface=eth0' --vdev='net_pcap1;iface=eth1'
+        --vdev 'net_pcap0,iface=eth0' --vdev='net_pcap1,iface=eth1'
 
 Enable 2 tx queues on a network interface:
 
diff --git a/dpdk/doc/guides/nics/sfc_efx.rst b/dpdk/doc/guides/nics/sfc_efx.rst
index 67d9b054d5..f79ebf518c 100644
--- a/dpdk/doc/guides/nics/sfc_efx.rst
+++ b/dpdk/doc/guides/nics/sfc_efx.rst
@@ -295,7 +295,7 @@ whitelist option like "-w 02:00.0,arg1=value1,...".
 Case-insensitive 1/y/yes/on or 0/n/no/off may be used to specify
 boolean parameters value.
 
-- ``rx_datapath`` [auto|efx|ef10|ef10_esps] (default **auto**)
+- ``rx_datapath`` [auto|efx|ef10|ef10_essb] (default **auto**)
 
   Choose receive datapath implementation.
   **auto** allows the driver itself to make a choice based on firmware
@@ -304,7 +304,7 @@ boolean parameters value.
   **ef10** chooses EF10 (SFN7xxx, SFN8xxx, X2xxx) native datapath which is
   more efficient than libefx-based and provides richer packet type
   classification.
-  **ef10_esps** chooses SFNX2xxx equal stride packed stream datapath
+  **ef10_essb** chooses SFNX2xxx equal stride super-buffer datapath
   which may be used on DPDK firmware variant only
   (see notes about its limitations above).
 
diff --git a/dpdk/doc/guides/prog_guide/cryptodev_lib.rst b/dpdk/doc/guides/prog_guide/cryptodev_lib.rst
index ac16437740..c839379885 100644
--- a/dpdk/doc/guides/prog_guide/cryptodev_lib.rst
+++ b/dpdk/doc/guides/prog_guide/cryptodev_lib.rst
@@ -1097,4 +1097,4 @@ Asymmetric Crypto Device API
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The cryptodev Library API is described in the
-`DPDK API Reference <http://doc.dpdk.org/api/>`_
+`DPDK API Reference <https://doc.dpdk.org/api/>`_
diff --git a/dpdk/doc/guides/prog_guide/img/ring-mp-enqueue3.svg b/dpdk/doc/guides/prog_guide/img/ring-mp-enqueue3.svg
index da483b031e..83ef7dba13 100644
--- a/dpdk/doc/guides/prog_guide/img/ring-mp-enqueue3.svg
+++ b/dpdk/doc/guides/prog_guide/img/ring-mp-enqueue3.svg
@@ -16,7 +16,7 @@
    height="403.06647"
    id="svg3388"
    version="1.1"
-   inkscape:version="0.48.4 r9939"
+   inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
    sodipodi:docname="ring-mp-enqueue3.svg">
   <defs
      id="defs3390">
@@ -359,15 +359,15 @@
      inkscape:pageshadow="2"
      inkscape:zoom="1.4"
      inkscape:cx="201.35119"
-     inkscape:cy="221.79811"
+     inkscape:cy="107.5124"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
      showgrid="false"
-     inkscape:window-width="958"
-     inkscape:window-height="1002"
-     inkscape:window-x="223"
-     inkscape:window-y="22"
-     inkscape:window-maximized="0"
+     inkscape:window-width="1313"
+     inkscape:window-height="713"
+     inkscape:window-x="53"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
      inkscape:snap-grids="false"
      inkscape:snap-to-guides="true"
      showguides="false"
@@ -382,8 +382,10 @@
        visible="true"
        enabled="true"
        snapvisiblegridlinesonly="true"
-       originx="-162.97143px"
-       originy="-370.03525px" />
+       originx="-162.97143"
+       originy="-370.03525"
+       spacingx="1"
+       spacingy="1" />
   </sodipodi:namedview>
   <metadata
      id="metadata3393">
@@ -393,7 +395,7 @@
         <dc:format>image/svg+xml</dc:format>
         <dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title />
+        <dc:title></dc:title>
       </cc:Work>
     </rdf:RDF>
   </metadata>
@@ -490,37 +492,37 @@
     </g>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="313.90488"
        y="495.49646"
-       id="text4269"
-       sodipodi:linespacing="125%"><tspan
+       id="text4269"><tspan
          sodipodi:role="line"
          id="tspan4271"
          x="313.90488"
-         y="495.49646">obj1</tspan></text>
+         y="495.49646"
+         style="font-size:14px;line-height:1.25">obj1</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="368.95203"
        y="495.49646"
-       id="text4269-4"
-       sodipodi:linespacing="125%"><tspan
+       id="text4269-4"><tspan
          sodipodi:role="line"
          id="tspan4271-5"
          x="368.95203"
-         y="495.49646">obj2</tspan></text>
+         y="495.49646"
+         style="font-size:14px;line-height:1.25">obj2</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="422.99518"
        y="495.49646"
-       id="text4269-5"
-       sodipodi:linespacing="125%"><tspan
+       id="text4269-5"><tspan
          sodipodi:role="line"
          id="tspan4271-4"
          x="422.99518"
-         y="495.49646">obj3</tspan></text>
+         y="495.49646"
+         style="font-size:14px;line-height:1.25">obj3</tspan></text>
     <path
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend);font-family:Arial;-inkscape-font-specification:Arial"
        d="m 323.57143,578.07647 0,-42.14286"
@@ -533,48 +535,48 @@
        inkscape:connector-curvature="0" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="289.85715"
        y="589.505"
-       id="text4787"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787"><tspan
          sodipodi:role="line"
          id="tspan4789"
          x="289.85715"
-         y="589.505">cons_head</tspan></text>
+         y="589.505"
+         style="font-size:14px;line-height:1.25">cons_head</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="293.45334"
        y="603.41034"
-       id="text4787-3"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-3"><tspan
          sodipodi:role="line"
          id="tspan4789-0"
          x="293.45334"
-         y="603.41034">cons_tail</tspan></text>
+         y="603.41034"
+         style="font-size:14px;line-height:1.25">cons_tail</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
-       x="527.01239"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
+       x="567.01239"
        y="587.9577"
-       id="text4787-7"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-7"><tspan
          sodipodi:role="line"
          id="tspan4789-8"
-         x="527.01239"
-         y="587.9577">prod_head</tspan></text>
+         x="567.01239"
+         y="587.9577"
+         style="font-size:14px;line-height:1.25">prod_head</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="460.7514"
        y="602.57739"
-       id="text4787-3-6"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-3-6"><tspan
          sodipodi:role="line"
          id="tspan4789-0-8"
          x="460.7514"
-         y="602.57739">prod_tail</tspan></text>
+         y="602.57739"
+         style="font-size:14px;line-height:1.25">prod_tail</tspan></text>
     <rect
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 1;stroke-dashoffset:0;font-family:Arial;-inkscape-font-specification:Arial"
        id="rect4889"
@@ -586,19 +588,20 @@
        ry="11.631636" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="174.28571"
        y="328.93362"
-       id="text4891"
-       sodipodi:linespacing="125%"><tspan
+       id="text4891"><tspan
          sodipodi:role="line"
          id="tspan4893"
          x="174.28571"
-         y="328.93362">local variables</tspan><tspan
+         y="328.93362"
+         style="font-size:14px;line-height:1.25">local variables</tspan><tspan
          sodipodi:role="line"
          x="174.28571"
          y="346.43362"
-         id="tspan4150">core 2</tspan></text>
+         id="tspan4150"
+         style="font-size:14px;line-height:1.25">core 2</tspan></text>
     <rect
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 1;stroke-dashoffset:0;font-family:Arial;-inkscape-font-specification:Arial"
        id="rect4889-8"
@@ -610,15 +613,15 @@
        ry="11.631636" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="170.89287"
-       y="682.09021"
-       id="text4891-4"
-       sodipodi:linespacing="125%"><tspan
+       y="664.09021"
+       id="text4891-4"><tspan
          sodipodi:role="line"
          id="tspan4893-3"
          x="170.89287"
-         y="682.09021">structure state</tspan></text>
+         y="664.09021"
+         style="font-size:14px;line-height:1.25">structure state</tspan></text>
     <path
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend);font-family:Arial;-inkscape-font-specification:Arial"
        d="m 325.25296,407.43361 0,42.14286"
@@ -631,37 +634,37 @@
        inkscape:connector-curvature="0" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="296.992"
        y="401.48123"
-       id="text4787-3-64"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-3-64"><tspan
          sodipodi:role="line"
          id="tspan4789-0-9"
          x="296.992"
-         y="401.48123">cons_tail</tspan></text>
+         y="401.48123"
+         style="font-size:14px;line-height:1.25">cons_tail</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="440.26532"
        y="401.48123"
-       id="text4787-7-5"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-7-5"><tspan
          sodipodi:role="line"
          id="tspan4789-8-0"
          x="440.26532"
-         y="401.48123">prod_head</tspan></text>
+         y="401.48123"
+         style="font-size:14px;line-height:1.25">prod_head</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="522.43298"
        y="401.48123"
-       id="text4787-3-6-4"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-3-6-4"><tspan
          sodipodi:role="line"
          id="tspan4789-0-8-8"
          x="522.43298"
-         y="401.48123">prod_next</tspan></text>
+         y="401.48123"
+         style="font-size:14px;line-height:1.25">prod_next</tspan></text>
     <path
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend);font-family:Arial;-inkscape-font-specification:Arial"
        d="m 537.14285,407.43361 0,42.14286"
@@ -678,19 +681,20 @@
        ry="11.631636" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="174.65646"
        y="398.23306"
-       id="text4891-3"
-       sodipodi:linespacing="125%"><tspan
+       id="text4891-3"><tspan
          sodipodi:role="line"
          id="tspan4893-1"
          x="174.65646"
-         y="398.23306">local variables</tspan><tspan
+         y="398.23306"
+         style="font-size:14px;line-height:1.25">local variables</tspan><tspan
          sodipodi:role="line"
          x="174.65646"
          y="415.73306"
-         id="tspan4152">core 1</tspan></text>
+         id="tspan4152"
+         style="font-size:14px;line-height:1.25">core 1</tspan></text>
     <path
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend);font-family:Arial;-inkscape-font-specification:Arial"
        d="m 326.73097,334.53006 0,42.14286"
@@ -703,37 +707,37 @@
        inkscape:connector-curvature="0" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="298.47"
        y="328.57767"
-       id="text4787-3-64-5"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-3-64-5"><tspan
          sodipodi:role="line"
          id="tspan4789-0-9-0"
          x="298.47"
-         y="328.57767">cons_tail</tspan></text>
+         y="328.57767"
+         style="font-size:14px;line-height:1.25">cons_tail</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="489.02905"
        y="328.57767"
-       id="text4787-7-5-3"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-7-5-3"><tspan
          sodipodi:role="line"
          id="tspan4789-8-0-6"
          x="489.02905"
-         y="328.57767">prod_head</tspan></text>
+         y="328.57767"
+         style="font-size:14px;line-height:1.25">prod_head</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="571.19672"
        y="328.57767"
-       id="text4787-3-6-4-1"
-       sodipodi:linespacing="125%"><tspan
+       id="text4787-3-6-4-1"><tspan
          sodipodi:role="line"
          id="tspan4789-0-8-8-0"
          x="571.19672"
-         y="328.57767">prod_next</tspan></text>
+         y="328.57767"
+         style="font-size:14px;line-height:1.25">prod_next</tspan></text>
     <path
        style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend);font-family:Arial;-inkscape-font-specification:Arial"
        d="m 587.90657,334.53006 0,42.14286"
@@ -741,45 +745,46 @@
        inkscape:connector-curvature="0" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="447.85715"
        y="289.505"
-       id="text3320"
-       sodipodi:linespacing="125%"><tspan
+       id="text3320"><tspan
          sodipodi:role="line"
          id="tspan3322"
          x="447.85715"
-         y="289.505">compare and swap succeeds</tspan><tspan
+         y="289.505"
+         style="font-size:14px;line-height:1.25">compare and swap succeeds</tspan><tspan
          sodipodi:role="line"
          x="447.85715"
          y="307.005"
-         id="tspan3324">on core 2</tspan></text>
+         id="tspan3324"
+         style="font-size:14px;line-height:1.25">on core 2</tspan></text>
     <path
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend);font-family:Arial;-inkscape-font-specification:Arial"
-       d="m 542.85715,575.57647 0,-42.14286"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:14px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+       d="M 602.85715,575.57647 V 533.43361"
        id="path4309-4-0"
        inkscape:connector-curvature="0" />
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="477.22983"
        y="495.49646"
-       id="text4269-5-5"
-       sodipodi:linespacing="125%"><tspan
+       id="text4269-5-5"><tspan
          sodipodi:role="line"
          id="tspan4271-4-5"
          x="477.22983"
-         y="495.49646">obj4</tspan></text>
+         y="495.49646"
+         style="font-size:14px;line-height:1.25">obj4</tspan></text>
     <text
        xml:space="preserve"
-       style="font-size:14px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
        x="531.27301"
        y="496.00156"
-       id="text4269-5-7"
-       sodipodi:linespacing="125%"><tspan
+       id="text4269-5-7"><tspan
          sodipodi:role="line"
          id="tspan4271-4-6"
          x="531.27301"
-         y="496.00156">obj5</tspan></text>
+         y="496.00156"
+         style="font-size:14px;line-height:1.25">obj5</tspan></text>
   </g>
 </svg>
diff --git a/dpdk/doc/guides/prog_guide/kernel_nic_interface.rst b/dpdk/doc/guides/prog_guide/kernel_nic_interface.rst
index 32d09ccf82..f5904f4d1b 100644
--- a/dpdk/doc/guides/prog_guide/kernel_nic_interface.rst
+++ b/dpdk/doc/guides/prog_guide/kernel_nic_interface.rst
@@ -178,7 +178,7 @@ KNI Creation and Deletion
 -------------------------
 
 Before any KNI interfaces can be created, the ``rte_kni`` kernel module must
-be loaded into the kernel and configured withe ``rte_kni_init()`` function.
+be loaded into the kernel and configured with the ``rte_kni_init()`` function.
 
 The KNI interfaces are created by a DPDK application dynamically via the
 ``rte_kni_alloc()`` function.
diff --git a/dpdk/doc/guides/prog_guide/lto.rst b/dpdk/doc/guides/prog_guide/lto.rst
index 43f4c63379..277a6f1090 100644
--- a/dpdk/doc/guides/prog_guide/lto.rst
+++ b/dpdk/doc/guides/prog_guide/lto.rst
@@ -31,7 +31,7 @@ the whole DPDK by setting:
 
 .. code-block:: console
 
-    CONFIG_ENABLE_LTO=y
+    CONFIG_RTE_ENABLE_LTO=y
 
 in config file.
 
diff --git a/dpdk/doc/guides/prog_guide/multi_proc_support.rst b/dpdk/doc/guides/prog_guide/multi_proc_support.rst
index a84083b96c..1a4a9e2d4d 100644
--- a/dpdk/doc/guides/prog_guide/multi_proc_support.rst
+++ b/dpdk/doc/guides/prog_guide/multi_proc_support.rst
@@ -75,7 +75,7 @@ and point to the same objects, in both processes.
 
 
 The EAL also supports an auto-detection mode (set by EAL ``--proc-type=auto`` flag ),
-whereby an DPDK process is started as a secondary instance if a primary instance is already running.
+whereby a DPDK process is started as a secondary instance if a primary instance is already running.
 
 Deployment Models
 -----------------
diff --git a/dpdk/doc/guides/prog_guide/packet_classif_access_ctrl.rst b/dpdk/doc/guides/prog_guide/packet_classif_access_ctrl.rst
index 2945eacf55..f99302a5e8 100644
--- a/dpdk/doc/guides/prog_guide/packet_classif_access_ctrl.rst
+++ b/dpdk/doc/guides/prog_guide/packet_classif_access_ctrl.rst
@@ -373,6 +373,12 @@ There are several implementations of classify algorithm:
 
 *   **RTE_ACL_CLASSIFY_AVX2**: vector implementation, can process up to 16 flows in parallel. Requires AVX2 support.
 
+*   **RTE_ACL_CLASSIFY_NEON**: vector implementation, can process up to 8 flows
+    in parallel. Requires NEON support.
+
+*   **RTE_ACL_CLASSIFY_ALTIVEC**: vector implementation, can process up to 8
+    flows in parallel. Requires ALTIVEC support.
+
 It is purely a runtime decision which method to choose, there is no build-time difference.
 All implementations operates over the same internal RT structures and use similar principles. The main difference is that vector implementations can manually exploit IA SIMD instructions and process several input data flows in parallel.
 At startup ACL library determines the highest available classify method for the given platform and sets it as default one. Though the user has an ability to override the default classifier function for a given ACL context or perform particular search using non-default classify method. In that case it is user responsibility to make sure that given platform supports selected classify implementation.
diff --git a/dpdk/doc/guides/prog_guide/rcu_lib.rst b/dpdk/doc/guides/prog_guide/rcu_lib.rst
index 8d0dfcf291..9b0bf138f6 100644
--- a/dpdk/doc/guides/prog_guide/rcu_lib.rst
+++ b/dpdk/doc/guides/prog_guide/rcu_lib.rst
@@ -61,7 +61,7 @@ wait till thread 2 enters quiescent state as well.
 
 However, the writer does not need to wait for reader thread 3 to enter
 quiescent state. Reader thread 3 was not accessing D1 when the delete
-operation happened. So, reader thread 1 will not have a reference to the
+operation happened. So, reader thread 3 will not have a reference to the
 deleted entry.
 
 It can be noted that, the critical sections for D2 is a quiescent state
diff --git a/dpdk/doc/guides/prog_guide/thread_safety_dpdk_functions.rst b/dpdk/doc/guides/prog_guide/thread_safety_dpdk_functions.rst
index 0f539db2b8..5618e25e47 100644
--- a/dpdk/doc/guides/prog_guide/thread_safety_dpdk_functions.rst
+++ b/dpdk/doc/guides/prog_guide/thread_safety_dpdk_functions.rst
@@ -61,8 +61,8 @@ rather than subsequently in the forwarding threads.
 However, the DPDK performs checks to ensure that libraries are only initialized once.
 If initialization is attempted more than once, an error is returned.
 
-In the multi-process case, the configuration information of shared memory will only be initialized by the master process.
-Thereafter, both master and secondary processes can allocate/release any objects of memory that finally rely on rte_malloc or memzones.
+In the multi-process case, the configuration information of shared memory will only be initialized by the primary process.
+Thereafter, both primary and secondary processes can allocate/release any objects of memory that finally rely on rte_malloc or memzones.
 
 Interrupt Thread
 ----------------
diff --git a/dpdk/doc/guides/rawdevs/ntb.rst b/dpdk/doc/guides/rawdevs/ntb.rst
index 58472135f5..aa7d809649 100644
--- a/dpdk/doc/guides/rawdevs/ntb.rst
+++ b/dpdk/doc/guides/rawdevs/ntb.rst
@@ -52,11 +52,11 @@ NTB PMD needs kernel PCI driver to support write combining (WC) to get
 better performance. The difference will be more than 10 times.
 To enable WC, there are 2 ways.
 
-- Insert igb_uio with ``wc_active=1`` flag if use igb_uio driver.
+- Insert igb_uio with ``wc_activate=1`` flag if use igb_uio driver.
 
 .. code-block:: console
 
-  insmod igb_uio.ko wc_active=1
+  insmod igb_uio.ko wc_activate=1
 
 - Enable WC for NTB device's Bar 2 and Bar 4 (Mapped memory) manually.
   The reference is https://www.kernel.org/doc/html/latest/x86/mtrr.html
diff --git a/dpdk/doc/guides/rel_notes/deprecation.rst b/dpdk/doc/guides/rel_notes/deprecation.rst
index afa94b43e2..58109590cc 100644
--- a/dpdk/doc/guides/rel_notes/deprecation.rst
+++ b/dpdk/doc/guides/rel_notes/deprecation.rst
@@ -67,12 +67,6 @@ Deprecation Notices
   In 19.11 PMDs will still update the field even when the offload is not
   enabled.
 
-* cryptodev: support for using IV with all sizes is added, J0 still can
-  be used but only when IV length in following structs ``rte_crypto_auth_xform``,
-  ``rte_crypto_aead_xform`` is set to zero. When IV length is greater or equal
-  to one it means it represents IV, when is set to zero it means J0 is used
-  directly, in this case 16 bytes of J0 need to be passed.
-
 * sched: To allow more traffic classes, flexible mapping of pipe queues to
   traffic classes, and subport level configuration of pipes and queues
   changes will be made to macros, data structures and API functions defined
@@ -81,8 +75,3 @@ Deprecation Notices
 
 * metrics: The function ``rte_metrics_init`` will have a non-void return
   in order to notify errors instead of calling ``rte_exit``.
-
-* power: ``rte_power_set_env`` function will no longer return 0 on attempt
-  to set new power environment if power environment was already initialized.
-  In this case the function will return -1 unless the environment is unset first
-  (using ``rte_power_unset_env``). Other function usage scenarios will not change.
diff --git a/dpdk/doc/guides/rel_notes/release_18_08.rst b/dpdk/doc/guides/rel_notes/release_18_08.rst
index 8a09dee95c..4ae388c331 100644
--- a/dpdk/doc/guides/rel_notes/release_18_08.rst
+++ b/dpdk/doc/guides/rel_notes/release_18_08.rst
@@ -546,4 +546,4 @@ Tested Platforms
      * Mellanox MLNX_OFED 4.2-1.4.21.0
 
   * DPDK application running on ARM cores inside SmartNIC
-  * Bluefield representors support planned for next release.
+  * BlueField representors support planned for next release.
diff --git a/dpdk/doc/guides/rel_notes/release_19_02.rst b/dpdk/doc/guides/rel_notes/release_19_02.rst
index ace1534eff..87dfbf5c7d 100644
--- a/dpdk/doc/guides/rel_notes/release_19_02.rst
+++ b/dpdk/doc/guides/rel_notes/release_19_02.rst
@@ -109,7 +109,7 @@ New Features
     ``CONFIG_RTE_IBVERBS_LINK_DLOPEN`` for make and ``ibverbs_link`` for meson.
   * Added static linkage of ``mlx`` dependency.
   * Improved stability of E-Switch flow driver.
-  * Added new make build configuration to set the cacheline size for Bluefield
+  * Added new make build configuration to set the cacheline size for BlueField
     correctly - ``arm64-bluefield-linux-gcc``.
 
 * **Updated the enic driver.**
diff --git a/dpdk/doc/guides/rel_notes/release_19_11.rst b/dpdk/doc/guides/rel_notes/release_19_11.rst
index 84aa03a1f2..511d7f87bd 100644
--- a/dpdk/doc/guides/rel_notes/release_19_11.rst
+++ b/dpdk/doc/guides/rel_notes/release_19_11.rst
@@ -206,7 +206,7 @@ New Features
   * Added support for VLAN set VID offload command.
   * Added support for matching on packets withe Geneve tunnel header.
   * Added hairpin support.
-  * Added ConnectX6-DX support.
+  * Added ConnectX-6 Dx support.
   * Flow engine selected based on RDMA Core library version.
     DV flow engine selected if version is rdma-core-24.0 or higher.
     Verbs flow engine selected otherwise.
@@ -474,9 +474,8 @@ API Changes
 
 * event: The function ``rte_event_eth_tx_adapter_enqueue`` takes an additional
   input as ``flags``. Flag ``RTE_EVENT_ETH_TX_ADAPTER_ENQUEUE_SAME_DEST`` which
-  has been introduced in this release is used when used when all the packets
-  enqueued in the Tx adapter are destined for the same Ethernet port ans Tx
-  queue.
+  has been introduced in this release is used when all the packets enqueued in
+  the Tx adapter are destined for the same Ethernet port and Tx queue.
 
 * sched: The pipe nodes configuration parameters such as number of pipes,
   pipe queue sizes, pipe profiles, etc., are moved from port level structure
@@ -918,3 +917,2313 @@ Tested Platforms
   * OFED:
 
     * MLNX_OFED 4.7-1.0.0.2
+
+19.11.1 Release Notes
+---------------------
+
+19.11.1 Fixes
+~~~~~~~~~~~~~
+
+* acl: fix 32-bit match for range field
+* app/eventdev: fix pipeline test with meson build
+* app/pdump: fix build with clang
+* app/testpmd: add port check before manual detach
+* app/testpmd: call cleanup on exit
+* app/testpmd: fix device mcast list error handling
+* app/testpmd: fix GENEVE flow item
+* app/testpmd: fix hot-unplug detaching
+* app/testpmd: fix identifier size for port attach
+* app/testpmd: fix initial value when setting PFC
+* app/testpmd: fix RFC addresses for Tx only
+* app/testpmd: fix txonly flow generation entropy
+* app/testpmd: fix uninitialized members of MPLS
+* app/testpmd: fix uninitialized members when setting PFC
+* app/testpmd: rename function for detaching by devargs
+* app/testpmd: update Rx offload after setting MTU
+* app/test: remove meson dependency on file in /sys
+* bpf: fix headers install with meson
+* build: explicitly enable sse4 for meson
+* build: fix libm detection in meson
+* build: remove unneeded function versioning
+* bus/fslmc: remove conflicting memory barrier macro
+* cfgfile: fix symbols map
+* ci: fix Travis config warnings
+* ci: use meson 0.47.1
+* common/cpt: check cipher and auth keys are set
+* common/cpt: fix component for empty IOV buffer
+* crypto/armv8: fix clang build
+* crypto/ccp: fix queue alignment
+* crypto/dpaa_sec: fix IOVA conversions
+* crypto/octeontx2: add kmod dependency info
+* devtools: add fixes flag to commit listing
+* devtools: fix debug build test
+* doc: add module EEPROM dump to mlx5 features
+* doc: clarify memory write combining in mlx5 guide
+* doc: fix build with python 3.8
+* doc: fix devargs in OCTEON TX2 event device guide
+* doc: fix igb_uio parameter in ntb guide
+* doc: fix multi-producer enqueue figure in ring guide
+* doc: fix naming of Mellanox devices
+* doc: fix quiescent state description in RCU guide
+* doc: fix typos in 19.11 release notes
+* doc: fix warning with meson
+* doc: reduce indentation in meson build file
+* doc: reduce whitespace in meson build file
+* doc: update recommended versions for i40e
+* drivers/crypto: fix session-less mode
+* eal/linux: fix build error on RHEL 7.6
+* eal/linux: fix build when VFIO is disabled
+* eal/linux: fix uninitialized data valgrind warning
+* eal/windows: fix cpuset macro name
+* ethdev: fix callback unregister with wildcard argument list
+* ethdev: fix flow API doxygen comment
+* ethdev: fix secondary process memory overwrite
+* ethdev: fix switching domain allocation
+* ethdev: fix VLAN offloads set if no driver callback
+* event/dpaa2: set number of order sequences
+* event/dsw: avoid credit leak on oversized enqueue bursts
+* event/dsw: flush buffers immediately on zero-sized enqueue
+* event/octeontx2: fix device name in device info
+* examples/ethtool: fix unchecked return value
+* examples/fips_validation: fix AES-GCM cipher length parsing
+* examples/fips_validation: fix cipher length for AES-GCM
+* examples/fips_validation: fix string token for CT length
+* examples/ioat: fix failure check for ioat dequeue
+* examples/ioat: fix invalid link status check
+* examples/ioat: fix unchecked return value
+* examples/ipsec-secgw: extend inline session to non AES-GCM
+* examples/ipsec-secgw: fix crash on unsupported algo
+* examples/l2fwd-event: fix core allocation in poll mode
+* examples/l2fwd-event: fix error checking
+* examples/l2fwd-event: fix ethdev RSS setup
+* examples/l2fwd-event: fix event device config
+* examples/l3fwd-power: fix a typo
+* examples/l3fwd-power: fix interrupt disable
+* examples/ntb: fix mempool ops setting
+* examples/power: fix ack for enable/disable turbo
+* examples/tep_term: remove redundant info get
+* examples/vhost_blk: check unused value on init
+* examples/vhost_blk: fix check of device path
+* fib: fix possible integer overflow
+* fix Mellanox copyright and SPDX tag
+* hash: fix lock-free flag doxygen
+* hash: fix meson headers packaging
+* kni: fix build with Linux 5.6
+* kni: fix meson warning about console keyword
+* kni: fix not contiguous FIFO
+* kni: rename variable with namespace prefix
+* latency: fix calculation for multi-thread
+* lib: fix unnecessary double negation
+* maintainers: resign from flow API maintenance
+* maintainers: update for failsafe and PCI library
+* mem: fix munmap in error unwind
+* mempool: fix anonymous populate
+* mempool: fix populate with small virtual chunks
+* mempool: fix slow allocation of large pools
+* mempool/octeontx: fix error handling in initialization
+* mk: avoid combining -r and -export-dynamic linker options
+* net/af_xdp: fix fill queue addresses
+* net/af_xdp: fix maximum MTU
+* net/af_xdp: fix redundant check for wakeup need
+* net/af_xdp: fix umem frame size and headroom
+* net/bnx2x: fix reset of scan FP flag
+* net/bnx2x: fix to sync fastpath Rx queue access
+* net/bnx2x: fix VLAN stripped flag
+* net/bnx2x: support secondary process
+* net/bnxt: add a field for FW capabilities
+* net/bnxt: allow group ID 0 for RSS action
+* net/bnxt: do not log error if stats queried before start
+* net/bnxt: fix alloc filter to use a common routine
+* net/bnxt: fix buffer allocation reattempt
+* net/bnxt: fix bumping of L2 filter reference count
+* net/bnxt: fix crash in port stop while handling events
+* net/bnxt: fix default timeout for getting FW version
+* net/bnxt: fix enable/disable VLAN filtering
+* net/bnxt: fix flow creation
+* net/bnxt: fix flow flush to sync with flow destroy
+* net/bnxt: fix IOVA mapping
+* net/bnxt: fix link during port toggle
+* net/bnxt: fix MAC address setting when port is stopped
+* net/bnxt: fix max rings calculation
+* net/bnxt: fix non matching flow hitting filter rule
+* net/bnxt: fix overwriting error message
+* net/bnxt: fix port stop on error recovery failure
+* net/bnxt: fix probe in FreeBSD
+* net/bnxt: fix race condition when port is stopped
+* net/bnxt: fix recovery alarm race condition in port close
+* net/bnxt: fix request for hot reset support
+* net/bnxt: fix return code handling in VLAN config
+* net/bnxt: fix reusing L2 filter
+* net/bnxt: fix Tx queue profile selection
+* net/bnxt: fix unnecessary delay in port stop
+* net/bnxt: fix VLAN strip
+* net/bnxt: fix VLAN strip flags in SSE Rx
+* net/bnxt: handle HW filter setting when port is stopped
+* net/bnxt: remove a redundant variable
+* net/bnxt: remove redundant if statement
+* net/bnxt: remove redundant macro
+* net/bnxt: remove unnecessary memset
+* net/bnxt: remove unnecessary structure variable
+* net/bnxt: restore MAC filters during reset recovery
+* net/bnxt: restore VLAN filters during reset recovery
+* net/bnxt: use macro for PCI log format
+* net/cxgbe: announce Tx multi-segments offload
+* net/dpaa: fix Rx offload flags on jumbo MTU set
+* net/failsafe: fix reported hash key size in device info
+* net/fm10k: fix descriptor VLAN field filling in Tx
+* net/fm10k: fix non-x86 build
+* net/hns3: fix crash when closing port
+* net/hns3: fix dumping VF register information
+* net/hns3: fix link status on failed query
+* net/hns3: fix ring vector related mailbox command format
+* net/hns3: fix Rx queue search with broadcast packet
+* net/hns3: fix triggering reset procedure in slave process
+* net/i40e/base: add new link speed constants
+* net/i40e/base: fix buffer address
+* net/i40e/base: fix display of FEC settings
+* net/i40e/base: fix error message
+* net/i40e/base: fix missing link modes
+* net/i40e/base: fix retrying logic
+* net/i40e/base: fix Tx descriptors number
+* net/i40e: fix port close in FreeBSD
+* net/i40e: fix Tx when TSO is enabled
+* net/i40e: fix unchecked Tx cleanup error
+* net/i40e: set fixed flag for exact link speed
+* net/iavf: add TSO offload use basic path
+* net/iavf/base: fix adminq return
+* net/iavf/base: fix command buffer memory leak
+* net/iavf: fix Rx total stats
+* net/iavf: fix virtual channel return
+* net/ice: add outer IPv4 matching for GTP-U flow
+* net/ice/base: fix loop limit
+* net/ice/base: increase PF reset wait timeout
+* net/ice: disable TSO offload in vector path
+* net/ice: fix flow director flag
+* net/ice: fix flow director GTP-U pattern
+* net/ice: fix flow director passthru
+* net/ice: fix flow FDIR/switch memory leak
+* net/ice: fix GTP-U rule conflict
+* net/ice: fix packet type table
+* net/ice: fix queue MSI-X interrupt binding
+* net/ice: fix Tx when TSO is enabled
+* net/ice: fix unchecked Tx cleanup error
+* net/ice: fix VSI context
+* net/ice: use ethernet copy API to do MAC assignment
+* net/ipn3ke: fix line side statistics register read
+* net/ipn3ke: fix meson build
+* net/ixgbe: check for illegal Tx packets
+* net/ixgbe: fix blocking system events
+* net/ixgbe: fix flow control mode setting
+* net/ixgbe: fix link status
+* net/ixgbe: fix link up in FreeBSD
+* net/ixgbe: remove dead code
+* net/ixgbe: remove duplicate function declaration
+* net/ixgbe: set fixed flag for exact link speed
+* net/mlx5: add free on completion queue
+* net/mlx5: allow push VLAN without VID
+* net/mlx5: block pop VLAN action on Tx
+* net/mlx5: block push VLAN action on Rx
+* net/mlx5: clean up redundant assignment
+* net/mlx5: engage free on completion queue
+* net/mlx5: fix bit mask to validate push VLAN
+* net/mlx5: fix blocker for push VLAN on Rx
+* net/mlx5: fix build with clang 3.4.2
+* net/mlx5: fix check for VLAN actions
+* net/mlx5: fix crash when meter action conf is null
+* net/mlx5: fix crash when setting hairpin queues
+* net/mlx5: fix dirty array of actions
+* net/mlx5: fix doorbell register offset type
+* net/mlx5: fix encap/decap validation
+* net/mlx5: fix flow match on GRE key
+* net/mlx5: fix GENEVE tunnel flow validation
+* net/mlx5: fix hairpin queue capacity
+* net/mlx5: fix ICMPv6 header rewrite actions
+* net/mlx5: fix ICMPv6 header rewrite action validation
+* net/mlx5: fix inline packet size for ConnectX-4 Lx
+* net/mlx5: fix item flag on GENEVE item validation
+* net/mlx5: fix L3 VXLAN RSS expansion
+* net/mlx5: fix layer flags missing in metadata
+* net/mlx5: fix layer type in header modify action
+* net/mlx5: fix layer validation with decapsulation
+* net/mlx5: fix legacy multi-packet write session
+* net/mlx5: fix masks of encap and decap actions
+* net/mlx5: fix matcher field usage for metadata entities
+* net/mlx5: fix match information in meter
+* net/mlx5: fix matching for ICMP fragments
+* net/mlx5: fix match on ethertype and CVLAN tag
+* net/mlx5: fix memory regions release deadlock
+* net/mlx5: fix metadata item endianness conversion
+* net/mlx5: fix metadata split with encap action
+* net/mlx5: fix meter header modify before decap
+* net/mlx5: fix meter suffix flow
+* net/mlx5: fix modify actions support limitation
+* net/mlx5: fix multiple flow table hash list
+* net/mlx5: fix pop VLAN action validation
+* net/mlx5: fix register usage in meter
+* net/mlx5: fix running without Rx queue
+* net/mlx5: fix setting of port ID for egress rules
+* net/mlx5: fix setting of Rx hash fields
+* net/mlx5: fix shared metadata matcher field setup
+* net/mlx5: fix tunnel flow priority
+* net/mlx5: fix Tx burst routines set
+* net/mlx5: fix VLAN actions in meter
+* net/mlx5: fix VLAN ID action offset
+* net/mlx5: fix VLAN match for DV mode
+* net/mlx5: fix VLAN VID action validation
+* net/mlx5: fix VXLAN-GPE item translation
+* net/mlx5: fix zero out UDP checksum in encap data
+* net/mlx5: make FDB default rule optional
+* net/mlx5: move Tx complete request routine
+* net/mlx5: optimize Rx hash fields conversion
+* net/mlx5: support maximum flow id allocation
+* net/mlx5: unify validation of drop action
+* net/mlx5: update description of validation functions
+* net/mlx5: update Tx error handling routine
+* net/mlx: add static ibverbs linkage with meson
+* net/mlx: fix build with clang 9
+* net/mlx: fix overlinking with meson and glue dlopen
+* net/mlx: rename meson variable for dlopen option
+* net/mlx: workaround static linkage with meson
+* net/netvsc: disable before changing RSS parameters
+* net/netvsc: fix crash in secondary process
+* net/netvsc: fix RSS offload flag
+* net/netvsc: initialize link state
+* net/octeontx2: fix flow control initial state
+* net/octeontx2: fix getting supported packet types
+* net/octeontx2: fix PTP
+* net/octeontx2: fix PTP and HIGIG2 coexistence
+* net/octeontx2: fix Tx flow control for HIGIG
+* net/octeontx2: fix VF configuration
+* net/octeontx: fix memory leak of MAC address table
+* net/qede/base: fix number of ports per engine
+* net/qede: do not stop vport if not started
+* net/qede: fix VF reload
+* net/sfc: fix log format specifiers
+* net/tap: fix memory leak when unregister intr handler
+* net/vhost: allocate interface name from heap
+* net/vhost: check creation failure
+* net/vhost: delay driver setup
+* net/vhost: fix probing in secondary process
+* net/vhost: fix setup error path
+* net/vhost: prevent multiple setups on reconfiguration
+* net/virtio-user: check file descriptor before closing
+* net/virtio-user: check tap offload setting failure
+* net/virtio-user: do not close tap when disabling queue pairs
+* net/virtio-user: do not reset virtqueues for split ring
+* net/virtio-user: fix packed ring server mode
+* raw/ntb: fix write memory barrier
+* service: don't walk out of bounds when checking services
+* test/common: fix log2 check
+* test/compress: replace test vector
+* test/crypto: fix missing operation status check
+* test/event: fix OCTEON TX2 event device name
+* test/event: fix unintended vdev creation
+* test: fix build without ring PMD
+* test/ipsec: fix a typo in function name
+* usertools: fix syntax warning in python 3.8
+* usertools: fix telemetry client with python 3
+* vfio: fix mapping failures in ppc64le
+* vhost: catch overflow causing mmap of size 0
+* vhost: check message header size read
+* vhost/crypto: fix fetch size
+* vhost: do not treat empty socket message as error
+* vhost: fix crash on port deletion
+* vhost: fix deadlock on port deletion
+* vhost: fix inflight resubmit check
+* vhost: fix packed virtqueue ready condition
+* vhost: fix socket initial value
+* vhost: flush shadow Tx if no more packets
+* vhost: protect log address translation in IOTLB update
+
+19.11.1 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Red Hat(R) Testing
+
+   * Platform
+
+      * RHEL 8
+      * Kernel 4.18
+      * Qemu 4.2
+      * X540-AT2 NIC(ixgbe, 10G)
+
+   * Functionality
+
+      * Guest with device assignment(PF) throughput testing(1G hugepage size)
+      * Guest with device assignment(PF) throughput testing(2M hugepage size)
+      * Guest with device assignment(VF) throughput testing
+      * PVP (host dpdk testpmd as vswitch) 1Q: throughput testing
+      * PVP vhost-user 2Q throughput testing
+      * PVP vhost-user 1Q - cross numa node  throughput testing
+      * Guest with vhost-user 2 queues throughput testing
+      * vhost-user reconnect with dpdk-client, qemu-server: qemu reconnect
+      * PVP 1Q live migration testing
+      * PVP 1Q cross numa node live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing (2M)
+      * Guest with ovs+dpdk+vhost-user 2Q live migration testing
+
+* Intel(R) Testing
+
+   * Basic Intel(R) NIC(ixgbe, i40e and ice) testing
+      * PF (i40e)
+      * PF (ixgbe)
+      * PF (ice)
+      * VF
+      * Compile Testing
+      * Intel NIC single core/NIC performance
+
+   * Basic cryptodev and virtio testing
+
+      * cryptodev
+      * vhost/virtio basic loopback, PVP and performance test
+
+* Mellanox(R) Testing
+
+   * Basic functionality with testpmd
+
+      * Tx/Rx
+      * xstats
+      * Timestamps
+      * Link status
+      * RTE flow and flow_director
+      * RSS
+      * VLAN stripping and insertion
+      * Checksum/TSO
+      * ptype
+      * l3fwd-power example application
+      * Multi-process example applications
+
+   * ConnectX-5
+
+      * RHEL 7.4
+      * Kernel 3.10.0-693.el7.x86_64
+      * Driver MLNX_OFED_LINUX-5.0-1.0.0.0
+      * fw 16.27.1016
+
+   * ConnectX-4 Lx
+
+      * RHEL 7.4
+      * Kernel 3.10.0-693.el7.x86_64
+      * Driver MLNX_OFED_LINUX-5.0-1.0.0.0
+      * fw 14.27.1016
+
+* Broadcom(R) Testing
+
+   * Functionality
+
+      * Tx/Rx
+      * Link status
+      * RSS
+      * Checksum/TSO
+      * VLAN filtering
+      * statistics
+      * MTU
+
+   * Platform
+
+      * BCM57414 NetXtreme-E 10Gb/25Gb Ethernet Controller, Firmware: 216.1.169.0
+      * BCM57508 NetXtreme-E 10Gb/25Gb/40Gb/50Gb/100Gb/200Gb Ethernet, Firmware : 216.0.314.0
+
+* IBM(R) Testing
+
+   * Functionality
+
+      * Basic PF on Mellanox
+      * Single port stability test using l3fwd (16 cpus) and TRex, tested 64
+        and 1500 byte packets at a 0.0% drop rate for 4 hours each
+      * Performance: no degradation compared to 19.11.0
+
+   * Platform
+
+      * Ubuntu 18.04.4 LTS
+      * Kernel 4.15.0-88-generic
+      * IBM Power9 Model 8335-101 CPU: 2.3 (pvr 004e 1203)
+      * Mellanox Technologies MT28800 Family [ConnectX-5 Ex], firmware version: 16.26.4012, MLNX_OFED_LINUX-4.7-3.2.9.1
+
+19.11.2 Release Notes
+---------------------
+
+19.11.2 Fixes
+~~~~~~~~~~~~~
+
+* 2cf9c470eb vhost: check log mmap offset and size overflow (CVE-2020-10722)
+* 8e9652b0b6 vhost: fix translated address not checked (CVE-2020-10723)
+* 95e1f29c26 vhost/crypto: validate keys lengths (CVE-2020-10724)
+* 963b6eea05 vhost: fix potential memory space leak (CVE-2020-10725)
+* c9c630a117 vhost: fix potential fd leak (CVE-2020-10726)
+* cd0ea71bb6 vhost: fix vring index check (CVE-2020-10726)
+
+19.11.2 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Red Hat(R) Testing
+
+   * Platform
+
+      * RHEL 8.3
+      * Kernel 4.18
+      * Qemu 4.2
+      * X540-AT2 NIC(ixgbe, 10G)
+
+   * Functionality
+
+      * PVP (host dpdk testpmd as vswitch) 1Q: throughput testing
+      * PVP vhost-user 2Q throughput testing
+      * PVP vhost-user 1Q - cross numa node  throughput testing
+      * PVP 1Q live migration testing
+      * PVP 1Q cross numa node live migration testing
+
+* Intel(R) Testing
+
+   * Virtio features
+
+      * vhost/virtio loopback test with virtio user as server mode
+      * loopback multi queues
+      * loopback multi paths port restart
+      * vhost/virtio pvp multi-paths performance
+      * pvp multi-queues and port restart
+      * vhost dequeue zero copy
+      * pvp share lib
+      * pvp vhost user reconnect
+      * pvp test with 4k pages
+      * pvp test with 2M hugepages
+      * pvp virtio bonding
+      * pvp test with diff qemu version
+      * vhost enqueue interrupt
+      * vhost event idx interrupt
+      * vhost virtio pmd interrupt
+      * vhost virtio user interrupt
+      * virtio event idx interrupt
+      * virtio user for container networking
+      * virtio user as exceptional path
+      * vhost xstats
+      * virtio-pmd multi-process
+      * vm2vm virtio pmd
+      * vm2vm virtio-net iperf
+      * vm2vm virtio-user
+      * vhost user live migration
+
+19.11.3 Release Notes
+---------------------
+
+19.11.3 Fixes
+~~~~~~~~~~~~~
+
+* app/crypto-perf: fix display of sample test vector
+* app/eventdev: check Tx adapter service ID
+* app: fix usage help of options separated by dashes
+* app/pipeline: fix build with gcc 10
+* app: remove extra new line after link duplex
+* app/testpmd: add parsing for QinQ VLAN headers
+* app/testpmd: fix DCB set
+* app/testpmd: fix memory failure handling for i40e DDP
+* app/testpmd: fix PPPoE flow command
+* app/testpmd: fix statistics after reset
+* baseband/turbo_sw: fix exposed LLR decimals assumption
+* bbdev: fix doxygen comments
+* build: disable gcc 10 zero-length-bounds warning
+* build: fix linker warnings with clang on Windows
+* build: support MinGW-w64 with Meson
+* buildtools: get static mlx dependencies for meson
+* bus/fslmc: fix dereferencing null pointer
+* bus/fslmc: fix size of qman fq descriptor
+* bus/pci: fix devargs on probing again
+* bus/pci: fix UIO resource access from secondary process
+* bus/vmbus: fix comment spelling
+* ci: fix telemetry dependency in Travis
+* common/iavf: update copyright
+* common/mlx5: fix build with -fno-common
+* common/mlx5: fix build with rdma-core 21
+* common/mlx5: fix netlink buffer allocation from stack
+* common/mlx5: fix umem buffer alignment
+* common/octeontx: fix gcc 9.1 ABI break
+* common/qat: fix GEN3 marketing name
+* contigmem: cleanup properly when load fails
+* crypto/caam_jr: fix check of file descriptors
+* crypto/caam_jr: fix IRQ functions return type
+* crypto/ccp: fix fd leak on probe failure
+* cryptodev: add asymmetric session-less feature name
+* cryptodev: fix missing device id range checking
+* cryptodev: fix SHA-1 digest enum comment
+* crypto/kasumi: fix extern declaration
+* crypto/nitrox: fix CSR register address generation
+* crypto/nitrox: fix oversized device name
+* crypto/octeontx2: fix build with gcc 10
+* crypto/openssl: fix out-of-place encryption
+* crypto/qat: fix cipher descriptor for ZUC and SNOW
+* crypto/qat: support plain SHA1..SHA512 hashes
+* devtools: fix symbol map change check
+* doc: add i40e limitation for flow director
+* doc: add NASM installation steps
+* doc: fix API index
+* doc: fix build issue in ABI guide
+* doc: fix build with doxygen 1.8.18
+* doc: fix default symbol binding in ABI guide
+* doc: fix log level example in Linux guide
+* doc: fix LTO config option
+* doc: fix matrix CSS for recent sphinx
+* doc: fix multicast filter feature announcement
+* doc: fix number of failsafe sub-devices
+* doc: fix reference in ABI guide
+* doc: fix sphinx compatibility
+* doc: fix typo in contributors guide
+* doc: fix typo in contributors guide
+* doc: fix typos in ABI policy
+* doc: prefer https when pointing to dpdk.org
+* drivers: add crypto as dependency for event drivers
+* drivers/crypto: disable gcc 10 no-common errors
+* drivers/crypto: fix build with make 4.3
+* drivers/crypto: fix log type variables for -fno-common
+* drivers: fix log type variables for -fno-common
+* eal/arm64: fix precise TSC
+* eal: fix C++17 compilation
+* eal: fix comments spelling
+* eal: fix log message print for regex
+* eal: fix PRNG init with HPET enabled
+* eal: fix typo in endian conversion macros
+* eal/freebsd: fix queuing duplicate alarm callbacks
+* eal/ppc: fix bool type after altivec include
+* eal/ppc: fix build with gcc 9.3
+* eal/x86: ignore gcc 10 stringop-overflow warnings
+* ethdev: fix build when vtune profiling is on
+* ethdev: fix spelling
+* eventdev: fix probe and remove for secondary process
+* event/dsw: avoid reusing previously recorded events
+* event/dsw: fix enqueue burst return value
+* event/dsw: remove redundant control ring poll
+* event/dsw: remove unnecessary read barrier
+* event/octeontx2: fix build for O1 optimization
+* event/octeontx2: fix queue removal from Rx adapter
+* examples/eventdev: fix build with gcc 10
+* examples/eventdev: fix crash on exit
+* examples/fips_validation: fix parsing of algorithms
+* examples/ip_pipeline: remove check of null response
+* examples/ipsec-gw: fix gcc 10 maybe-uninitialized warning
+* examples/kni: fix crash during MTU set
+* examples/kni: fix MTU change to setup Tx queue
+* examples/l2fwd-keepalive: fix mbuf pool size
+* examples/qos_sched: fix build with gcc 10
+* examples: remove extra new line after link duplex
+* examples/vhost_blk: fix build with gcc 10
+* examples/vmdq: fix output of pools/queues
+* examples/vmdq: fix RSS configuration
+* examples/vm_power: drop Unix path limit redefinition
+* examples/vm_power: fix build with -fno-common
+* fib: fix headers for C++ support
+* fix same typo in multiple places
+* fix various typos found by Lintian
+* ipsec: check SAD lookup error
+* ipsec: fix build dependency on hash lib
+* kvargs: fix buffer overflow when parsing list
+* kvargs: fix invalid token parsing on FreeBSD
+* kvargs: fix strcmp helper documentation
+* log: fix level picked with globbing on type register
+* lpm6: fix comments spelling
+* lpm6: fix size of tbl8 group
+* mem: fix overflow on allocation
+* mem: mark pages as not accessed when freeing memory
+* mem: mark pages as not accessed when reserving VA
+* mempool/dpaa2: install missing header with meson
+* mempool/octeontx2: fix build for gcc O1 optimization
+* mempool: remove inline functions from export list
+* mem: preallocate VA space in no-huge mode
+* mk: fix static linkage of mlx dependency
+* net/avp: fix gcc 10 maybe-uninitialized warning
+* net/bnxt: do not use PMD log type
+* net/bnxt: fix error log for command timeout
+* net/bnxt: fix FW version query
+* net/bnxt: fix HWRM command during FW reset
+* net/bnxt: fix max ring count
+* net/bnxt: fix memory leak during queue restart
+* net/bnxt: fix number of TQM ring
+* net/bnxt: fix port start failure handling
+* net/bnxt: fix possible stack smashing
+* net/bnxt: fix Rx ring producer index
+* net/bnxt: fix storing MAC address twice
+* net/bnxt: fix TQM ring context memory size
+* net/bnxt: fix using RSS config struct
+* net/bnxt: fix VLAN add when port is stopped
+* net/bnxt: fix VNIC Rx queue count on VNIC free
+* net/bnxt: use true/false for bool types
+* net/dpaa2: fix 10G port negotiation
+* net/dpaa2: fix congestion ID for multiple traffic classes
+* net/dpaa: use dynamic log type
+* net/e1000: fix port hotplug for multi-process
+* net/ena/base: fix documentation of functions
+* net/ena/base: fix indentation in CQ polling
+* net/ena/base: fix indentation of multiple defines
+* net/ena/base: fix testing for supported hash function
+* net/ena/base: make allocation macros thread-safe
+* net/ena/base: prevent allocation of zero sized memory
+* net/ena: fix build for O1 optimization
+* net/ena: set IO ring size to valid value
+* net/enetc: fix Rx lock-up
+* net/enic: fix flow action reordering
+* net/failsafe: fix fd leak
+* net/hinic: allocate IO memory with socket id
+* net/hinic/base: fix PF firmware hot-active problem
+* net/hinic/base: fix port start during FW hot update
+* net/hinic: fix LRO
+* net/hinic: fix queues resource free
+* net/hinic: fix repeating cable log and length check
+* net/hinic: fix snprintf length of cable info
+* net/hinic: fix TSO
+* net/hinic: fix Tx mbuf length while copying
+* net/hns3: add free threshold in Rx
+* net/hns3: add RSS hash offload to capabilities
+* net/hns3: clear residual flow rules on init
+* net/hns3: fix configuring illegal VLAN PVID
+* net/hns3: fix configuring RSS hash when rules are flushed
+* net/hns3: fix crash when flushing RSS flow rules with FLR
+* net/hns3: fix default error code of command interface
+* net/hns3: fix default VLAN filter configuration for PF
+* net/hns3: fix mailbox opcode data type
+* net/hns3: fix MSI-X interrupt during initialization
+* net/hns3: fix packets offload features flags in Rx
+* net/hns3: fix promiscuous mode for PF
+* net/hns3: fix return value of setting VLAN offload
+* net/hns3: fix return value when clearing statistics
+* net/hns3: fix RSS indirection table configuration
+* net/hns3: fix RSS key length
+* net/hns3: fix Rx interrupt after reset
+* net/hns3: fix status after repeated resets
+* net/hns3: fix Tx interrupt when enabling Rx interrupt
+* net/hns3: fix VLAN filter when setting promisucous mode
+* net/hns3: fix VLAN PVID when configuring device
+* net/hns3: reduce judgements of free Tx ring space
+* net/hns3: remove one IO barrier in Rx
+* net/hns3: remove unnecessary assignments in Tx
+* net/hns3: replace memory barrier with data dependency order
+* net/hns3: support different numbers of Rx and Tx queues
+* net/hns3: support Rx interrupt
+* net/i40e/base: update copyright
+* net/i40e: fix flow director enabling
+* net/i40e: fix flow director for ARP packets
+* net/i40e: fix flow director initialisation
+* net/i40e: fix flush of flow director filter
+* net/i40e: fix queue region in RSS flow
+* net/i40e: fix queue related exception handling
+* net/i40e: fix setting L2TAG
+* net/i40e: fix wild pointer
+* net/i40e: fix X722 performance
+* net/i40e: relax barrier in Tx
+* net/i40e: relax barrier in Tx for NEON
+* net/iavf: fix link speed
+* net/iavf: fix setting L2TAG
+* net/iavf: fix stats query error code
+* net/ice: add action number check for switch
+* net/ice/base: check memory pointer before copying
+* net/ice/base: fix binary order for GTPU filter
+* net/ice/base: fix MAC write command
+* net/ice/base: fix uninitialized stack variables
+* net/ice/base: minor fixes
+* net/ice/base: read PSM clock frequency from register
+* net/ice/base: remove unused code in switch rule
+* net/ice/base: update copyright
+* net/ice: change default tunnel type
+* net/ice: fix crash in switch filter
+* net/ice: fix hash flow crash
+* net/ice: fix input set of VLAN item
+* net/ice: fix RSS advanced rule
+* net/ice: fix RSS for GTPU
+* net/ice: fix setting L2TAG
+* net/ice: fix variable initialization
+* net/ice: remove bulk alloc option
+* net/ice: remove unnecessary variable
+* net/ice: support mark only action for flow director
+* net/ipn3ke: use control thread to check link status
+* net/ixgbe/base: update copyright
+* net/ixgbe: check driver type in MACsec API
+* net/ixgbe: fix link state timing on fiber ports
+* net/ixgbe: fix link status after port reset
+* net/ixgbe: fix link status inconsistencies
+* net/ixgbe: fix link status synchronization on BSD
+* net/ixgbe: fix resource leak after thread exits normally
+* net/ixgbe: fix statistics in flow control mode
+* net/memif: fix init when already connected
+* net/memif: fix resource leak
+* net/mlx4: fix build with -fno-common
+* net/mlx4: fix drop queue error handling
+* net/mlx5: add device parameter for MPRQ stride size
+* net/mlx5: add multi-segment packets in MPRQ mode
+* net/mlx5: enable MPRQ multi-stride operations
+* net/mlx5: fix actions validation on root table
+* net/mlx5: fix assert in doorbell lookup
+* net/mlx5: fix assert in dynamic metadata handling
+* net/mlx5: fix assert in modify converting
+* net/mlx5: fix build with separate glue lib for dlopen
+* net/mlx5: fix call to modify action without init item
+* net/mlx5: fix counter container usage
+* net/mlx5: fix crash when releasing meter table
+* net/mlx5: fix CVLAN tag set in IP item translation
+* net/mlx5: fix doorbell bitmap management offsets
+* net/mlx5: fix gcc 10 enum-conversion warning
+* net/mlx5: fix header modify action validation
+* net/mlx5: fix imissed counter overflow
+* net/mlx5: fix jump table leak
+* net/mlx5: fix mask used for IPv6 item validation
+* net/mlx5: fix matching for UDP tunnels with Verbs
+* net/mlx5: fix match on empty VLAN item in DV mode
+* net/mlx5: fix metadata for compressed Rx CQEs
+* net/mlx5: fix meter color register consideration
+* net/mlx5: fix meter suffix table leak
+* net/mlx5: fix packet length assert in MPRQ
+* net/mlx5: fix push VLAN action to use item info
+* net/mlx5: fix RSS enablement
+* net/mlx5: fix RSS key copy to TIR context
+* net/mlx5: fix Tx queue release debug log timing
+* net/mlx5: fix validation of push VLAN without full mask
+* net/mlx5: fix validation of VXLAN/VXLAN-GPE specs
+* net/mlx5: fix VLAN flow action with wildcard VLAN item
+* net/mlx5: fix VLAN ID check
+* net/mlx5: fix VLAN PCP item calculation
+* net/mlx5: fix zero metadata action
+* net/mlx5: fix zero value validation for metadata
+* net/mlx5: improve logging of MPRQ selection
+* net/mlx5: reduce Tx completion index memory loads
+* net/mlx5: set dynamic flow metadata in Rx queues
+* net/mlx5: update VLAN and encap actions validation
+* net/mlx5: use open/read/close for ib stats query
+* net/mvneta: do not use PMD log type
+* net/mvpp2: fix build with gcc 10
+* net/netvsc: avoid possible live lock
+* net/netvsc: do not configure RSS if disabled
+* net/netvsc: do RSS across Rx queue only
+* net/netvsc: fix comment spelling
+* net/netvsc: fix memory free on device close
+* net/netvsc: handle Rx packets during multi-channel setup
+* net/netvsc: handle Tx completions based on burst size
+* net/netvsc: propagate descriptor limits from VF
+* net/netvsc: remove process event optimization
+* net/netvsc: split send buffers from Tx descriptors
+* net/nfp: fix dangling pointer on probe failure
+* net/nfp: fix log format specifiers
+* net/null: fix secondary burst function selection
+* net/null: remove redundant check
+* net/octeontx2: disable unnecessary error interrupts
+* net/octeontx2: enable error and RAS interrupt in configure
+* net/octeontx2: fix buffer size assignment
+* net/octeontx2: fix device configuration sequence
+* net/octeontx2: fix link information for loopback port
+* net/octeontx: fix dangling pointer on init failure
+* net/octeontx: fix meson build for disabled drivers
+* net/pfe: do not use PMD log type
+* net/pfe: fix double free of MAC address
+* net/qede: fix link state configuration
+* net/qede: fix port reconfiguration
+* net/ring: fix device pointer on allocation
+* net/sfc/base: fix build when EVB is enabled
+* net/sfc/base: fix manual filter delete in EF10
+* net/sfc/base: handle manual and auto filter clashes in EF10
+* net/sfc/base: reduce filter priorities to implemented only
+* net/sfc/base: refactor filter lookup loop in EF10
+* net/sfc/base: reject automatic filter creation by users
+* net/sfc/base: use simpler EF10 family conditional check
+* net/sfc/base: use simpler EF10 family run-time checks
+* net/sfc: fix initialization error path
+* net/sfc: fix promiscuous and allmulticast toggles errors
+* net/sfc: fix reported promiscuous/multicast mode
+* net/sfc: fix Rx queue start failure path
+* net/sfc: set priority of created filters to manual
+* net/softnic: fix memory leak for thread
+* net/softnic: fix resource leak for pipeline
+* net/tap: do not use PMD log type
+* net/tap: fix check for mbuf number of segment
+* net/tap: fix crash in flow destroy
+* net/tap: fix fd leak on creation failure
+* net/tap: fix file close on remove
+* net/tap: fix mbuf and mem leak during queue release
+* net/tap: fix mbuf double free when writev fails
+* net/tap: fix queues fd check before close
+* net/tap: fix unexpected link handler
+* net/tap: remove unused assert
+* net/thunderx: use dynamic log type
+* net/vhost: fix potential memory leak on close
+* net/virtio: do not use PMD log type
+* net/virtio: fix crash when device reconnecting
+* net/virtio: fix outdated comment
+* net/virtio: fix unexpected event after reconnect
+* net/virtio-user: fix devargs parsing
+* net/vmxnet3: fix RSS setting on v4
+* net/vmxnet3: handle bad host framing
+* pci: accept 32-bit domain numbers
+* pci: fix build on FreeBSD
+* pci: fix build on ppc
+* pci: reject negative values in PCI id
+* pci: remove unneeded includes in public header file
+* remove references to private PCI probe function
+* Revert "common/qat: fix GEN3 marketing name"
+* Revert "net/bnxt: fix number of TQM ring"
+* Revert "net/bnxt: fix TQM ring context memory size"
+* security: fix crash at accessing non-implemented ops
+* security: fix return types in documentation
+* security: fix session counter
+* security: fix verification of parameters
+* service: fix crash on exit
+* service: fix identification of service running on other lcore
+* service: fix race condition for MT unsafe service
+* service: remove rte prefix from static functions
+* telemetry: fix port stats retrieval
+* test/crypto: fix flag check
+* test/crypto: fix statistics case
+* test: fix build with gcc 10
+* test/flow_classify: enable multi-sockets system
+* test/ipsec: fix crash in session destroy
+* test/kvargs: fix invalid cases check
+* test/kvargs: fix to consider empty elements as valid
+* test: load drivers when required
+* test: remove redundant macro
+* test: skip some subtests in no-huge mode
+* timer: protect initialization with lock
+* usertools: check for pci.ids in /usr/share/misc
+* vfio: fix race condition with sysfs
+* vfio: fix use after free with multiprocess
+* vhost/crypto: add missing user protocol flag
+* vhost: fix packed ring zero-copy
+* vhost: fix peer close check
+* vhost: fix shadowed descriptors not flushed
+* vhost: fix shadow update
+* vhost: fix zero-copy server mode
+* vhost: handle mbuf allocation failure
+* vhost: make IOTLB cache name unique among processes
+* vhost: prevent zero-copy with incompatible client mode
+* vhost: remove unused variable
+
+19.11.3 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Intel(R) Testing
+
+   * Basic Intel(R) NIC(ixgbe, i40e and ice) testing
+      * PF (i40e)
+      * PF (ixgbe)
+      * PF (ice)
+      * VF (i40e)
+      * VF (ixgbe)
+      * VF (ice)
+      * Compile Testing
+      * Intel NIC single core/NIC performance
+
+   * Basic cryptodev and virtio testing
+
+      * vhost/virtio basic loopback, PVP and performance test
+      * cryptodev Function/Performance
+
+* Mellanox(R) Testing
+
+   * Basic functionality with testpmd
+
+      * Tx/Rx
+      * xstats
+      * Timestamps
+      * Link status
+      * RTE flow and flow_director
+      * RSS
+      * VLAN stripping and insertion
+      * Checksum/TSO
+      * ptype
+      * l3fwd-power example application
+      * Multi-process example applications
+
+   * ConnectX-5
+
+      * RHEL 7.4
+      * Driver MLNX_OFED_LINUX-5.0-2.1.8.0
+      * fw 16.27.2008
+
+   * ConnectX-4 Lx
+
+      * RHEL 7.4
+      * Driver MLNX_OFED_LINUX-5.0-2.1.8.0
+      * fw 14.27.1016
+
+* Red Hat(R) Testing
+
+   * Platform
+
+      * RHEL 8
+      * Kernel 4.18
+      * Qemu 4.2
+      * X540-AT2 NIC(ixgbe, 10G)
+
+   * Functionality
+
+      * Guest with device assignment(PF) throughput testing(1G hugepage size)
+      * Guest with device assignment(PF) throughput testing(2M hugepage size)
+      * Guest with device assignment(VF) throughput testing
+      * PVP (host dpdk testpmd as vswitch) 1Q: throughput testing
+      * PVP vhost-user 2Q throughput testing
+      * PVP vhost-user 1Q - cross numa node  throughput testing
+      * Guest with vhost-user 2 queues throughput testing
+      * vhost-user reconnect with dpdk-client, qemu-server: qemu reconnect
+      * PVP 1Q live migration testing
+      * PVP 1Q cross numa node live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing (2M)
+      * Guest with ovs+dpdk+vhost-user 2Q live migration testing
+      * Allocate memory from the NUMA node which Virtio device locates
+
+
+* Intel(R) Testing with Open vSwitch
+
+   * OVS testing with OVS branches master and 2.13 with VSPERF
+
+   * Tested NICs
+
+      * i40e (X710)
+      * ixgbe (82599ES)
+      * ice
+      * vhost
+
+   * Functionality
+
+      * P2P
+      * PVP
+      * PVPV
+      * PVVP
+      * Multiqueue RSS
+      * Vhost reconnect
+      * Jumbo frames 1500, 6000, 9702
+
+
+* Microsoft(R) Testing
+
+   * Platform
+
+      * Azure
+         * Ubuntu 16.04-LTS
+         * Ubuntu 18.04-DAILY-LTS
+         * RHEL 7-RAW
+         * RHEL 7.5
+         * CentOS 7.5
+         * SLES-15-sp1 gen1
+      * Mellanox(R) ConnectX-4
+      * LISAv2 test framework
+
+   * Functionality
+
+      * VERIFY-DPDK-COMPLIANCE - verifies kernel is supported and that the build is successful
+      * VERIFY-DPDK-BUILD-AND-TESTPMD-TEST - verifies using testpmd that packets can be sent from a VM to another VM
+      * VERIFY-SRIOV-FAILSAFE-FOR-DPDK - disables/enables Accelerated Networking for the NICs under test and makes sure DPDK works in both scenarios
+      * VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC - disables/enables Accelerated Networking for the NICs while generating traffic using testpmd
+      * PERF-DPDK-FWD-PPS-DS15 - verifies DPDK forwarding performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-SINGLE-CORE-PPS-DS4 - verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS4_v2
+      * PERF-DPDK-SINGLE-CORE-PPS-DS15 - verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-MULTICORE-PPS-DS15 - verifies DPDK performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-MULTICORE-PPS-F32 - verifies DPDK performance using testpmd on 2, 4, 8, 16 cores, rx and io mode on size Standard_F32s_v2
+      * DPDK-RING-LATENCY - verifies DPDK CPU latency using dpdk-ring-ping
+      * VERIFY-DPDK-PRIMARY-SECONDARY-PROCESSES - verifies primary / secondary processes support for DPDK. Runs only on RHEL and Ubuntu distros with Linux kernel >= 4.20
+      * VERIFY-DPDK-OVS - builds OVS with DPDK support and tests if the OVS DPDK ports can be created. Runs only on Ubuntu distro.
+
+19.11.4 Release Notes
+---------------------
+
+19.11.4 Fixes
+~~~~~~~~~~~~~
+
+* app/eventdev: fix capability check in pipeline ATQ test
+* app/testpmd: fix burst percentage calculation
+* app/testpmd: fix CPU cycles per packet stats on Tx modes
+* app/testpmd: fix error detection in MTU command
+* app/testpmd: fix memory leak on error path
+* app/testpmd: fix stats error message
+* app/testpmd: remove hardcoded descriptors limit
+* app/testpmd: use clock time in throughput calculation
+* avoid libfdt checks adding full paths to pkg-config
+* bpf: fix add/sub min/max estimations
+* build: fix drivers library path on Windows
+* bus/dpaa: fix iterating on a class type
+* bus/fslmc: fix getting FD error
+* bus/fslmc: fix iterating on a class type
+* bus/fslmc: fix memory leak in secondary process
+* bus/pci: fix VF memory access
+* bus/vdev: fix a typo in doxygen comment
+* bus/vmbus: fix ring buffer mapping
+* cfgfile: fix stack buffer underflow
+* common/cpt: fix encryption offset
+* common/dpaax: fix 12-bit null auth case
+* common/mlx5: fix code arrangement in tag allocation
+* common/mlx5: fix queue doorbell record size
+* common/mlx5: fix void parameters in glue wrappers
+* common/octeontx2: fix crash on running procinfo
+* common/qat: fix uninitialized variable
+* common/qat: get firmware version
+* common/qat: move max inflights param into qp
+* common/qat: remove tail write coalescing
+* common/qat: support dual threads for enqueue/dequeue
+* crypto/armv8: remove debug option
+* crypto/armv8: use dedicated log type
+* crypto/dpaa2_sec: fix HFN override
+* crypto/dpaax_sec: fix 18-bit PDCP cases with HFN override
+* crypto/dpaax_sec: fix inline query for descriptors
+* crypto/qat: add minimum enq threshold
+* crypto/qat: fix AES-XTS capabilities
+* crypto/qat: handle mixed hash-cipher on GEN2
+* crypto/qat: handle mixed hash-cipher requests on GEN3
+* devtools: fix path in forbidden token check
+* doc: add RIB and FIB into the API index
+* doc: fix a typo in mlx5 guide
+* doc: fix doc build after qat threshold patch
+* doc: fix ethtool app path
+* doc: fix reference to master process
+* doc: fix some typos in Linux guide
+* doc: fix typo in bbdev test guide
+* doc: rebuild with meson whenever a file changes
+* doc: update build instructions in the Linux guide
+* drivers/crypto: add missing OOP feature flag
+* drivers/net: fix exposing internal headers
+* drivers/qat: add handling of capabilities in multi process
+* drivers/qat: add multi process handling of driver id
+* drivers/qat: improve multi process on qat
+* eal/arm: add vcopyq intrinsic for aarch32
+* eal/armv8: fix timer frequency calibration with PMU
+* eal: fix lcore accessors for non-EAL threads
+* eal: fix parentheses in alignment macros
+* eal: fix uuid header dependencies
+* eal/linux: fix epoll fd list rebuild for interrupts
+* eal: remove redundant newline in alert message
+* eal/windows: fix symbol export
+* ethdev: fix data room size verification in Rx queue setup
+* ethdev: fix log type for some error messages
+* ethdev: fix VLAN offloads set if no relative capabilities
+* eventdev: fix race condition on timer list counter
+* eventdev: relax SMP barriers with C11 atomics
+* eventdev: remove redundant reset on timer cancel
+* eventdev: use C11 atomics for lcore timer armed flag
+* event/dpaa2: add all-types queue capability flag
+* event/dpaa: remove dead code
+* event/octeontx2: fix device reconfigure
+* event/octeontx2: fix sub event type
+* examples: add flush after stats printing
+* examples/eventdev: fix 32-bit coremask
+* examples/fips_validation: fix count overwrite for TDES
+* examples/fips_validation: fix parsing of TDES vectors
+* examples/fips_validation: fix TDES interim callback
+* examples/packet_ordering: use proper exit method
+* hash: fix out-of-memory handling in hash creation
+* kni: fix reference to master/slave process
+* lib: remind experimental status in headers
+* mbuf: fix boundary check at dynamic field registration
+* mbuf: fix dynamic field dump log
+* mbuf: fix error code in dynamic field/flag registration
+* mbuf: fix free space update for dynamic field
+* mbuf: remove unused next member in dynamic flag/field
+* mem: fix 32-bit init config with meson
+* mempool: fix allocation in memzone during retry
+* meter: remove inline functions from export list
+* net/af_packet: fix check of file descriptors
+* net/af_packet: fix memory leak on init failure
+* net/af_packet: fix munmap on init failure
+* net/af_xdp: remove mempool freeing on umem destruction
+* net/bnxt: fix flow error on filter creation
+* net/bnxt: fix freeing filters on flow creation failure
+* net/bnxt: fix logical AND in if condition
+* net/bnxt: fix performance for Arm
+* net/bnxt: fix unnecessary HWRM command
+* net/bnxt: remove unused enum declaration
+* net/bonding: change state machine to defaulted
+* net/bonding: delete redundant code
+* net/bonding: fix dead loop on RSS RETA update
+* net/bonding: fix error code on device creation
+* net/bonding: fix LACP negotiation
+* net/bonding: fix MAC address when one port resets
+* net/bonding: fix MAC address when switching active port
+* net/bonding: fix socket ID check
+* net/cxgbe: fix CLIP leak in filter error path
+* net/cxgbe: fix double MPS alloc by flow validate and create
+* net/cxgbe: fix L2T leak in filter error and free path
+* net/dpaa: fix FD offset data type
+* net/e1000: fix crash on Tx done clean up
+* net/e1000: report VLAN extend capability
+* net/failsafe: fix RSS RETA size info
+* net: fix checksum on big endian CPUs
+* net: fix IPv4 checksum
+* net: fix pedantic build
+* net: fix unneeded replacement of TCP checksum 0
+* net/hinic/base: avoid system time jump
+* net/hinic/base: check output of management sync channel
+* net/hinic/base: remove unused function parameters
+* net/hinic: check memory allocations in flow creation
+* net/hinic: fix setting promiscuous mode
+* net/hinic: optimize Rx performance for x86
+* net/hns3: add RSS hash offload to Rx configuration
+* net/hns3: check multi-process action register result
+* net/hns3: clear promiscuous on PF uninit
+* net/hns3: clear residual hardware configurations on init
+* net/hns3: fix adding multicast MAC address
+* net/hns3: fix flow director error message
+* net/hns3: fix key length when configuring RSS
+* net/hns3: fix RSS configuration on empty RSS type
+* net/hns3: fix Rx buffer size
+* net/hns3: fix Tx less than 60 bytes
+* net/hns3: fix unintended sign extension in dump operation
+* net/hns3: fix unintended sign extension in fd operation
+* net/hns3: fix VLAN strip configuration when setting PVID
+* net/hns3: fix VLAN tags reported in Rx
+* net/hns3: get link status change through mailbox
+* net/hns3: ignore function return on reset error path
+* net/hns3: optimize default RSS algorithm
+* net/hns3: remove restriction on setting VF MTU
+* net/hns3: remove unnecessary branch
+* net/hns3: remove unsupported VLAN capabilities
+* net/i40e: enable NEON Rx/Tx in meson
+* net/i40e: enable QinQ stripping
+* net/i40e: fix binding interrupt without MSI-X vector
+* net/i40e: fix filter pctype
+* net/i40e: fix flow director MSI-X resource allocation
+* net/i40e: fix flow director Rx writeback packet
+* net/i40e: fix getting EEPROM information
+* net/i40e: fix queue pairs configuration in VF
+* net/i40e: remove duplicate tunnel type check
+* net/i40e: report VLAN filter capability
+* net/i40e: support aarch32
+* net/iavf: fix RSS RETA after restart
+* net/iavf: fix uninitialized variable
+* net/ice: add input set byte number check
+* net/ice: add memory allocation check in RSS init
+* net/ice/base: fix GTP-U inner RSS IPv4 IPv6 co-exist
+* net/ice/base: fix initializing resource for field vector
+* net/ice/base: fix memory leak on error path
+* net/ice/base: fix memory leak on GTPU RSS
+* net/ice/base: fix reference count on VSI list update
+* net/ice/base: fix return value
+* net/ice/base: fix RSS interference
+* net/ice/base: fix RSS removal for GTP-U
+* net/ice/base: fix VSI ID mask to 10 bits
+* net/ice: calculate TCP header size for offload
+* net/ice: fix bytes statistics
+* net/ice: fix error log in generic flow
+* net/ice: fix memory leak when releasing VSI
+* net/ice: fix switch action number check
+* net/ice: fix TCP checksum offload
+* net/ice: fix Tx hang with TSO
+* net/ice: revert fake TSO fixes
+* net/ixgbe/base: fix host interface shadow RAM read
+* net/ixgbe/base: fix infinite recursion on PCIe link down
+* net/ixgbe/base: fix x550em 10G NIC link status
+* net/ixgbe/base: remove dead code
+* net/ixgbe: fix flow control status
+* net/ixgbe: fix include of vector header file
+* net/ixgbe: fix MAC control frame forward
+* net/ixgbe: report 10Mbps link speed for x553
+* net/kni: set packet input port in Rx
+* net/mlx4: optimize stack memory size in probe
+* net/mlx5: do not select legacy MPW implicitly
+* net/mlx5: fix counter query
+* net/mlx5: fix crash in NVGRE item translation
+* net/mlx5: fix descriptors number adjustment
+* net/mlx5: fix flow items size calculation
+* net/mlx5: fix flow META item validation
+* net/mlx5: fix hairpin Rx queue creation error flow
+* net/mlx5: fix hairpin Tx queue creation error flow
+* net/mlx5: fix HW counters path in switchdev mode
+* net/mlx5: fix initialization of steering registers
+* net/mlx5: fix interrupt installation timing
+* net/mlx5: fix iterator type in Rx queue management
+* net/mlx5: fix LRO checksum
+* net/mlx5: fix metadata storing for NEON Rx
+* net/mlx5: fix secondary process resources release
+* net/mlx5: fix tunnel flow priority
+* net/mlx5: fix typos in meter error messages
+* net/mlx5: fix UAR lock sharing for multiport devices
+* net/mlx5: fix unnecessary init in mark conversion
+* net/mlx5: fix unreachable MPLS error path
+* net/mlx5: fix vectorized Rx burst termination
+* net/mlx5: fix VF MAC address set over BlueField
+* net/mlx5: fix VLAN pop with decap action validation
+* net/mlx5: fix VLAN push action on hairpin queue
+* net/mlx5: remove ineffective increment in hairpin split
+* net/mlx5: remove needless Tx queue initialization check
+* net/mlx5: remove redundant newline from logs
+* net/mvpp2: fix non-EAL thread support
+* net/netvsc: do not query VF link state
+* net/netvsc: do not spin forever waiting for reply
+* net/netvsc: fix chimney index
+* net/netvsc: fix crash during Tx
+* net/netvsc: fix underflow when Rx external mbuf
+* net/netvsc: fix warning when VF is removed
+* net/nfp: fix RSS hash configuration reporting
+* net/octeontx2: fix DMAC filtering
+* net/qede: fix multicast drop in promiscuous mode
+* net/qede: remove dead code
+* net/sfc: do not enforce hash offload in RSS multi-queue
+* net/virtio-user: check tap system call setting
+* net/virtio-user: fix status management
+* pci: fix address domain format size
+* rawdev: allow getting info for unknown device
+* rawdev: export dump function in map file
+* rawdev: fill NUMA socket ID in info
+* rawdev: remove remaining experimental tags
+* raw/ifpga/base: fix NIOS SPI init
+* raw/ifpga/base: fix SPI transaction
+* rib: add C++ include guard
+* sched: fix 64-bit rate
+* sched: fix port time rounding
+* sched: fix subport freeing
+* service: fix C++ linkage
+* service: fix core mapping reset
+* service: fix lcore iteration
+* test: allow no-huge mode for fast-tests
+* test/bpf: fix few small issues
+* test/crypto: add mixed encypted-digest
+* test/crypto: change cipher offset for ESN vector
+* test/crypto: fix asymmetric session mempool creation
+* test/cycles: restore default delay callback
+* test: fix build with ring PMD but no bond PMD
+* test: fix rpath for drivers with meson
+* test/hash: move lock-free tests to perf tests
+* test/mbuf: fix a dynamic flag log
+* test/ring: fix statistics in bulk enq/dequeue
+* version: 19.11.4-rc1
+* vfio: map contiguous areas in one go
+* vfio: remove unused variable
+* vhost: fix double-free with zero-copy
+* vhost: fix features definition location
+* vhost: fix virtio ready flag check
+* vhost: remove zero-copy and client mode restriction
+
+19.11.4 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Canonical(R) Testing
+
+   * Build tests on all Ubuntu architectures
+   * OVS-DPDK tests on x86_64
+
+* Red Hat(R) Testing
+
+   * Platform
+
+      * RHEL 8
+      * Kernel 4.18
+      * Qemu 5.1
+      * X540-AT2 NIC(ixgbe, 10G)
+
+   * Functionality
+
+      * Guest with device assignment(PF) throughput testing(1G hugepage size)
+      * Guest with device assignment(PF) throughput testing(2M hugepage size)
+      * Guest with device assignment(VF) throughput testing
+      * PVP (host dpdk testpmd as vswitch) 1Q: throughput testing
+      * PVP vhost-user 2Q throughput testing
+      * PVP vhost-user 1Q - cross numa node  throughput testing
+      * Guest with vhost-user 2 queues throughput testing
+      * vhost-user reconnect with dpdk-client, qemu-server: qemu reconnect
+      * PVP 1Q live migration testing
+      * PVP 1Q cross numa node live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing (2M)
+      * Guest with ovs+dpdk+vhost-user 2Q live migration testing
+      * Allocate memory from the NUMA node which Virtio device locates
+      * Host PF + DPDK testing
+      * Host VF + DPDK testing
+
+* Intel(R) Testing
+
+   * Basic Intel(R) NIC(ixgbe, i40e and ice) testing
+      * PF (i40e)
+      * PF (ixgbe)
+      * PF (ice)
+      * VF (i40e)
+      * VF (ixgbe)
+      * VF (ice)
+      * Compile Testing
+      * Intel NIC single core/NIC performance
+
+   * Basic cryptodev and virtio testing
+
+      * vhost/virtio basic loopback, PVP and performance test
+      * cryptodev Function/Performance
+
+
+* Intel(R) Testing with Open vSwitch
+
+   * OVS testing with OVS branches master and 2.13 with VSPERF
+
+   * Tested NICs
+
+      * i40e (X710)
+      * ixgbe (82599ES)
+      * ice
+      * vhost user client
+
+   * Functionality
+
+      *  Performance tests
+      *  vHost zero-copy
+      *  Flow control
+      *  RSS
+      *  Partial HW offloading
+
+* Mellanox(R) Testing
+
+   * Basic functionality with testpmd
+
+      * Tx/Rx
+      * xstats
+      * Timestamps
+      * Link status
+      * RTE flow and flow_director
+      * RSS
+      * VLAN stripping and insertion
+      * Checksum/TSO
+      * ptype
+      * l3fwd-power example application
+      * Multi-process example applications
+
+   * ConnectX-5
+
+      * RHEL 7.4
+      * Driver MLNX_OFED_LINUX-5.1-0.6.6.0
+      * fw 16.28.1002
+
+   * ConnectX-4 Lx
+
+      * RHEL 7.4
+      * Driver MLNX_OFED_LINUX-5.1-0.6.6.0
+      * fw 14.28.1002
+
+
+* Microsoft(R) Testing
+
+   * Platform
+
+      * Azure
+         * Ubuntu 16.04-LTS
+         * Ubuntu 18.04-DAILY-LTS
+         * RHEL 7-RAW
+         * RHEL 7.5
+         * CentOS 7.5
+         * SLES-15-sp1 gen1
+      * Mellanox(R) ConnectX-4
+      * LISAv2 test framework
+
+   * Functionality
+
+      * VERIFY-DPDK-COMPLIANCE - verifies kernel is supported and that the build is successful
+      * VERIFY-DPDK-BUILD-AND-TESTPMD-TEST - verifies using testpmd that packets can be sent from a VM to another VM
+      * VERIFY-SRIOV-FAILSAFE-FOR-DPDK - disables/enables Accelerated Networking for the NICs under test and makes sure DPDK works in both scenarios
+      * VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC - disables/enables Accelerated Networking for the NICs while generating traffic using testpmd
+      * PERF-DPDK-FWD-PPS-DS15 - verifies DPDK forwarding performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-SINGLE-CORE-PPS-DS4 - verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS4_v2
+      * PERF-DPDK-SINGLE-CORE-PPS-DS15 - verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-MULTICORE-PPS-DS15 - verifies DPDK performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-MULTICORE-PPS-F32 - verifies DPDK performance using testpmd on 2, 4, 8, 16 cores, rx and io mode on size Standard_F32s_v2
+      * DPDK-RING-LATENCY - verifies DPDK CPU latency using dpdk-ring-ping
+      * VERIFY-DPDK-PRIMARY-SECONDARY-PROCESSES - verifies primary / secondary processes support for DPDK. Runs only on RHEL and Ubuntu distros with Linux kernel >= 4.20
+      * VERIFY-DPDK-OVS - builds OVS with DPDK support and tests if the OVS DPDK ports can be created. Runs only on Ubuntu distro.
+
+19.11.4 Known Issues
+~~~~~~~~~~~~~~~~~~~~
+
+* ICE
+
+   * Exception on VF port reset
+   * MD5 is not same between kernel ethtool and dpdk ethtool when testing
+     userspace_ethtool/retrieve_eeprom
+
+* vhost/virtio
+
+   * udp-fragmentation-offload cannot be setup on Ubuntu 19.10 VMs.
+     https://bugzilla.kernel.org/show_bug.cgi?id=207075
+   * l3fwd-power can wake up lcore, but then cannot sleep again
+
+* cryptodev
+
+   * fips_cryptodev test fails for TDES
+
+* vdev_netvsc
+
+   * hot-removal of VF driver can fail
+
+19.11.5 Release Notes
+---------------------
+
+19.11.5 Fixes
+~~~~~~~~~~~~~
+
+* vhost/crypto: fix data length check (CVE-2020-14374)
+* vhost/crypto: fix incorrect descriptor deduction (CVE-2020-14378)
+* vhost/crypto: fix incorrect write back source
+* vhost/crypto: fix missed request check for copy mode (CVE-2020-14376 CVE-2020-14377)
+* vhost/crypto: fix pool allocation
+* vhost/crypto: fix possible TOCTOU attack (CVE-2020-14375)
+
+19.11.5 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Intel(R) Testing
+
+   * Basic cryptodev testing
+
+      * vhost_crypto Unit test and Function/Performance test
+
+19.11.6 Release Notes
+---------------------
+
+19.11.6 Fixes
+~~~~~~~~~~~~~
+
+* acl: fix x86 build for compiler without AVX2
+* app/bbdev: fix test vector symlink
+* app/eventdev: check timer adadpters number
+* app: fix ethdev port id size
+* app: fix missing dependencies
+* app/testpmd: do not allow dynamic change of core number
+* app/testpmd: fix bonding xmit balance policy command
+* app/testpmd: fix build with gcc 11
+* app/testpmd: fix descriptor id check
+* app/testpmd: fix displaying Rx/Tx queues information
+* app/testpmd: fix max Rx packet length for VLAN packet
+* app/testpmd: fix MTU after device configure
+* app/testpmd: fix name of bitrate library in meson build
+* app/testpmd: fix packet header in txonly mode
+* app/testpmd: fix port id check in Tx VLAN command
+* app/testpmd: fix RSS key for flow API RSS rule
+* app/testpmd: fix VLAN configuration on failure
+* app/testpmd: remove restriction on Tx segments set
+* app/testpmd: revert max Rx packet length adjustment
+* app/testpmd: revert setting MTU explicitly after configure
+* app/test-sad: fix uninitialized variable
+* baseband/fpga_lte_fec: fix crash with debug
+* baseband/turbo_sw: fix memory leak in error path
+* build: fix gcc warning requiring Wformat
+* build: fix install on Windows
+* build: fix MS linker flag with meson 0.54
+* build: skip detecting libpcap via pcap-config
+* bus/dpaa: fix fd check before close
+* bus/dpaa: remove logically dead code
+* bus/fslmc: fix atomic queues on NXP LX2 platform
+* bus/fslmc: fix dpio close
+* bus/fslmc: fix VFIO group descriptor check
+* bus/pci: fix leak on VFIO mapping error
+* bus/pci: fix memory leak when unmapping VFIO resource
+* bus/pci: remove duplicate declaration
+* bus/pci: remove unused scan by address
+* common/mlx5: fix DevX SQ object creation
+* common/mlx5: fix name for ConnectX VF device ID
+* common/mlx5: fix PCI address lookup
+* common/qat: add missing kmod dependency info
+* compress/isal: check allocation in queue setup
+* config: add Graviton2(arm64) defconfig
+* config: enable packet prefetching with Meson
+* crypto/aesni_mb: fix CCM digest size check
+* crypto/aesni_mb: fix GCM digest size check
+* crypto/armv8: fix mempool object returning
+* crypto/caam_jr: fix device tree parsing for SEC_ERA
+* cryptodev: fix parameter parsing
+* crypto/dpaa2_sec: fix stats query without queue pair
+* crypto/dpaa2_sec: remove dead code
+* crypto/dpaa_sec: fix a null pointer dereference
+* crypto/octeontx2: fix multi-process
+* crypto/octeontx2: fix out-of-place support
+* crypto/octeontx2: fix session-less mode
+* crypto/octeontx: fix out-of-place support
+* crypto/scheduler: fix header install with meson
+* crypto/scheduler: remove unused internal seqn
+* devtools: fix build test config inheritance from env
+* devtools: fix directory filter in forbidden token check
+* devtools: fix x86-default build test install env
+* distributor: fix API documentation
+* distributor: fix buffer use after free
+* distributor: fix clearing returns buffer
+* distributor: fix flushing in flight packets
+* distributor: fix handshake deadlock
+* distributor: fix handshake synchronization
+* distributor: fix return pkt calls in single mode
+* distributor: fix scalar matching
+* distributor: handle worker shutdown in burst mode
+* doc: add SPDX license tag header to Intel performance guide
+* doc: add SPDX license tag header to meson guide
+* doc: clarify instructions on running as non-root
+* doc: fix diagram in dpaa2 guide
+* doc: fix EF10 Rx mode name in sfc guide
+* doc: fix ethdev port id size
+* doc: fix formatting of notes in meson guide
+* doc: fix grammar
+* doc: fix missing classify methods in ACL guide
+* doc: fix rule file parameters in l3fwd-acl guide
+* doc: fix typo in ipsec-secgw guide
+* doc: fix typo in KNI guide
+* doc: fix typo in pcap guide
+* doc: improve multiport PF in nfp guide
+* doc: remove notice about AES-GCM IV and J0
+* doc: remove obsolete deprecation notice for power library
+* doc: update information on using hugepages
+* drivers/net: fix port id size
+* eal/arm: fix build with gcc optimization level 0
+* eal/arm: fix clang build of native target
+* eal: fix doxygen for EAL cleanup
+* eal: fix leak on device event callback unregister
+* eal: fix MCS lock and ticketlock headers install
+* eal/linux: change udev debug message
+* eal/linux: fix memory leak in uevent handling
+* eal/x86: fix memcpy AVX-512 enablement
+* efd: fix tailq entry leak in error path
+* ethdev: fix data type for port id
+* ethdev: fix memory ordering for callback functions
+* ethdev: fix RSS flow expansion in case of mismatch
+* ethdev: move non-offload capabilities
+* ethdev: remove redundant license text
+* eventdev: check allocation in Tx adapter
+* eventdev: fix adapter leak in error path
+* event/dpaa2: fix dereference before null check
+* event/dpaa2: remove dead code from self test
+* event/octeontx2: unlink queues during port release
+* examples/fips_validation: fix buffer overflow
+* examples/fips_validation: fix build with pkg-config
+* examples/fips_validation: fix missed version line
+* examples/fips_validation: fix version compatibility
+* examples: fix flattening directory layout on install
+* examples/ioat: fix stats print
+* examples/ip_pipeline: fix external build
+* examples/ip_pipeline: use POSIX network address conversion
+* examples/ipsec-secgw: use POSIX network address conversion
+* examples/kni: fix build with pkg-config
+* examples/l2fwd-crypto: fix build with pkg-config
+* examples/l2fwd-crypto: fix missing dependency
+* examples/l2fwd-keepalive: skip meson build if no librt
+* examples/l3fwd-power: check packet types after start
+* examples/multi_process: fix build on Ubuntu 20.04
+* examples/ntb: fix clean target
+* examples/performance-thread: fix build with low core count
+* examples/performance-thread: fix build with pkg-config
+* examples/qos_sched: fix usage string
+* examples/rxtx_callbacks: fix build with pkg-config
+* examples/vhost_blk: check driver start failure
+* examples/vhost_blk: fix build with pkg-config
+* examples/vhost_crypto: add new line character in usage
+* examples/vm_power: fix 32-bit build
+* examples/vm_power: fix build on Ubuntu 20.04
+* fix spellings that Lintian complains about
+* gro: fix packet type detection with IPv6 tunnel
+* gso: fix payload unit size for UDP
+* ipc: fix spelling in log and comment
+* kni: fix build on RHEL 8.3
+* kni: fix build with Linux 5.9
+* license: add licenses for exception cases
+* maintainers: update Mellanox emails
+* malloc: fix style in free list index computation
+* mbuf: fix dynamic fields and flags with multiprocess
+* mbuf: fix typo in dynamic field convention note
+* mcslock: fix hang in weak memory model
+* mem: fix allocation failure on non-NUMA kernel
+* mem: fix allocation in container with SELinux
+* mem: fix config name in error logs
+* mempool/octeontx: fix aura to pool mapping
+* net/af_xdp: avoid deadlock due to empty fill queue
+* net/af_xdp: change return value from Rx to unsigned
+* net/af_xdp: fix pointer storage size
+* net/af_xdp: fix umem size
+* net/af_xdp: use strlcpy instead of strncpy
+* net/bnx2x: add QLogic vendor id for BCM57840
+* net/bnxt: add memory allocation check in VF info init
+* net/bnxt: add separate mutex for FW health check
+* net/bnxt: fix boolean operator usage
+* net/bnxt: fix checking VNIC in shutdown path
+* net/bnxt: fix crash in vector mode Tx
+* net/bnxt: fix doorbell barrier location
+* net/bnxt: fix drop enable in get Rx queue info
+* net/bnxt: fix endianness while setting L4 destination port
+* net/bnxt: fix L2 filter allocation
+* net/bnxt: fix link status during device recovery
+* net/bnxt: fix link update
+* net/bnxt: fix LRO configuration
+* net/bnxt: fix memory leak when freeing VF info
+* net/bnxt: fix queue get info
+* net/bnxt: fix queue release
+* net/bnxt: fix resetting mbuf data offset
+* net/bnxt: fix Rx performance by removing spinlock
+* net/bnxt: fix shift operation
+* net/bnxt: fix structure variable initialization
+* net/bnxt: fix vnic Rx queue cnt updation
+* net/bnxt: fix xstats by id
+* net/bnxt: increase size of Rx CQ
+* net/bnxt: remove useless prefetches
+* net/bonding: fix possible unbalanced packet receiving
+* net/bonding: fix Rx queue conversion
+* net: check segment pointer in raw checksum processing
+* net/cxgbe: fix crash when accessing empty Tx mbuf list
+* net/cxgbe: fix duplicate MAC addresses in MPS TCAM
+* net/cxgbe: fix queue DMA ring leaks during port close
+* net/dpaa2: fix build with timesync functions
+* net/dpaa2: fix misuse of interface index
+* net/dpaa: fix port ID type in API
+* net/ena/base: align IO CQ allocation to 4K
+* net/ena/base: fix release of wait event
+* net/ena/base: specify delay operations
+* net/ena/base: use min/max macros with type conversion
+* net/ena: fix getting xstats global stats offset
+* net/ena: fix setting Rx checksum flags in mbuf
+* net/ena: remove unused macro
+* net/enic: fix header sizes when copying flow patterns
+* net/enic: generate VXLAN src port if it is zero in template
+* net/enic: ignore VLAN inner type when it is zero
+* net/failsafe: fix double space in warning log
+* net/failsafe: fix state synchro cleanup
+* net/fm10k: fix memory leak when thresh check fails
+* net/fm10k: fix memory leak when Tx thresh check fails
+* net/fm10k: fix vector Rx
+* net/hinic/base: add message check for command channel
+* net/hinic/base: fix clock definition with glibc version
+* net/hinic/base: fix log info for PF command channel
+* net/hinic/base: get default cos from chip
+* net/hinic/base: remove queue number limitation
+* net/hinic/base: support two or more AEQS for chip
+* net/hinic: fix filters on memory allocation failure
+* net/hinic: fix negative array index read
+* net/hinic: fix Rx nombuf stats
+* net/hinic: remove optical module operation
+* net/hns3: check PCI config space reads
+* net/hns3: check PCI config space write
+* net/hns3: check setting VF PCI bus return value
+* net/hns3: decrease non-nearby memory access in Rx
+* net/hns3: fix configurations of port-level scheduling rate
+* net/hns3: fix configuring device with RSS enabled
+* net/hns3: fix config when creating RSS rule after flush
+* net/hns3: fix crash with multi-TC
+* net/hns3: fix data type to store queue number
+* net/hns3: fix default MAC address from firmware
+* net/hns3: fix deleting default VLAN from PF
+* net/hns3: fix error type when validating RSS flow action
+* net/hns3: fix flow error type
+* net/hns3: fix flow RSS queue number 0
+* net/hns3: fix flushing RSS rule
+* net/hns3: fix out of bounds access
+* net/hns3: fix queue offload capability
+* net/hns3: fix reassembling multiple segment packets in Tx
+* net/hns3: fix RSS max queue id allowed in multi-TC
+* net/hns3: fix some incomplete command structures
+* net/hns3: fix storing RSS info when creating flow action
+* net/hns3: fix TX checksum with fix header length
+* net/hns3: reduce address calculation in Rx
+* net/hns3: report Rx drop packets enable configuration
+* net/hns3: report Rx free threshold
+* net/hns3: skip VF register access when PF in FLR
+* net/i40e: add C++ include guard
+* net/i40e/base: fix function header arguments
+* net/i40e/base: fix Rx only for unicast promisc on VLAN
+* net/i40e: fix build for log format specifier
+* net/i40e: fix byte counters
+* net/i40e: fix flow director for eth + VLAN pattern
+* net/i40e: fix incorrect FDIR flex configuration
+* net/i40e: fix link status
+* net/i40e: fix QinQ flow pattern to allow non full mask
+* net/i40e: fix recreating flexible flow director rule
+* net/i40e: fix vector Rx
+* net/i40e: fix virtual channel conflict
+* net/iavf: downgrade error log
+* net/iavf: enable port reset
+* net/iavf: fix command after PF reset
+* net/iavf: fix flow flush after PF reset
+* net/iavf: fix iterator for RSS LUT
+* net/iavf: fix performance drop after port reset
+* net/iavf: fix port start during configuration restore
+* net/iavf: fix releasing mbufs
+* net/iavf: fix scattered Rx enabling
+* net/iavf: fix setting of MAC address
+* net/iavf: fix unchecked Tx cleanup error
+* net/iavf: fix vector Rx
+* net/iavf: support multicast configuration
+* net/ice/base: fix issues around move nodes
+* net/ice/base: fix parameter name in comment
+* net/ice: fix flow validation for unsupported patterns
+* net/ice: fix ptype parsing
+* net/ice: fix Rx offload flags in SSE path
+* net/ice: fix vector Rx
+* net/ice: update writeback policy to reduce latency
+* net/ixgbe: check switch domain allocation result
+* net/ixgbe: fix vector Rx
+* net/ixgbe: fix VF reset HW error handling
+* net/ixgbe: remove redundant MAC flag check
+* net/memif: do not update local copy of tail in Tx
+* net/memif: relax load of ring head for M2S ring
+* net/memif: relax load of ring head for S2M ring
+* net/memif: relax load of ring tail for M2S ring
+* net/mlx5: fix debug configuration build issue
+* net/mlx5: fix hairpin dependency on destination DevX TIR
+* net/mlx5: fix meter table definitions
+* net/mlx5: fix missing meter packet
+* net/mlx5: fix port shared data reference count
+* net/mlx5: fix raw encap/decap limit
+* net/mlx5: fix representor interrupts handler
+* net/mlx5: fix RSS queue type validation
+* net/mlx5: fix RSS RETA reset on start
+* net/mlx5: fix Rx descriptor status
+* net/mlx5: fix Rx packet padding config via DevX
+* net/mlx5: fix Rx queue completion index consistency
+* net/mlx5: fix Rx queue count calculation
+* net/mlx5: fix Rx queue count calculation
+* net/mlx5: fix switch port id when representor in bonding
+* net/mlx5: fix xstats reset reinitialization
+* net/mlx5: free MR resource on device DMA unmap
+* net/mlx5: remove unused includes
+* net/mlx5: remove unused log macros
+* net/mlx5: remove unused variable in Tx queue creation
+* net/mlx5: validate MPLSoGRE with GRE key
+* net/mlx: do not enforce RSS hash offload
+* net/mvpp2: fix memory leak in error path
+* net/netvsc: allocate contiguous physical memory for RNDIS
+* net/netvsc: check for overflow on packet info from host
+* net/netvsc: disable external mbuf on Rx by default
+* net/netvsc: fix multiple channel Rx
+* net/netvsc: fix rndis packet addresses
+* net/netvsc: fix stale value after free
+* net/netvsc: fix Tx queue leak in error path
+* net/netvsc: manage VF port under read/write lock
+* net/netvsc: replace compiler builtin overflow check
+* net/nfp: expand device info get
+* net/octeontx2: fix multi segment mode for jumbo packets
+* net/octeontx2: fix RSS flow create
+* net/octeontx2: remove useless check before free
+* net/pcap: fix crash on exit for infinite Rx
+* net/pcap: fix input only Rx
+* net/pfe: fix misuse of interface index
+* net/qede: fix dereference before null check
+* net/qede: fix getting link details
+* net/qede: fix milliseconds sleep macro
+* net/ring: check internal arguments
+* net/ring: fix typo in log message
+* net/sfc/base: fix tunnel configuration
+* net/sfc: fix RSS hash flag when offload is disabled
+* net/sfc: fix RSS hash offload if queue action is used
+* net/softnic: use POSIX network address conversion
+* net/tap: free mempool when closing
+* net/thunderx: fix memory leak on rbdr desc ring failure
+* net/vdev_netvsc: fix device probing error flow
+* net/vhost: fix xstats after clearing stats
+* net/virtio: check raw checksum failure
+* net/virtio: fix packed ring indirect descricptors setup
+* pmdinfogen: fix build with gcc 11
+* port: remove useless assignment
+* power: fix current frequency index
+* raw/dpaa2_qdma: fix reset
+* raw/ifpga/base: fix interrupt handler instance usage
+* raw/ifpga/base: fix return of IRQ unregister
+* raw/ifpga/base: handle unsupported interrupt type
+* raw/ifpga: terminate string filled by readlink with null
+* raw/ifpga: use trusted buffer to free
+* raw/ioat: fix missing close function
+* raw/skeleton: allow closing already closed device
+* raw/skeleton: reset test statistics
+* rcu: avoid literal suffix warning in C++ mode
+* Revert "app/testpmd: fix name of bitrate library in meson build"
+* Revert "Revert "build: always link whole DPDK static libraries""
+* Revert "Revert "build/pkg-config: improve static linking flags""
+* Revert "Revert "build/pkg-config: move pkg-config file creation""
+* Revert "Revert "build/pkg-config: output drivers first for static build""
+* Revert "Revert "build/pkg-config: prevent overlinking""
+* Revert "Revert "devtools: test static linkage with pkg-config""
+* stack: fix uninitialized variable
+* stack: reload head when pop fails
+* table: fix hash for 32-bit
+* test/crypto: fix device number
+* test/crypto: fix stats test
+* test/distributor: collect return mbufs
+* test/distributor: ensure all packets are delivered
+* test/distributor: fix freeing mbufs
+* test/distributor: fix lcores statistics
+* test/distributor: fix mbuf leak on failure
+* test/distributor: fix quitting workers in burst mode
+* test/distributor: fix race conditions on shutdown
+* test/distributor: fix shutdown of busy worker
+* test/event_crypto_adapter: fix configuration
+* test/event: fix function arguments for crypto adapter
+* test/mbuf: skip field registration at busy offset
+* test/rcu: fix build with low core count
+* test/ring: fix number of single element enqueue/dequeue
+* timer: add limitation note for sync stop and reset
+* usertools: fix CPU layout script to be PEP8 compliant
+* usertools: fix pmdinfo parsing
+* vdpa/ifc: fix build with recent kernels
+* version: 19.11.6-rc1
+* vfio: fix group descriptor check
+* vhost: fix error path when setting memory tables
+* vhost: fix external mbuf creation
+* vhost: fix fd leak in dirty logging setup
+* vhost: fix fd leak in kick setup
+* vhost: fix IOTLB mempool single-consumer flag
+* vhost: fix virtio-net header length with packed ring
+* vhost: fix virtqueue initialization
+* vhost: fix virtqueues metadata allocation
+* vhost: validate index in available entries API
+* vhost: validate index in guest notification API
+* vhost: validate index in inflight API
+* vhost: validate index in live-migration API
+
+19.11.6 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Intel(R) Testing
+
+   * Basic Intel(R) NIC(ixgbe, i40e and ice) testing
+      * PF (i40e)
+      * PF (ixgbe)
+      * PF (ice)
+      * VF (i40e)
+      * VF (ixgbe)
+      * VF (ice)
+      * Compile Testing
+      * Intel NIC single core/NIC performance
+
+   * Basic cryptodev and virtio testing
+
+      * vhost/virtio basic loopback, PVP and performance test
+      * cryptodev Function/Performance
+
+
+* Microsoft(R) Testing
+
+   * Platform
+
+      * Azure
+         * Ubuntu 16.04-LTS
+         * Ubuntu 18.04-DAILY-LTS
+         * RHEL 7.5
+         * Openlogic CentOS 7.5
+         * SLES-15-sp1 gen1
+      * Mellanox(R) ConnectX-4
+      * LISAv2 test framework
+
+   * Functionality
+
+      * VERIFY-DPDK-COMPLIANCE       * verifies kernel is supported and that the build is successful
+      * VERIFY-DPDK-BUILD-AND-TESTPMD-TEST       * verifies using testpmd that packets can be sent from a VM to another VM
+      * VERIFY-SRIOV-FAILSAFE-FOR-DPDK       * disables/enables Accelerated Networking for the NICs under test and makes sure DPDK works in both scenarios
+      * VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC       * disables/enables Accelerated Networking for the NICs while generating traffic using testpmd
+      * PERF-DPDK-FWD-PPS-DS15       * verifies DPDK forwarding performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-SINGLE-CORE-PPS-DS4       * verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS4_v2
+      * PERF-DPDK-SINGLE-CORE-PPS-DS15       * verifies DPDK performance using testpmd on 1 core, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-MULTICORE-PPS-DS15       * verifies DPDK performance using testpmd on 2, 4, 8 cores, rx and io mode on size Standard_DS15_v2
+      * PERF-DPDK-MULTICORE-PPS-F32       * verifies DPDK performance using testpmd on 2, 4, 8, 16 cores, rx and io mode on size Standard_F32s_v2
+      * DPDK-RING-LATENCY       * verifies DPDK CPU latency using dpdk-ring-ping
+      * VERIFY-DPDK-OVS       * builds OVS with DPDK support and tests if the OVS DPDK ports can be created. Runs only on Ubuntu distro.
+      * VERIFY-DPDK-BUILD-AND-NETVSCPMD-TEST       * verifies using testpmd with netvsc pmd that packets can be sent from a VM to another VM.
+      * VERIFY-SRIOV-FAILSAFE-FOR-DPDK-NETVSCPMD       * disables/enables Accelerated Networking for the NICs under test and makes sure DPDK with netvsc pmd works in both scenarios.
+      * VERIFY-DPDK-FAILSAFE-DURING-TRAFFIC-NETVSCPMD       * Verify Accelerated Networking (VF) removed and readded for the NICs while generating traffic using testpmd with netvsc pmd.
+
+
+* Red Hat(R) Testing
+
+   * Platform
+
+      * RHEL 8
+      * Kernel 4.18
+      * Qemu 5.2
+      * X540-AT2 NIC(ixgbe, 10G)
+
+   * Functionality
+
+      * Guest with device assignment(PF) throughput testing(1G hugepage size)
+      * Guest with device assignment(PF) throughput testing(2M hugepage size)
+      * Guest with device assignment(VF) throughput testing
+      * PVP (host dpdk testpmd as vswitch) 1Q: throughput testing
+      * PVP vhost-user 2Q throughput testing
+      * PVP vhost-user 1Q       * cross numa node  throughput testing
+      * Guest with vhost-user 2 queues throughput testing
+      * vhost-user reconnect with dpdk-client, qemu-server: qemu reconnect
+      * vhost-user reconnect with dpdk-client, qemu-server: ovs reconnect: PASS
+      * PVP 1Q live migration testing
+      * PVP 1Q cross numa node live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing (2M)
+      * Guest with ovs+dpdk+vhost-user 2Q live migration testing
+      * Allocate memory from the NUMA node which Virtio device locates
+      * Host PF + DPDK testing
+      * Host VF + DPDK testing
+
+
+* Intel(R) Testing with Open vSwitch
+
+   * OVS testing with OVS 2.14.1
+
+   * Performance
+
+      * ICE Device
+
+         * Basic performance tests (RFC2544 P2P, PVP_CONT, RFC2544 PVP_TPUT, RFC2544 PVVP_TPUT, PVPV) Jumbo frames RSS
+
+      * i40e Device
+
+         * Basic performance (RFC2544 P2P, PVP_CONT, RFC2544 PVP_TPUT, RFC2544 PVVP_TPUT, PVPV) Jumbo frames RSS Flow control
+
+      * ixgbe Device
+
+         * Basic performance tests (RFC2544 P2P, PVP_CONT, RFC2544 PVP_TPUT, RFC2544 PVVP_TPUT, PVPV) Jumbo frames RSS
+
+   * Functionality
+
+      * vhostuserclient device
+      * jumbo frames
+      * dpdkvhostuserclient re-connect
+      * dpdkvhostuserclient NUMA node
+
+
+* Nvidia(R) Testing
+
+   * Basic functionality with testpmd
+
+      * Tx/Rx
+      * xstats
+      * Timestamps
+      * Link status
+      * RTE flow and flow_director
+      * RSS
+      * VLAN stripping and insertion
+      * Checksum/TSO
+      * ptype
+      * l3fwd-power example application
+      * Multi-process example applications
+
+   * Build tests
+
+      * Ubuntu 20.04 with MLNX_OFED_LINUX-5.1-2.5.8.0.
+      * Ubuntu 20.04 with rdma-core master (6a5c1b7).
+      * Ubuntu 20.04 with rdma-core v28.0.
+      * Ubuntu 18.04 with rdma-core v17.1.
+      * Ubuntu 18.04 with rdma-core master (6a5c1b7) (i386).
+      * Ubuntu 16.04 with rdma-core v22.7.
+      * Fedora 32 with rdma-core v32.0.
+      * CentOS 7 7.9.2009 with rdma-core master (6a5c1b7).
+      * CentOS 7 7.9.2009 with MLNX_OFED_LINUX-5.1-2.5.8.0.
+      * CentOS 8 8.3.2011 with rdma-core master (6a5c1b7).
+      * openSUSE Leap 15.2 with rdma-core v27.1.
+
+   * ConnectX-5
+
+      * RHEL 7.4
+      * Driver MLNX_OFED_LINUX-5.1-2.5.8.0
+      * fw 14.28.2006
+
+   * ConnectX-4 Lx
+
+      * RHEL 7.4
+      * Driver MLNX_OFED_LINUX-5.1-2.5.8.0
+      * fw 16.28.2006
+
+19.11.6 Known Issues
+~~~~~~~~~~~~~~~~~~~~
+
+* i40e
+
+   * rss_to_rte_flow/set_key_keylen: create rule can fail.
+     https://bugs.dpdk.org/show_bug.cgi?id=573
+   * inconsistency with expected queue after creating a flow rule - firmware issue.
+
+* vhost/virtio
+
+   * udp-fragmentation-offload cannot be setup on Ubuntu 19.10 VMs.
+     https://bugzilla.kernel.org/show_bug.cgi?id=207075
+
+* vdev_netvsc
+
+   * hot-removal of VF driver can fail
+
+19.11.7 Release Notes
+---------------------
+
+19.11.7 Fixes
+~~~~~~~~~~~~~
+
+* app/crypto-perf: fix CSV output format
+* app/crypto-perf: fix latency CSV output
+* app/crypto-perf: fix spelling in output
+* app/crypto-perf: remove always true condition
+* app/eventdev: adjust event count order for pipeline test
+* app/eventdev: fix SMP barrier in performance test
+* app/eventdev: remove redundant enqueue in burst Tx
+* app: fix build with extra include paths
+* app/procinfo: fix check on xstats-ids
+* app/procinfo: fix _filters stats reporting
+* app/procinfo: remove useless memset
+* app/testpmd: avoid exit without terminal restore
+* app/testpmd: fix help of metering commands
+* app/testpmd: fix IP checksum calculation
+* app/testpmd: fix key for RSS flow rule
+* app/testpmd: fix max Rx packet length for VLAN packets
+* app/testpmd: fix packets dump overlapping
+* app/testpmd: release flows left before port stop
+* build: fix linker flags on Windows
+* build: fix plugin load on static build
+* build: fix scheduler macro definition for meson
+* build: force pkg-config for dependency detection
+* build: provide suitable error for "both" libraries option
+* common/mlx5: fix pointer cast on Windows
+* common/octeontx2: fix build with SVE
+* crypto/dpaa2_sec: fix memory allocation check
+* doc: fix mark action zero value in mlx5 guide
+* doc: fix product link in hns3 guide
+* doc: fix QinQ flow rules in testpmd guide
+* doc: update flow mark action in mlx5 guide
+* eal/arm: fix debug build with gcc for 128-bit atomics
+* eal: fix MCS lock header include
+* eal: fix reciprocal header include
+* eal/linux: fix handling of error events from epoll
+* ethdev: fix max Rx packet length check
+* ethdev: fix missing header include
+* eventdev: fix a return value comment
+* examples/eventdev: add info output for main core
+* examples/eventdev: check CPU core enabling
+* examples/eventdev: move ethdev stop to the end
+* examples/l3fwd: remove limitation on Tx queue count
+* fbarray: fix overlap check
+* fib: fix missing header includes
+* ip_frag: remove padding length of fragment
+* ipsec: fix missing header include
+* lib/power: fix make build error
+* lpm: fix vector IPv4 lookup
+* mbuf: add C++ include guard for dynamic fields header
+* mbuf: fix missing header include
+* mem: exclude unused memory from core dump
+* net/af_xdp: remove useless assignment
+* net/avp: remove always true condition
+* net/bnxt: disable end of packet padding for Rx
+* net/bnxt: fix cleanup on mutex init failure
+* net/bnxt: fix doorbell write ordering
+* net/bnxt: fix fallback mbuf allocation logic
+* net/bnxt: fix FW version log
+* net/bnxt: fix max rings computation
+* net/bnxt: fix memory leak when mapping fails
+* net/bnxt: fix null termination of Rx mbuf chain
+* net/bnxt: fix outer UDP checksum Rx offload capability
+* net/bnxt: fix Rx rings in RSS redirection table
+* net/bnxt: fix VNIC config on Rx queue stop
+* net/bnxt: fix VNIC RSS configure function
+* net/bnxt: propagate FW command failure to application
+* net/bnxt: release HWRM lock in error
+* net/bonding: fix PCI address comparison on non-PCI ports
+* net/bonding: fix port id validity check on parsing
+* net/bonding: remove local variable shadowing outer one
+* net/cxgbe: fix jumbo frame flag condition
+* net/dpaa2: fix jumbo frame flag condition for MTU set
+* net/dpaa: fix jumbo frame flag condition for MTU set
+* net/e1000: fix flow control mode setting
+* net/e1000: fix jumbo frame flag condition for MTU set
+* net/ena: flush Rx buffers memory pool cache
+* net/enetc: fix jumbo frame flag condition for MTU set
+* net/enic: fix filter log message
+* net/enic: fix filter type used for flow API
+* net/hns3: adjust format specifier for enum
+* net/hns3: fix data overwriting during register dump
+* net/hns3: fix dump register out of range
+* net/hns3: fix error code in xstats
+* net/hns3: fix firmware exceptions by concurrent commands
+* net/hns3: fix flow director rule residue on malloc failure
+* net/hns3: fix interception with flow director
+* net/hns3: fix jumbo frame flag condition for MTU set
+* net/hns3: fix memory leak on secondary process exit
+* net/hns3: fix register length when dumping registers
+* net/hns3: fix Rx/Tx errors stats
+* net/hns3: fix VF query link status in dev init
+* net/hns3: fix VF reset on mailbox failure
+* net/hns3: fix xstats with id and names
+* net/hns3: remove MPLS from supported flow items
+* net/hns3: use new opcode for clearing hardware resource
+* net/hns3: validate requested maximum Rx frame length
+* net/i40e: add null input checks
+* net/i40e: fix global register recovery
+* net/i40e: fix jumbo frame flag condition
+* net/i40e: fix L4 checksum flag
+* net/i40e: fix returned code for RSS hardware failure
+* net/i40e: fix Rx bytes statistics
+* net/i40e: fix stats counters
+* net/i40e: fix VLAN stripping in VF
+* net/i40e: fix X722 for 802.1ad frames ability
+* net/iavf: fix jumbo frame flag condition
+* net/iavf: fix vector mapping with queue
+* net/ice/base: fix memory handling
+* net/ice/base: fix null pointer dereference
+* net/ice/base: fix tunnel destroy
+* net/ice: check Rx queue number on RSS init
+* net/ice: disable IPv4 checksum offload in vector Tx
+* net/ice: enlarge Rx queue rearm threshold to 64
+* net/ice: fix jumbo frame flag condition
+* net/ice: fix outer checksum flags
+* net/ice: fix outer UDP Tx checksum offload
+* net/ice: fix RSS lookup table initialization
+* net/ipn3ke: fix jumbo frame flag condition for MTU set
+* net/ixgbe: add new flag of stripped VLAN for NEON
+* net/ixgbe: detect failed VF MTU set
+* net/ixgbe: disable NFS filtering
+* net/ixgbe: enable IXGBE NEON vector PMD when CHECKSUM need to checksum
+* net/ixgbe: fix configuration of max frame size
+* net/ixgbe: fix flex bytes flow director rule
+* net/ixgbe: fix jumbo frame flag condition
+* net/ixgbe: fix UDP zero checksum on x86
+* net/ixgbe: support bad checksum flag for NEON
+* net/ixgbe: support good checksum flag for NEON
+* net/liquidio: fix jumbo frame flag condition for MTU set
+* net/mlx4: fix handling of probing failure
+* net/mlx4: fix port attach in secondary process
+* net/mlx5: fix comparison sign in flow engine
+* net/mlx5: fix crash on secondary process port close
+* net/mlx5: fix leak on Rx queue creation failure
+* net/mlx5: fix leak on Tx queue creation failure
+* net/mlx5: refuse empty VLAN in flow pattern
+* net/mvneta: check allocation in Rx queue flush
+* net/mvpp2: fix frame size checking
+* net/mvpp2: fix stack corruption
+* net/mvpp2: remove CRC length from MRU validation
+* net/mvpp2: remove debug log on fast-path
+* net/mvpp2: remove VLAN flush
+* net/netvsc: ignore unsupported packet on sync command
+* net/nfp: fix jumbo frame flag condition for MTU set
+* net/nfp: read chip model from PluDevice register
+* net/octeontx2: fix corruption in segments list
+* net/octeontx2: fix jumbo frame flag condition for MTU
+* net/octeontx2: fix PF flow action for Tx
+* net/octeontx: fix build with SVE
+* net/pcap: fix byte stats for drop Tx
+* net/pcap: fix infinite Rx with large files
+* net/pcap: remove local variable shadowing outer one
+* net/qede: fix jumbo frame flag condition for MTU set
+* net/qede: fix promiscuous enable
+* net/sfc: fix generic byte statistics to exclude FCS bytes
+* net/sfc: fix jumbo frame flag condition for MTU set
+* net/sfc: fix TSO and checksum offloads for EF10
+* net/thunderx: fix jumbo frame flag condition for MTU set
+* net/virtio-user: fix run closing stdin and close callfd
+* power: clean up includes
+* power: create guest channel public header file
+* power: export guest channel header file
+* power: fix missing header includes
+* power: make channel message functions public
+* power: rename constants
+* power: rename public structs
+* Revert "app/testpmd: release flows left before port stop"
+* rib: fix insertion in some cases
+* rib: fix missing header include
+* rib: fix missing header includes
+* (tag: 19.11.7-20.11-21.02-rc2) app/testpmd: fix setting maximum packet length
+* (tag: 19.11.7-20.11-21.02-rc2-backports) net/mlx5: fix port attach in secondary process
+* (tag: 19.11.7-21.02rc2-21.02-rc3-backports) net/mlx5: fix VXLAN decap on non-VXLAN flow
+* (tag: 19.11.7-21.02rc2-21.02-rc3) mempool: fix panic on dump or audit
+* (tag: 19.11.7-21.02rc3-21.02-backports) mem: fix build
+* (tag: 19.11.7-21.02rc3-21.02) usertools: fix binding built-in kernel driver
+* (tag: v19.11.7-rc1) version: 19.11.7-rc1
+* test/distributor: fix return buffer queue overload
+* test/event_crypto: set cipher operation in transform
+* test: fix buffer overflow in Tx burst
+* test: fix terminal settings on exit
+* test/ipsec: fix result code for not supported
+* test/mcslock: remove unneeded per lcore copy
+* usertools: fix Python compatibility issue
+* vhost: fix packed ring dequeue offloading
+* vhost: fix vid allocation race
+
+19.11.7 Validation
+~~~~~~~~~~~~~~~~~~
+
+* Red Hat(R) Testing
+
+   * Platform
+
+      * RHEL 8
+      * Kernel 4.18
+      * Qemu 5.2
+      * X540-AT2 NIC(ixgbe, 10G)
+      * Tested on 19.11.7-RC1
+
+   * Tests
+
+      * Guest with device assignment(PF) throughput testing(1G hugepage size): PASS
+      * Guest with device assignment(PF) throughput testing(2M hugepage size) : PASS
+      * Guest with device assignment(VF) throughput testing: PASS
+      * PVP (host dpdk testpmd as vswitch) 1Q: throughput testing: PASS
+      * PVP vhost-user 2Q throughput testing: PASS
+      * PVP vhost-user 1Q - cross numa node throughput testing: PASS
+      * Guest with vhost-user 2 queues throughput testing: PASS
+      * vhost-user reconnect with dpdk-client, qemu-server: qemu reconnect: PASS
+      * vhost-user reconnect with dpdk-client, qemu-server: ovs reconnect: PASS
+      * PVP 1Q live migration testing: PASS
+      * PVP 1Q cross numa node live migration testing: PASS
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing: PASS
+      * Guest with ovs+dpdk+vhost-user 1Q live migration testing (2M): PASS
+      * Guest with ovs+dpdk+vhost-user 2Q live migration testing: PASS
+      * Host PF + DPDK testing: PASS
+      * Host VF + DPDK testing: PASS
+
+* Nvidia (R) Testing
+
+   * functional tests on Mellanox hardware
+
+      * NIC: ConnectX-4 Lx / OS: RHEL7.4 / Driver: MLNX_OFED_LINUX-5.2-2.2.0.0 Firmware: 14.29.2002
+      * NIC: ConnectX-5 / OS: RHEL7.4 / Driver: MLNX_OFED_LINUX-5.2-2.2.0.0 Firmware: 16.29.2002
+
+   * Basic functionality:
+
+      * Send and receive multiple types of traffic.
+      * testpmd xstats counter test.
+      * testpmd timestamp test.
+      * Changing/checking link status through testpmd.
+      * RTE flow tests: Items: eth / vlan / ipv4 / ipv6 / tcp / udp / icmp / gre / nvgre / vxlan ip in ip / mplsoudp / mplsogre
+      * Actions: drop / queue / rss / mark / flag / jump / count / raw_encap / raw_decap / vxlan_encap / vxlan_decap / NAT / dec_ttl
+      * Some RSS tests.
+      * VLAN filtering, stripping and insertion tests.
+      * Checksum and TSO tests.
+      * ptype tests.
+      * link_status_interrupt example application tests.
+      * l3fwd-power example application tests.
+      * Multi-process example applications tests.
+
+   * Compilation tests with multiple configurations in the following OS/driver combinations are also passing:
+
+      * Ubuntu 20.04.2 with MLNX_OFED_LINUX-5.2-2.2.0.0.
+      * Ubuntu 20.04.2 with rdma-core master (a1a9ffb).
+      * Ubuntu 20.04.2 with rdma-core v28.0.
+      * Ubuntu 18.04.5 with rdma-core v17.1.
+      * Ubuntu 18.04.5 with rdma-core master (a1a9ffb) (i386).
+      * Ubuntu 16.04.7 with rdma-core v22.7.
+      * Fedora 32 with rdma-core v33.0.
+      * CentOS 7 7.9.2009 with rdma-core master (a1a9ffb).
+      * CentOS 7 7.9.2009 with MLNX_OFED_LINUX-5.2-2.2.0.0.
+      * CentOS 8 8.3.2011 with rdma-core master (a1a9ffb).
+      * OpenSUSE Leap 15.2 with rdma-core v27.1.
+
+* Intel(R) Testing
+
+   * Basic Intel NIC (ixgbe, i40e) testing
+
+      * PF (i40e)
+      * PF (ixgbe)
+      * VF (i40e)
+      * VF (ixgbe)
+      * Compile Testing
+      * Intel NIC single core/NIC performance
+
+   * Basic cryptodev and virtio testing
+
+      * vhost/virtio basic loopback, PVP and performance test
+      * cryptodev Function/Performance
+
+* Intel(R) Testing with Open vSwitch
+
+   * OVS testing with OVS 2.14.3
+
+      * I40e: Performance Tests Jumbo frames RSS
+      * Niantic: Performance Tests Jumbo frames RSS
+      * Ice: Performance Tests Jumbo frames RSS
+      * Vhost: Port addition, deletion, jumbo frames and RSS multi-queue tests.
+
+* Canonical(R) Testing
+
+   * Build tests on Ubuntu 21.04
+   * OVS-DPDK tests on x86_64
+
+      * performance tests
+
+         * test guest-openvswitch for OVS-5CPU  => Pass
+         * test guest-dpdk-vhost-user-client-multiq for OVSDPDK-VUC  => Pass
+
+      * VUC endurance tests
+
+         * start stop guests (client)  => Pass
+         * add/remove ports (client)  => Pass
+
+19.11.7 Known Issues
+~~~~~~~~~~~~~~~~~~~~
+
+* The UDP fragmentation offload feature of Virtio-net device can not be turned on in the VM. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=207075
+
+* mlx5 VLAN packets will not do RSS. Bug: https://bugs.dpdk.org/show_bug.cgi?id=661
diff --git a/dpdk/doc/guides/sample_app_ug/ethtool.rst b/dpdk/doc/guides/sample_app_ug/ethtool.rst
index 8f7fc6ca66..253004dd00 100644
--- a/dpdk/doc/guides/sample_app_ug/ethtool.rst
+++ b/dpdk/doc/guides/sample_app_ug/ethtool.rst
@@ -24,7 +24,7 @@ The only available options are the standard ones for the EAL:
 
 .. code-block:: console
 
-    ./ethtool-app/ethtool-app/${RTE_TARGET}/ethtool [EAL options]
+    ./ethtool-app/${RTE_TARGET}/ethtool [EAL options]
 
 Refer to the *DPDK Getting Started Guide* for general information on
 running applications and the Environment Abstraction Layer (EAL)
diff --git a/dpdk/doc/guides/sample_app_ug/eventdev_pipeline.rst b/dpdk/doc/guides/sample_app_ug/eventdev_pipeline.rst
index dc7972aa9a..24fb23b898 100644
--- a/dpdk/doc/guides/sample_app_ug/eventdev_pipeline.rst
+++ b/dpdk/doc/guides/sample_app_ug/eventdev_pipeline.rst
@@ -34,6 +34,7 @@ options.
 An example eventdev pipeline running with the software eventdev PMD using
 these settings is shown below:
 
+ * ``-l 0,2,8-15``: lcore to use
  * ``-r1``: core mask 0x1 for RX
  * ``-t1``: core mask 0x1 for TX
  * ``-e4``: core mask 0x4 for the software scheduler
@@ -46,7 +47,8 @@ these settings is shown below:
 
 .. code-block:: console
 
-    ./build/eventdev_pipeline --vdev event_sw0 -- -r1 -t1 -e4 -w FF00 -s4 -n0 -c32 -W1000 -D
+    ./build/eventdev_pipeline --vdev event_sw0 -l 0,2,8-15 -- -r1 -t1 \
+    -e4 -w FF00 -s4 -n0 -c32 -W1000 -D
 
 The application has some sanity checking built-in, so if there is a function
 (e.g.; the RX core) which doesn't have a cpu core mask assigned, the application
diff --git a/dpdk/doc/guides/sample_app_ug/flow_classify.rst b/dpdk/doc/guides/sample_app_ug/flow_classify.rst
index bc234b50a7..451a0db88f 100644
--- a/dpdk/doc/guides/sample_app_ug/flow_classify.rst
+++ b/dpdk/doc/guides/sample_app_ug/flow_classify.rst
@@ -271,7 +271,7 @@ Forwarding application is shown below:
 .. code-block:: c
 
     static inline int
-    port_init(uint8_t port, struct rte_mempool *mbuf_pool)
+    port_init(uint16_t port, struct rte_mempool *mbuf_pool)
     {
         struct rte_eth_conf port_conf = port_conf_default;
         const uint16_t rx_rings = 1, tx_rings = 1;
diff --git a/dpdk/doc/guides/sample_app_ug/flow_filtering.rst b/dpdk/doc/guides/sample_app_ug/flow_filtering.rst
index 5e5a6cd8a0..d3653e57b2 100644
--- a/dpdk/doc/guides/sample_app_ug/flow_filtering.rst
+++ b/dpdk/doc/guides/sample_app_ug/flow_filtering.rst
@@ -384,7 +384,7 @@ This function is located in the ``flow_blocks.c`` file.
 .. code-block:: c
 
    static struct rte_flow *
-   generate_ipv4_flow(uint8_t port_id, uint16_t rx_q,
+   generate_ipv4_flow(uint16_t port_id, uint16_t rx_q,
                    uint32_t src_ip, uint32_t src_mask,
                    uint32_t dest_ip, uint32_t dest_mask,
                    struct rte_flow_error *error)
diff --git a/dpdk/doc/guides/sample_app_ug/ipsec_secgw.rst b/dpdk/doc/guides/sample_app_ug/ipsec_secgw.rst
index d6d8d44686..eb1a57a98f 100644
--- a/dpdk/doc/guides/sample_app_ug/ipsec_secgw.rst
+++ b/dpdk/doc/guides/sample_app_ug/ipsec_secgw.rst
@@ -92,7 +92,7 @@ The application has a number of command line options::
 
    ./build/ipsec-secgw [EAL options] --
                         -p PORTMASK -P -u PORTMASK -j FRAMESIZE
-                        -l -w REPLAY_WINOW_SIZE -e -a
+                        -l -w REPLAY_WINDOW_SIZE -e -a
                         --config (port,queue,lcore)[,(port,queue,lcore]
                         --single-sa SAIDX
                         --rxoffload MASK
@@ -122,7 +122,7 @@ Where:
 
 *   ``-l``: enables code-path that uses librte_ipsec.
 
-*   ``-w REPLAY_WINOW_SIZE``: specifies the IPsec sequence number replay window
+*   ``-w REPLAY_WINDOW_SIZE``: specifies the IPsec sequence number replay window
     size for each Security Association (available only with librte_ipsec
     code path).
 
diff --git a/dpdk/doc/guides/sample_app_ug/l2_forward_event.rst b/dpdk/doc/guides/sample_app_ug/l2_forward_event.rst
index 8c519c3046..c5fad93d00 100644
--- a/dpdk/doc/guides/sample_app_ug/l2_forward_event.rst
+++ b/dpdk/doc/guides/sample_app_ug/l2_forward_event.rst
@@ -202,9 +202,6 @@ chapters that related to the Poll Mode and Event mode Driver in the
 
 .. code-block:: c
 
-    if (rte_pci_probe() < 0)
-        rte_panic("Cannot probe PCI\n");
-
     /* reset l2fwd_dst_ports */
 
     for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
@@ -234,11 +231,6 @@ chapters that related to the Poll Mode and Event mode Driver in the
         rte_eth_dev_info_get((uint8_t) portid, &dev_info);
     }
 
-Observe that:
-
-*   rte_pci_probe() parses the devices on the PCI bus and initializes recognized
-    devices.
-
 The next step is to configure the RX and TX queues. For each port, there is only
 one RX queue (only one lcore is able to poll a given port). The number of TX
 queues depends on the number of available lcores. The rte_eth_dev_configure()
diff --git a/dpdk/doc/guides/sample_app_ug/l2_forward_real_virtual.rst b/dpdk/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
index 39d6b0067a..671d0c7c19 100644
--- a/dpdk/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
+++ b/dpdk/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
@@ -194,9 +194,6 @@ in the *DPDK Programmer's Guide* - Rel 1.4 EAR and the *DPDK API Reference*.
 
 .. code-block:: c
 
-    if (rte_pci_probe() < 0)
-        rte_exit(EXIT_FAILURE, "Cannot probe PCI\n");
-
     /* reset l2fwd_dst_ports */
 
     for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
@@ -226,12 +223,6 @@ in the *DPDK Programmer's Guide* - Rel 1.4 EAR and the *DPDK API Reference*.
         rte_eth_dev_info_get((uint8_t) portid, &dev_info);
     }
 
-Observe that:
-
-*   rte_igb_pmd_init_all() simultaneously registers the driver as a PCI driver and as an Ethernet* Poll Mode Driver.
-
-*   rte_pci_probe() parses the devices on the PCI bus and initializes recognized devices.
-
 The next step is to configure the RX and TX queues.
 For each port, there is only one RX queue (only one lcore is able to poll a given port).
 The number of TX queues depends on the number of available lcores.
diff --git a/dpdk/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst b/dpdk/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst
index a44fbcd52c..4e58c6c612 100644
--- a/dpdk/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst
+++ b/dpdk/doc/guides/sample_app_ug/l3_forward_access_ctrl.rst
@@ -236,7 +236,7 @@ The application has a number of command line options:
 
 ..  code-block:: console
 
-    ./build/l3fwd-acl [EAL options] -- -p PORTMASK [-P] --config(port,queue,lcore)[,(port,queue,lcore)] --rule_ipv4 FILENAME rule_ipv6 FILENAME [--scalar] [--enable-jumbo [--max-pkt-len PKTLEN]] [--no-numa]
+    ./build/l3fwd-acl [EAL options] -- -p PORTMASK [-P] --config(port,queue,lcore)[,(port,queue,lcore)] --rule_ipv4 FILENAME --rule_ipv6 FILENAME [--scalar] [--enable-jumbo [--max-pkt-len PKTLEN]] [--no-numa]
 
 
 where,
@@ -268,7 +268,7 @@ To enable L3 forwarding between two ports, assuming that both ports are in the s
 
 ..  code-block:: console
 
-    ./build/l3fwd-acl -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --rule_ipv4="./rule_ipv4.db" -- rule_ipv6="./rule_ipv6.db" --scalar
+    ./build/l3fwd-acl -l 1,2 -n 4 -- -p 0x3 --config="(0,0,1),(1,0,2)" --rule_ipv4="./rule_ipv4.db" --rule_ipv6="./rule_ipv6.db" --scalar
 
 In this command:
 
@@ -290,9 +290,9 @@ In this command:
     |          |            |           |                                     |
     +----------+------------+-----------+-------------------------------------+
 
-*   The --rule_ipv4 option specifies the reading of IPv4 rules sets from the ./ rule_ipv4.db file.
+*   The --rule_ipv4 option specifies the reading of IPv4 rules sets from the rule_ipv4.db file.
 
-*   The --rule_ipv6 option specifies the reading of IPv6 rules sets from the ./ rule_ipv6.db file.
+*   The --rule_ipv6 option specifies the reading of IPv6 rules sets from the rule_ipv6.db file.
 
 *   The --scalar option specifies the performing of rule lookup with a scalar function.
 
diff --git a/dpdk/doc/guides/sample_app_ug/l3_forward_power_man.rst b/dpdk/doc/guides/sample_app_ug/l3_forward_power_man.rst
index 6ec24f4ad8..dbdaa743dd 100644
--- a/dpdk/doc/guides/sample_app_ug/l3_forward_power_man.rst
+++ b/dpdk/doc/guides/sample_app_ug/l3_forward_power_man.rst
@@ -49,7 +49,7 @@ to set the CPUFreq governor and set the frequency of specific cores.
 
 This application includes a P-state power management algorithm to generate a frequency hint to be sent to CPUFreq.
 The algorithm uses the number of received and available Rx packets on recent polls to make a heuristic decision to scale frequency up/down.
-Specifically, some thresholds are checked to see whether a specific core running an DPDK polling thread needs to increase frequency
+Specifically, some thresholds are checked to see whether a specific core running a DPDK polling thread needs to increase frequency
 a step up based on the near to full trend of polled Rx queues.
 Also, it decreases frequency a step if packet processed per loop is far less than the expected threshold
 or the thread's sleeping time exceeds a threshold.
diff --git a/dpdk/doc/guides/sample_app_ug/link_status_intr.rst b/dpdk/doc/guides/sample_app_ug/link_status_intr.rst
index 5283be8b7c..04c40f2854 100644
--- a/dpdk/doc/guides/sample_app_ug/link_status_intr.rst
+++ b/dpdk/doc/guides/sample_app_ug/link_status_intr.rst
@@ -88,9 +88,6 @@ To fully understand this code, it is recommended to study the chapters that rela
 
 .. code-block:: c
 
-    if (rte_pci_probe() < 0)
-        rte_exit(EXIT_FAILURE, "Cannot probe PCI\n");
-
     /*
      * Each logical core is assigned a dedicated TX queue on each port.
      */
@@ -115,10 +112,6 @@ To fully understand this code, it is recommended to study the chapters that rela
         rte_eth_dev_info_get((uint8_t) portid, &dev_info);
     }
 
-Observe that:
-
-*   rte_pci_probe()  parses the devices on the PCI bus and initializes recognized devices.
-
 The next step is to configure the RX and TX queues.
 For each port, there is only one RX queue (only one lcore is able to poll a given port).
 The number of TX queues depends on the number of available lcores.
diff --git a/dpdk/doc/guides/sample_app_ug/multi_process.rst b/dpdk/doc/guides/sample_app_ug/multi_process.rst
index 9c374da6f7..f2a79a6397 100644
--- a/dpdk/doc/guides/sample_app_ug/multi_process.rst
+++ b/dpdk/doc/guides/sample_app_ug/multi_process.rst
@@ -209,7 +209,7 @@ How the Application Works
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The initialization calls in both the primary and secondary instances are the same for the most part,
-calling the rte_eal_init(), 1 G and 10 G driver initialization and then rte_pci_probe() functions.
+calling the rte_eal_init(), 1 G and 10 G driver initialization and then probing devices.
 Thereafter, the initialization done depends on whether the process is configured as a primary or secondary instance.
 
 In the primary instance, a memory pool is created for the packet mbufs and the network ports to be used are initialized -
diff --git a/dpdk/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/dpdk/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 73ef0b41d3..17a41c21e5 100644
--- a/dpdk/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/dpdk/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -237,7 +237,7 @@ Display the RSS hash functions and RSS hash key of a port::
 clear port
 ~~~~~~~~~~
 
-Clear the port statistics for a given port or for all ports::
+Clear the port statistics and forward engine statistics for a given port or for all ports::
 
    testpmd> clear port (info|stats|xstats|fdir|stat_qmap) (port_id|all)
 
@@ -2437,16 +2437,16 @@ For example, to set the MAC address of a Link Bonding device (port 10) to 00:00:
 
    testpmd> set bonding mac 10 00:00:00:00:00:01
 
-set bonding xmit_balance_policy
+set bonding balance_xmit_policy
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Set the transmission policy for a Link Bonding device when it is in Balance XOR mode::
 
-   testpmd> set bonding xmit_balance_policy (port_id) (l2|l23|l34)
+   testpmd> set bonding balance_xmit_policy (port_id) (l2|l23|l34)
 
 For example, set a Link Bonding device (port 10) to use a balance policy of layer 3+4 (IP addresses & UDP ports)::
 
-   testpmd> set bonding xmit_balance_policy 10 l34
+   testpmd> set bonding balance_xmit_policy 10 l34
 
 
 set bonding mon_period
@@ -4435,14 +4435,14 @@ Sample QinQ flow rules
 Before creating QinQ rule(s) the following commands should be issued to enable QinQ::
 
    testpmd> port stop 0
-   testpmd> vlan set qinq_strip on 0
+   testpmd> vlan set extend on 0
 
 The above command sets the inner and outer TPID's to 0x8100.
 
 To change the TPID's the following commands should be used::
 
-   testpmd> vlan set outer tpid 0xa100 0
-   testpmd> vlan set inner tpid 0x9100 0
+   testpmd> vlan set outer tpid 0x88A8 0
+   testpmd> vlan set inner tpid 0x8100 0
    testpmd> port start 0
 
 Validate and create a QinQ rule on port 0 to steer traffic to a VF queue in a VM.
diff --git a/dpdk/doc/guides/tools/testbbdev.rst b/dpdk/doc/guides/tools/testbbdev.rst
index 7e95696609..bddfd8ae83 100644
--- a/dpdk/doc/guides/tools/testbbdev.rst
+++ b/dpdk/doc/guides/tools/testbbdev.rst
@@ -6,7 +6,7 @@ dpdk-test-bbdev Application
 
 The ``dpdk-test-bbdev`` tool is a Data Plane Development Kit (DPDK) utility that
 allows measuring performance parameters of PMDs available in the bbdev framework.
-Available tests available for execution are: latency, throughput, validation and
+Tests available for execution are: latency, throughput, validation and
 sanity tests. Execution of tests can be customized using various parameters
 passed to a python running script.
 
diff --git a/dpdk/doc/guides/windows_gsg/build_dpdk.rst b/dpdk/doc/guides/windows_gsg/build_dpdk.rst
index 6711e07e21..a0e51dfcb3 100644
--- a/dpdk/doc/guides/windows_gsg/build_dpdk.rst
+++ b/dpdk/doc/guides/windows_gsg/build_dpdk.rst
@@ -7,15 +7,22 @@ Compiling the DPDK Target from Source
 System Requirements
 -------------------
 
-The DPDK and its applications require the Clang-LLVM C compiler
-and Microsoft MSVC linker.
+Building the DPDK and its applications requires one of the following
+environments:
+
+* The Clang-LLVM C compiler and Microsoft MSVC linker.
+* The MinGW-w64 toolchain (either native or cross).
+
 The Meson Build system is used to prepare the sources for compilation
 with the Ninja backend.
 The installation of these tools is covered in this section.
 
 
+Option 1. Clang-LLVM C Compiler and Microsoft MSVC Linker
+---------------------------------------------------------
+
 Install the Compiler
---------------------
+~~~~~~~~~~~~~~~~~~~~
 
 Download and install the clang compiler from
 `LLVM website <http://releases.llvm.org/download.html>`_.
@@ -25,7 +32,7 @@ For example, Clang-LLVM direct download link::
 
 
 Install the Linker
-------------------
+~~~~~~~~~~~~~~~~~~
 
 Download and install the Build Tools for Visual Studio to link and build the
 files on windows,
@@ -34,6 +41,18 @@ When installing build tools, select the "Visual C++ build tools" option
 and ensure the Windows SDK is selected.
 
 
+Option 2. MinGW-w64 Toolchain
+-----------------------------
+
+Obtain the latest version from
+`MinGW-w64 website <http://mingw-w64.org/doku.php/download>`_.
+On Windows, install to a folder without spaces in its name, like ``C:\MinGW``.
+This path is assumed for the rest of this guide.
+
+Version 4.0.4 for Ubuntu 16.04 cannot be used due to a
+`MinGW-w64 bug <https://sourceforge.net/p/mingw-w64/bugs/562/>`_.
+
+
 Install the Build System
 ------------------------
 
@@ -43,6 +62,8 @@ A good option to choose is the MSI installer for both meson and ninja together::
 
 	http://mesonbuild.com/Getting-meson.html#installing-meson-and-ninja-with-the-msi-installer%22
 
+Recommended version is either Meson 0.47.1 (baseline) or the latest release.
+
 Install the Backend
 -------------------
 
@@ -56,23 +77,30 @@ Build the code
 The build environment is setup to build the EAL and the helloworld example by
 default.
 
-Using the ninja backend
-~~~~~~~~~~~~~~~~~~~~~~~~
+Option 1. Native Build on Windows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Specifying the compiler might be required to complete the meson command.
+When using Clang-LLVM, specifying the compiler might be required to complete
+the meson command:
 
 .. code-block:: console
 
     set CC=clang
 
+When using MinGW-w64, it is sufficient to have toolchain executables in PATH:
+
+.. code-block:: console
+
+    set PATH=C:\MinGW\mingw64\bin;%PATH%
+
 To compile the examples, the flag ``-Dexamples`` is required.
 
 .. code-block:: console
 
     cd C:\Users\me\dpdk
     meson -Dexamples=helloworld build
-    cd build
-    ninja
+    ninja -C build
+
 
 Run the helloworld example
 ==========================
@@ -87,3 +115,8 @@ Navigate to the examples in the build directory and run `dpdk-helloworld.exe`.
     hello from core 3
     hello from core 0
     hello from core 2
+
+Note for MinGW-w64: applications are linked to ``libwinpthread-1.dll``
+by default. To run the example, either add toolchain executables directory
+to the PATH or copy the library to the working directory.
+Alternatively, static linking may be used (mind the LGPLv2.1 license).
diff --git a/dpdk/drivers/Makefile b/dpdk/drivers/Makefile
index 7d5da5d9f5..cfc24b2d0b 100644
--- a/dpdk/drivers/Makefile
+++ b/dpdk/drivers/Makefile
@@ -19,7 +19,7 @@ DEPDIRS-common/qat := bus mempool
 DIRS-$(CONFIG_RTE_LIBRTE_COMPRESSDEV) += compress
 DEPDIRS-compress := bus mempool
 DIRS-$(CONFIG_RTE_LIBRTE_EVENTDEV) += event
-DEPDIRS-event := common bus mempool net
+DEPDIRS-event := common bus mempool net crypto
 DIRS-$(CONFIG_RTE_LIBRTE_RAWDEV) += raw
 DEPDIRS-raw := common bus mempool net event
 
diff --git a/dpdk/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c b/dpdk/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c
index 8bd10b401a..0a75a0ff13 100644
--- a/dpdk/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c
+++ b/dpdk/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c
@@ -2325,7 +2325,7 @@ fpga_lte_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
 
 	rte_bbdev_log_debug(
 			"Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
-			dev->device->driver->name, dev->data->name,
+			drv->driver.name, dev->data->name,
 			(void *)pci_dev->mem_resource[0].addr,
 			pci_dev->mem_resource[0].phys_addr);
 }
@@ -2380,7 +2380,7 @@ fpga_lte_fec_probe(struct rte_pci_driver *pci_drv,
 		((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
 
 #ifdef RTE_LIBRTE_BBDEV_DEBUG
-	if (!strcmp(bbdev->device->driver->name,
+	if (!strcmp(pci_drv->driver.name,
 			RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME)))
 		print_static_reg_debug_info(d->mmio_base);
 #endif
diff --git a/dpdk/drivers/baseband/turbo_sw/bbdev_turbo_software.c b/dpdk/drivers/baseband/turbo_sw/bbdev_turbo_software.c
index f2fe7a2194..18c4649917 100644
--- a/dpdk/drivers/baseband/turbo_sw/bbdev_turbo_software.c
+++ b/dpdk/drivers/baseband/turbo_sw/bbdev_turbo_software.c
@@ -10,6 +10,7 @@
 #include <rte_ring.h>
 #include <rte_kvargs.h>
 #include <rte_cycles.h>
+#include <rte_errno.h>
 
 #include <rte_bbdev.h>
 #include <rte_bbdev_pmd.h>
@@ -218,7 +219,7 @@ info_get(struct rte_bbdev *dev, struct rte_bbdev_driver_info *dev_info)
 					RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
 					RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE,
 			.llr_size = 8,
-			.llr_decimals = 2,
+			.llr_decimals = 4,
 			.harq_memory_size = 0,
 			.num_buffers_src =
 					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
@@ -303,7 +304,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->enc_out = rte_zmalloc_socket(name,
 			((RTE_BBDEV_TURBO_MAX_TB_SIZE >> 3) + 3) *
@@ -312,6 +314,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->enc_out == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -323,7 +326,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->enc_in = rte_zmalloc_socket(name,
 			(RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) * sizeof(*q->enc_in),
@@ -331,6 +335,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->enc_in == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -341,7 +346,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->ag = rte_zmalloc_socket(name,
 			RTE_BBDEV_TURBO_MAX_CB_SIZE * 10 * sizeof(*q->ag),
@@ -349,6 +355,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->ag == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -359,7 +366,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->code_block = rte_zmalloc_socket(name,
 			RTE_BBDEV_TURBO_MAX_CB_SIZE * sizeof(*q->code_block),
@@ -367,6 +375,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->code_block == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -378,7 +387,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->deint_input = rte_zmalloc_socket(name,
 			DEINT_INPUT_BUF_SIZE * sizeof(*q->deint_input),
@@ -386,6 +396,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->deint_input == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -397,7 +408,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->deint_output = rte_zmalloc_socket(NULL,
 			DEINT_OUTPUT_BUF_SIZE * sizeof(*q->deint_output),
@@ -405,6 +417,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->deint_output == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -416,7 +429,8 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->adapter_output = rte_zmalloc_socket(NULL,
 			ADAPTER_OUTPUT_BUF_SIZE * sizeof(*q->adapter_output),
@@ -424,6 +438,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	if (q->adapter_output == NULL) {
 		rte_bbdev_log(ERR,
 			"Failed to allocate queue memory for %s", name);
+		ret = -ENOMEM;
 		goto free_q;
 	}
 
@@ -434,12 +449,14 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 		rte_bbdev_log(ERR,
 				"Creating queue name for device %u queue %u failed",
 				dev->data->dev_id, q_id);
-		return -ENAMETOOLONG;
+		ret = -ENAMETOOLONG;
+		goto free_q;
 	}
 	q->processed_pkts = rte_ring_create(name, queue_conf->queue_size,
 			queue_conf->socket, RING_F_SP_ENQ | RING_F_SC_DEQ);
 	if (q->processed_pkts == NULL) {
 		rte_bbdev_log(ERR, "Failed to create ring for %s", name);
+		ret = -rte_errno;
 		goto free_q;
 	}
 
@@ -459,7 +476,7 @@ q_setup(struct rte_bbdev *dev, uint16_t q_id,
 	rte_free(q->deint_output);
 	rte_free(q->adapter_output);
 	rte_free(q);
-	return -EFAULT;
+	return ret;
 }
 
 static const struct rte_bbdev_ops pmd_ops = {
diff --git a/dpdk/drivers/bus/dpaa/base/qbman/qman_driver.c b/dpdk/drivers/bus/dpaa/base/qbman/qman_driver.c
index 69244ef701..e1dee17542 100644
--- a/dpdk/drivers/bus/dpaa/base/qbman/qman_driver.c
+++ b/dpdk/drivers/bus/dpaa/base/qbman/qman_driver.c
@@ -132,7 +132,7 @@ struct qman_portal *fsl_qman_fq_portal_create(int *fd)
 	struct qm_portal_config *q_pcfg;
 	struct dpaa_ioctl_irq_map irq_map;
 	struct dpaa_ioctl_portal_map q_map = {0};
-	int q_fd = 0, ret;
+	int q_fd, ret;
 
 	q_pcfg = kzalloc((sizeof(struct qm_portal_config)), 0);
 	if (!q_pcfg) {
@@ -169,7 +169,7 @@ struct qman_portal *fsl_qman_fq_portal_create(int *fd)
 	if (!portal) {
 		pr_err("Qman portal initialisation failed (%d)\n",
 		       q_pcfg->cpu);
-		goto err;
+		goto err_alloc;
 	}
 
 	irq_map.type = dpaa_portal_qman;
@@ -178,11 +178,9 @@ struct qman_portal *fsl_qman_fq_portal_create(int *fd)
 
 	*fd = q_fd;
 	return portal;
+err_alloc:
+	close(q_fd);
 err:
-	if (portal)
-		qman_free_global_portal(portal);
-	if (q_fd)
-		close(q_fd);
 	process_portal_unmap(&q_map.addr);
 	kfree(q_pcfg);
 	return NULL;
diff --git a/dpdk/drivers/bus/dpaa/dpaa_bus.c b/dpdk/drivers/bus/dpaa/dpaa_bus.c
index f27820db37..327d9269f7 100644
--- a/dpdk/drivers/bus/dpaa/dpaa_bus.c
+++ b/dpdk/drivers/bus/dpaa/dpaa_bus.c
@@ -700,6 +700,11 @@ dpaa_bus_dev_iterate(const void *start, const char *str,
 	struct rte_dpaa_device *dev;
 	char *dup, *dev_name = NULL;
 
+	if (str == NULL) {
+		DPAA_BUS_DEBUG("No device string");
+		return NULL;
+	}
+
 	/* Expectation is that device would be name=device_name */
 	if (strncmp(str, "name=", 5) != 0) {
 		DPAA_BUS_DEBUG("Invalid device string (%s)\n", str);
diff --git a/dpdk/drivers/bus/dpaa/rte_dpaa_bus.h b/dpdk/drivers/bus/dpaa/rte_dpaa_bus.h
index 9bf2cd9d68..373aca9785 100644
--- a/dpdk/drivers/bus/dpaa/rte_dpaa_bus.h
+++ b/dpdk/drivers/bus/dpaa/rte_dpaa_bus.h
@@ -132,7 +132,23 @@ static inline void *rte_dpaa_mem_ptov(phys_addr_t paddr)
 	}
 
 	/* If not, Fallback to full memseg list searching */
-	return rte_mem_iova2virt(paddr);
+	va = rte_mem_iova2virt(paddr);
+
+	dpaax_iova_table_update(paddr, va, RTE_CACHE_LINE_SIZE);
+
+	return va;
+}
+
+static inline rte_iova_t
+rte_dpaa_mem_vtop(void *vaddr)
+{
+	const struct rte_memseg *ms;
+
+	ms = rte_mem_virt2memseg(vaddr, NULL);
+	if (ms)
+		return ms->iova + RTE_PTR_DIFF(vaddr, ms->addr);
+
+	return (size_t)NULL;
 }
 
 /**
diff --git a/dpdk/drivers/bus/fslmc/fslmc_bus.c b/dpdk/drivers/bus/fslmc/fslmc_bus.c
index b3e964aa92..7431177f2e 100644
--- a/dpdk/drivers/bus/fslmc/fslmc_bus.c
+++ b/dpdk/drivers/bus/fslmc/fslmc_bus.c
@@ -608,6 +608,11 @@ fslmc_bus_dev_iterate(const void *start, const char *str,
 	struct rte_dpaa2_device *dev;
 	char *dup, *dev_name = NULL;
 
+	if (str == NULL) {
+		DPAA2_BUS_DEBUG("No device string");
+		return NULL;
+	}
+
 	/* Expectation is that device would be name=device_name */
 	if (strncmp(str, "name=", 5) != 0) {
 		DPAA2_BUS_DEBUG("Invalid device string (%s)\n", str);
diff --git a/dpdk/drivers/bus/fslmc/fslmc_vfio.c b/dpdk/drivers/bus/fslmc/fslmc_vfio.c
index 970969d2bf..bf9e3e49a5 100644
--- a/dpdk/drivers/bus/fslmc/fslmc_vfio.c
+++ b/dpdk/drivers/bus/fslmc/fslmc_vfio.c
@@ -448,11 +448,14 @@ fslmc_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 
 	/* get the actual group fd */
 	vfio_group_fd = rte_vfio_get_group_fd(iommu_group_no);
-	if (vfio_group_fd < 0)
+	if (vfio_group_fd < 0 && vfio_group_fd != -ENOENT)
 		return -1;
 
-	/* if group_fd == 0, that means the device isn't managed by VFIO */
-	if (vfio_group_fd == 0) {
+	/*
+	 * if vfio_group_fd == -ENOENT, that means the device
+	 * isn't managed by VFIO
+	 */
+	if (vfio_group_fd == -ENOENT) {
 		RTE_LOG(WARNING, EAL, " %s not managed by VFIO driver, skipping\n",
 				dev_addr);
 		return 1;
@@ -730,7 +733,6 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev)
 {
 	int ret;
 	intptr_t v_addr;
-	char *dev_name = NULL;
 	struct fsl_mc_io dpmng  = {0};
 	struct mc_version mc_ver_info = {0};
 
@@ -741,13 +743,6 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev)
 		goto cleanup;
 	}
 
-	dev_name = strdup(dev->device.name);
-	if (!dev_name) {
-		DPAA2_BUS_ERR("Unable to allocate MC device name memory");
-		ret = -ENOMEM;
-		goto cleanup;
-	}
-
 	v_addr = vfio_map_mcp_obj(dev->device.name);
 	if (v_addr == (intptr_t)MAP_FAILED) {
 		DPAA2_BUS_ERR("Error mapping region (errno = %d)", errno);
@@ -784,13 +779,9 @@ fslmc_process_mcp(struct rte_dpaa2_device *dev)
 	}
 	rte_mcp_ptr_list[0] = (void *)v_addr;
 
-	free(dev_name);
 	return 0;
 
 cleanup:
-	if (dev_name)
-		free(dev_name);
-
 	if (rte_mcp_ptr_list) {
 		free(rte_mcp_ptr_list);
 		rte_mcp_ptr_list = NULL;
diff --git a/dpdk/drivers/bus/fslmc/mc/fsl_mc_sys.h b/dpdk/drivers/bus/fslmc/mc/fsl_mc_sys.h
index d0c7b39f8d..a310c5697e 100644
--- a/dpdk/drivers/bus/fslmc/mc/fsl_mc_sys.h
+++ b/dpdk/drivers/bus/fslmc/mc/fsl_mc_sys.h
@@ -32,11 +32,10 @@ struct fsl_mc_io {
 #include <sys/uio.h>
 #include <linux/byteorder/little_endian.h>
 
-#ifndef dmb
-#define dmb() {__asm__ __volatile__("" : : : "memory"); }
-#endif
-#define __iormb()	dmb()
-#define __iowmb()	dmb()
+#include <rte_atomic.h>
+
+#define __iormb()	rte_io_rmb()
+#define __iowmb()	rte_io_wmb()
 #define __arch_getq(a)		(*(volatile uint64_t *)(a))
 #define __arch_putq(v, a)	(*(volatile uint64_t *)(a) = (v))
 #define __arch_putq32(v, a)	(*(volatile uint32_t *)(a) = (v))
diff --git a/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c b/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
index 3ca3ae4f51..9c09c69fe9 100644
--- a/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
+++ b/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_dpio.c
@@ -546,8 +546,13 @@ dpaa2_create_dpio_device(int vdev_fd,
 
 err:
 	if (dpio_dev->dpio) {
-		dpio_disable(dpio_dev->dpio, CMD_PRI_LOW, dpio_dev->token);
-		dpio_close(dpio_dev->dpio, CMD_PRI_LOW,  dpio_dev->token);
+		if (dpio_dev->token) {
+			dpio_disable(dpio_dev->dpio, CMD_PRI_LOW,
+				     dpio_dev->token);
+			dpio_close(dpio_dev->dpio, CMD_PRI_LOW,
+				   dpio_dev->token);
+		}
+
 		rte_free(dpio_dev->dpio);
 	}
 
diff --git a/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h b/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
index ab2b213f8d..00ef4ee539 100644
--- a/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
+++ b/dpdk/drivers/bus/fslmc/portal/dpaa2_hw_pvt.h
@@ -289,7 +289,7 @@ enum qbman_fd_format {
 #define DPAA2_GET_FD_FRC(fd)   ((fd)->simple.frc)
 #define DPAA2_GET_FD_FLC(fd) \
 	(((uint64_t)((fd)->simple.flc_hi) << 32) + (fd)->simple.flc_lo)
-#define DPAA2_GET_FD_ERR(fd)   ((fd)->simple.bpid_offset & 0x000000FF)
+#define DPAA2_GET_FD_ERR(fd)   ((fd)->simple.ctrl & 0x000000FF)
 #define DPAA2_GET_FLE_OFFSET(fle) (((fle)->fin_bpid_offset & 0x0FFF0000) >> 16)
 #define DPAA2_SET_FLE_SG_EXT(fle) ((fle)->fin_bpid_offset |= (uint64_t)1 << 29)
 #define DPAA2_IS_SET_FLE_SG_EXT(fle)	\
diff --git a/dpdk/drivers/bus/fslmc/qbman/qbman_debug.c b/dpdk/drivers/bus/fslmc/qbman/qbman_debug.c
index 0bb2ce880f..34374ae4b6 100644
--- a/dpdk/drivers/bus/fslmc/qbman/qbman_debug.c
+++ b/dpdk/drivers/bus/fslmc/qbman/qbman_debug.c
@@ -20,26 +20,27 @@ struct qbman_fq_query_desc {
 	uint8_t verb;
 	uint8_t reserved[3];
 	uint32_t fqid;
-	uint8_t reserved2[57];
+	uint8_t reserved2[56];
 };
 
 int qbman_fq_query_state(struct qbman_swp *s, uint32_t fqid,
 			 struct qbman_fq_query_np_rslt *r)
 {
 	struct qbman_fq_query_desc *p;
+	struct qbman_fq_query_np_rslt *var;
 
 	p = (struct qbman_fq_query_desc *)qbman_swp_mc_start(s);
 	if (!p)
 		return -EBUSY;
 
 	p->fqid = fqid;
-	*r = *(struct qbman_fq_query_np_rslt *)qbman_swp_mc_complete(s, p,
-						QBMAN_FQ_QUERY_NP);
-	if (!r) {
+	var = qbman_swp_mc_complete(s, p, QBMAN_FQ_QUERY_NP);
+	if (!var) {
 		pr_err("qbman: Query FQID %d NP fields failed, no response\n",
 		       fqid);
 		return -EIO;
 	}
+	*r = *var;
 
 	/* Decode the outcome */
 	QBMAN_BUG_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_FQ_QUERY_NP);
diff --git a/dpdk/drivers/bus/fslmc/qbman/qbman_portal.c b/dpdk/drivers/bus/fslmc/qbman/qbman_portal.c
index d4223bdc8b..54bea97820 100644
--- a/dpdk/drivers/bus/fslmc/qbman/qbman_portal.c
+++ b/dpdk/drivers/bus/fslmc/qbman/qbman_portal.c
@@ -999,6 +999,8 @@ static int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
 				QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
 		memcpy(&p[1], &cl[1], 28);
 		memcpy(&p[8], &fd[i], sizeof(*fd));
+		p[0] = cl[0] | s->eqcr.pi_vb;
+
 		if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
 			struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
 
@@ -1006,7 +1008,6 @@ static int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
 				((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
 		}
 		eqcr_pi++;
-		p[0] = cl[0] | s->eqcr.pi_vb;
 
 		if (!(eqcr_pi & half_mask))
 			s->eqcr.pi_vb ^= QB_VALID_BIT;
diff --git a/dpdk/drivers/bus/ifpga/ifpga_bus.c b/dpdk/drivers/bus/ifpga/ifpga_bus.c
index dfd6b1fba9..addbc3e86b 100644
--- a/dpdk/drivers/bus/ifpga/ifpga_bus.c
+++ b/dpdk/drivers/bus/ifpga/ifpga_bus.c
@@ -24,6 +24,7 @@
 #include <rte_kvargs.h>
 #include <rte_alarm.h>
 #include <rte_string_fns.h>
+#include <rte_debug.h>
 
 #include "rte_rawdev.h"
 #include "rte_rawdev_pmd.h"
diff --git a/dpdk/drivers/bus/ifpga/rte_bus_ifpga.h b/dpdk/drivers/bus/ifpga/rte_bus_ifpga.h
index 88a6289642..a6eeaaf568 100644
--- a/dpdk/drivers/bus/ifpga/rte_bus_ifpga.h
+++ b/dpdk/drivers/bus/ifpga/rte_bus_ifpga.h
@@ -17,6 +17,7 @@ extern "C" {
 
 #include <rte_bus.h>
 #include <rte_pci.h>
+#include <rte_interrupts.h>
 #include <rte_spinlock.h>
 
 /** Name of Intel FPGA Bus */
diff --git a/dpdk/drivers/bus/pci/bsd/pci.c b/dpdk/drivers/bus/pci/bsd/pci.c
index ebbfeb13a8..081c62ab06 100644
--- a/dpdk/drivers/bus/pci/bsd/pci.c
+++ b/dpdk/drivers/bus/pci/bsd/pci.c
@@ -392,55 +392,6 @@ pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
 	return RTE_IOVA_PA;
 }
 
-int
-pci_update_device(const struct rte_pci_addr *addr)
-{
-	int fd;
-	struct pci_conf matches[2];
-	struct pci_match_conf match = {
-		.pc_sel = {
-			.pc_domain = addr->domain,
-			.pc_bus = addr->bus,
-			.pc_dev = addr->devid,
-			.pc_func = addr->function,
-		},
-	};
-	struct pci_conf_io conf_io = {
-		.pat_buf_len = 0,
-		.num_patterns = 1,
-		.patterns = &match,
-		.match_buf_len = sizeof(matches),
-		.matches = &matches[0],
-	};
-
-	fd = open("/dev/pci", O_RDONLY);
-	if (fd < 0) {
-		RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
-		goto error;
-	}
-
-	if (ioctl(fd, PCIOCGETCONF, &conf_io) < 0) {
-		RTE_LOG(ERR, EAL, "%s(): error with ioctl on /dev/pci: %s\n",
-				__func__, strerror(errno));
-		goto error;
-	}
-
-	if (conf_io.num_matches != 1)
-		goto error;
-
-	if (pci_scan_one(fd, &matches[0]) < 0)
-		goto error;
-
-	close(fd);
-
-	return 0;
-
-error:
-	if (fd >= 0)
-		close(fd);
-	return -1;
-}
-
 /* Read PCI config space. */
 int rte_pci_read_config(const struct rte_pci_device *dev,
 		void *buf, size_t len, off_t offset)
diff --git a/dpdk/drivers/bus/pci/linux/pci.c b/dpdk/drivers/bus/pci/linux/pci.c
index 740a2cdad4..dba87f1275 100644
--- a/dpdk/drivers/bus/pci/linux/pci.c
+++ b/dpdk/drivers/bus/pci/linux/pci.c
@@ -377,6 +377,11 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 						 */
 						RTE_LOG(ERR, EAL, "Unexpected device scan at %s!\n",
 							filename);
+					else if (dev2->device.devargs !=
+						 dev->device.devargs) {
+						rte_devargs_remove(dev2->device.devargs);
+						pci_name_set(dev2);
+					}
 				}
 				free(dev);
 			}
@@ -389,18 +394,6 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
 	return 0;
 }
 
-int
-pci_update_device(const struct rte_pci_addr *addr)
-{
-	char filename[PATH_MAX];
-
-	snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT,
-		 rte_pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid,
-		 addr->function);
-
-	return pci_scan_one(filename, addr);
-}
-
 /*
  * split up a pci address into its constituent parts.
  */
diff --git a/dpdk/drivers/bus/pci/linux/pci_vfio.c b/dpdk/drivers/bus/pci/linux/pci_vfio.c
index 64cd84a689..a0bb1f5fd3 100644
--- a/dpdk/drivers/bus/pci/linux/pci_vfio.c
+++ b/dpdk/drivers/bus/pci/linux/pci_vfio.c
@@ -149,6 +149,38 @@ pci_vfio_get_msix_bar(int fd, struct pci_msix_table *msix_table)
 	return 0;
 }
 
+/* enable PCI bus memory space */
+static int
+pci_vfio_enable_bus_memory(int dev_fd)
+{
+	uint16_t cmd;
+	int ret;
+
+	ret = pread64(dev_fd, &cmd, sizeof(cmd),
+		      VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
+		      PCI_COMMAND);
+
+	if (ret != sizeof(cmd)) {
+		RTE_LOG(ERR, EAL, "Cannot read command from PCI config space!\n");
+		return -1;
+	}
+
+	if (cmd & PCI_COMMAND_MEMORY)
+		return 0;
+
+	cmd |= PCI_COMMAND_MEMORY;
+	ret = pwrite64(dev_fd, &cmd, sizeof(cmd),
+		       VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
+		       PCI_COMMAND);
+
+	if (ret != sizeof(cmd)) {
+		RTE_LOG(ERR, EAL, "Cannot write command to PCI config space!\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 /* set PCI bus mastering */
 static int
 pci_vfio_set_bus_master(int dev_fd, bool op)
@@ -427,6 +459,11 @@ pci_rte_vfio_setup_device(struct rte_pci_device *dev, int vfio_dev_fd)
 		return -1;
 	}
 
+	if (pci_vfio_enable_bus_memory(vfio_dev_fd)) {
+		RTE_LOG(ERR, EAL, "Cannot enable bus memory!\n");
+		return -1;
+	}
+
 	/* set bus mastering for the device */
 	if (pci_vfio_set_bus_master(vfio_dev_fd, true)) {
 		RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n");
@@ -789,7 +826,8 @@ pci_vfio_map_resource_primary(struct rte_pci_device *dev)
 err_vfio_res:
 	rte_free(vfio_res);
 err_vfio_dev_fd:
-	close(vfio_dev_fd);
+	rte_vfio_release_device(rte_pci_get_sysfs_path(),
+			pci_addr, vfio_dev_fd);
 	return -1;
 }
 
@@ -857,7 +895,8 @@ pci_vfio_map_resource_secondary(struct rte_pci_device *dev)
 
 	return 0;
 err_vfio_dev_fd:
-	close(vfio_dev_fd);
+	rte_vfio_release_device(rte_pci_get_sysfs_path(),
+			pci_addr, vfio_dev_fd);
 	return -1;
 }
 
@@ -966,7 +1005,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev)
 	}
 
 	TAILQ_REMOVE(vfio_res_list, vfio_res, next);
-
+	rte_free(vfio_res);
 	return 0;
 }
 
diff --git a/dpdk/drivers/bus/pci/pci_common.c b/dpdk/drivers/bus/pci/pci_common.c
index 3f55420769..ab73c009ac 100644
--- a/dpdk/drivers/bus/pci/pci_common.c
+++ b/dpdk/drivers/bus/pci/pci_common.c
@@ -288,8 +288,8 @@ pci_probe_all_drivers(struct rte_pci_device *dev)
  * all registered drivers that have a matching entry in its id_table
  * for discovered devices.
  */
-int
-rte_pci_probe(void)
+static int
+pci_probe(void)
 {
 	struct rte_pci_device *dev = NULL;
 	size_t probed = 0, failed = 0;
@@ -675,7 +675,7 @@ rte_pci_get_iommu_class(void)
 struct rte_pci_bus rte_pci_bus = {
 	.bus = {
 		.scan = rte_pci_scan,
-		.probe = rte_pci_probe,
+		.probe = pci_probe,
 		.find_device = pci_find_device,
 		.plug = pci_plug,
 		.unplug = pci_unplug,
diff --git a/dpdk/drivers/bus/pci/pci_common_uio.c b/dpdk/drivers/bus/pci/pci_common_uio.c
index 7ea73dbc5b..f4dca9da91 100644
--- a/dpdk/drivers/bus/pci/pci_common_uio.c
+++ b/dpdk/drivers/bus/pci/pci_common_uio.c
@@ -70,6 +70,7 @@ pci_uio_map_secondary(struct rte_pci_device *dev)
 				}
 				return -1;
 			}
+			dev->mem_resource[i].addr = mapaddr;
 		}
 		return 0;
 	}
diff --git a/dpdk/drivers/bus/pci/private.h b/dpdk/drivers/bus/pci/private.h
index a205d4d9f0..81735e4c0a 100644
--- a/dpdk/drivers/bus/pci/private.h
+++ b/dpdk/drivers/bus/pci/private.h
@@ -15,18 +15,6 @@ extern struct rte_pci_bus rte_pci_bus;
 struct rte_pci_driver;
 struct rte_pci_device;
 
-extern struct rte_pci_bus rte_pci_bus;
-
-/**
- * Probe the PCI bus
- *
- * @return
- *   - 0 on success.
- *   - !0 on error.
- */
-int
-rte_pci_probe(void);
-
 /**
  * Scan the content of the PCI bus, and the devices in the devices
  * list
@@ -67,19 +55,6 @@ void rte_pci_add_device(struct rte_pci_device *pci_dev);
 void rte_pci_insert_device(struct rte_pci_device *exist_pci_dev,
 		struct rte_pci_device *new_pci_dev);
 
-/**
- * Update a pci device object by asking the kernel for the latest information.
- *
- * This function is private to EAL.
- *
- * @param addr
- *	The PCI Bus-Device-Function address to look for
- * @return
- *   - 0 on success.
- *   - negative on error.
- */
-int pci_update_device(const struct rte_pci_addr *addr);
-
 /**
  * Map the PCI resource of a PCI device in virtual memory
  *
diff --git a/dpdk/drivers/bus/vdev/rte_bus_vdev.h b/dpdk/drivers/bus/vdev/rte_bus_vdev.h
index 2bc46530c9..78a032cea8 100644
--- a/dpdk/drivers/bus/vdev/rte_bus_vdev.h
+++ b/dpdk/drivers/bus/vdev/rte_bus_vdev.h
@@ -155,7 +155,7 @@ int rte_vdev_init(const char *name, const char *args);
  * Uninitalize a driver specified by name.
  *
  * @param name
- *   The pointer to a driver name to be initialized.
+ *   The pointer to a driver name to be uninitialized.
  * @return
  *  0 on success, negative on error
  */
diff --git a/dpdk/drivers/bus/vmbus/linux/vmbus_uio.c b/dpdk/drivers/bus/vmbus/linux/vmbus_uio.c
index 10e50c9b5a..5dc0c47de6 100644
--- a/dpdk/drivers/bus/vmbus/linux/vmbus_uio.c
+++ b/dpdk/drivers/bus/vmbus/linux/vmbus_uio.c
@@ -165,7 +165,7 @@ vmbus_uio_map_resource_by_index(struct rte_vmbus_device *dev, int idx,
 	dev->resource[idx].addr = mapaddr;
 	vmbus_map_addr = RTE_PTR_ADD(mapaddr, size);
 
-	/* Record result of sucessful mapping for use by secondary */
+	/* Record result of successful mapping for use by secondary */
 	maps[idx].addr = mapaddr;
 	maps[idx].size = size;
 
@@ -242,7 +242,7 @@ static int vmbus_uio_map_subchan(const struct rte_vmbus_device *dev,
 	*ring_size = file_size / 2;
 	*ring_buf = mapaddr;
 
-	vmbus_map_addr = RTE_PTR_ADD(ring_buf, file_size);
+	vmbus_map_addr = RTE_PTR_ADD(mapaddr, file_size);
 	return 0;
 }
 
diff --git a/dpdk/drivers/bus/vmbus/vmbus_common.c b/dpdk/drivers/bus/vmbus/vmbus_common.c
index 48a219f735..3adef01c95 100644
--- a/dpdk/drivers/bus/vmbus/vmbus_common.c
+++ b/dpdk/drivers/bus/vmbus/vmbus_common.c
@@ -131,7 +131,7 @@ vmbus_probe_one_driver(struct rte_vmbus_driver *dr,
 }
 
 /*
- * IF device class GUID mathces, call the probe function of
+ * If device class GUID matches, call the probe function of
  * registere drivers for the vmbus device.
  * Return -1 if initialization failed,
  * and 1 if no driver found for this device.
diff --git a/dpdk/drivers/common/cpt/cpt_ucode.h b/dpdk/drivers/common/cpt/cpt_ucode.h
index d5a0135d73..e92e3678c6 100644
--- a/dpdk/drivers/common/cpt/cpt_ucode.h
+++ b/dpdk/drivers/common/cpt/cpt_ucode.h
@@ -298,7 +298,7 @@ cpt_fc_ciph_set_key(void *ctx, cipher_type_t type, const uint8_t *key,
 		cpt_fc_ciph_set_key_kasumi_f8_cbc(cpt_ctx, key, key_len);
 		goto success;
 	default:
-		break;
+		return -1;
 	}
 
 	/* Only for FC_GEN case */
@@ -377,7 +377,7 @@ fill_sg_comp_from_iov(sg_comp_t *list,
 {
 	int32_t j;
 	uint32_t extra_len = extra_buf ? extra_buf->size : 0;
-	uint32_t size = *psize - extra_len;
+	uint32_t size = *psize;
 	buf_ptr_t *bufs;
 
 	bufs = from->bufs;
@@ -386,9 +386,6 @@ fill_sg_comp_from_iov(sg_comp_t *list,
 		uint32_t e_len;
 		sg_comp_t *to = &list[i >> 2];
 
-		if (!bufs[j].size)
-			continue;
-
 		if (unlikely(from_offset)) {
 			if (from_offset >= bufs[j].size) {
 				from_offset -= bufs[j].size;
@@ -420,18 +417,19 @@ fill_sg_comp_from_iov(sg_comp_t *list,
 				to->u.s.len[i % 4] = rte_cpu_to_be_16(e_len);
 			}
 
+			extra_len = RTE_MIN(extra_len, size);
 			/* Insert extra data ptr */
 			if (extra_len) {
 				i++;
 				to = &list[i >> 2];
 				to->u.s.len[i % 4] =
-					rte_cpu_to_be_16(extra_buf->size);
+					rte_cpu_to_be_16(extra_len);
 				to->ptr[i % 4] =
 					rte_cpu_to_be_64(extra_buf->dma_addr);
-
-				/* size already decremented by extra len */
+				size -= extra_len;
 			}
 
+			next_len = RTE_MIN(next_len, size);
 			/* insert the rest of the data */
 			if (next_len) {
 				i++;
@@ -720,9 +718,6 @@ cpt_enc_hmac_prep(uint32_t flags,
 	m_vaddr = (uint8_t *)m_vaddr + size;
 	m_dma += size;
 
-	if (hash_type == GMAC_TYPE)
-		encr_data_len = 0;
-
 	if (unlikely(!(flags & VALID_IV_BUF))) {
 		iv_len = 0;
 		iv_offset = ENCR_IV_OFFSET(d_offs);
@@ -754,6 +749,11 @@ cpt_enc_hmac_prep(uint32_t flags,
 	opcode.s.major = CPT_MAJOR_OP_FC;
 	opcode.s.minor = 0;
 
+	if (hash_type == GMAC_TYPE) {
+		encr_offset = 0;
+		encr_data_len = 0;
+	}
+
 	auth_dlen = auth_offset + auth_data_len;
 	enc_dlen = encr_data_len + encr_offset;
 	if (unlikely(encr_data_len & 0xf)) {
@@ -764,11 +764,6 @@ cpt_enc_hmac_prep(uint32_t flags,
 			enc_dlen = ROUNDUP16(encr_data_len) + encr_offset;
 	}
 
-	if (unlikely(hash_type == GMAC_TYPE)) {
-		encr_offset = auth_dlen;
-		enc_dlen = 0;
-	}
-
 	if (unlikely(auth_dlen > enc_dlen)) {
 		inputlen = auth_dlen;
 		outputlen = auth_dlen + mac_len;
@@ -1071,9 +1066,6 @@ cpt_dec_hmac_prep(uint32_t flags,
 	hash_type = cpt_ctx->hash_type;
 	mac_len = cpt_ctx->mac_len;
 
-	if (hash_type == GMAC_TYPE)
-		encr_data_len = 0;
-
 	if (unlikely(!(flags & VALID_IV_BUF))) {
 		iv_len = 0;
 		iv_offset = ENCR_IV_OFFSET(d_offs);
@@ -1130,6 +1122,11 @@ cpt_dec_hmac_prep(uint32_t flags,
 	opcode.s.major = CPT_MAJOR_OP_FC;
 	opcode.s.minor = 1;
 
+	if (hash_type == GMAC_TYPE) {
+		encr_offset = 0;
+		encr_data_len = 0;
+	}
+
 	enc_dlen = encr_offset + encr_data_len;
 	auth_dlen = auth_offset + auth_data_len;
 
@@ -1141,9 +1138,6 @@ cpt_dec_hmac_prep(uint32_t flags,
 		outputlen = enc_dlen;
 	}
 
-	if (hash_type == GMAC_TYPE)
-		encr_offset = inputlen;
-
 	vq_cmd_w0.u64 = 0;
 	vq_cmd_w0.s.param1 = encr_data_len;
 	vq_cmd_w0.s.param2 = auth_data_len;
@@ -2620,10 +2614,13 @@ fill_sess_aead(struct rte_crypto_sym_xform *xform,
 	sess->iv_length = aead_form->iv.length;
 	sess->aad_length = aead_form->aad_length;
 
-	cpt_fc_ciph_set_key(ctx, enc_type, aead_form->key.data,
-			aead_form->key.length, NULL);
+	if (unlikely(cpt_fc_ciph_set_key(ctx, enc_type, aead_form->key.data,
+			aead_form->key.length, NULL)))
+		return -1;
 
-	cpt_fc_auth_set_key(ctx, auth_type, NULL, 0, aead_form->digest_length);
+	if (unlikely(cpt_fc_auth_set_key(ctx, auth_type, NULL, 0,
+			aead_form->digest_length)))
+		return -1;
 
 	return 0;
 }
@@ -2723,8 +2720,9 @@ fill_sess_cipher(struct rte_crypto_sym_xform *xform,
 	sess->iv_length = c_form->iv.length;
 	sess->is_null = is_null;
 
-	cpt_fc_ciph_set_key(SESS_PRIV(sess), enc_type, c_form->key.data,
-			    c_form->key.length, NULL);
+	if (unlikely(cpt_fc_ciph_set_key(SESS_PRIV(sess), enc_type,
+			c_form->key.data, c_form->key.length, NULL)))
+		return -1;
 
 	return 0;
 }
@@ -2823,8 +2821,10 @@ fill_sess_auth(struct rte_crypto_sym_xform *xform,
 		sess->auth_iv_offset = a_form->iv.offset;
 		sess->auth_iv_length = a_form->iv.length;
 	}
-	cpt_fc_auth_set_key(SESS_PRIV(sess), auth_type, a_form->key.data,
-			    a_form->key.length, a_form->digest_length);
+	if (unlikely(cpt_fc_auth_set_key(SESS_PRIV(sess), auth_type,
+			a_form->key.data, a_form->key.length,
+			a_form->digest_length)))
+		return -1;
 
 	return 0;
 }
@@ -2867,9 +2867,13 @@ fill_sess_gmac(struct rte_crypto_sym_xform *xform,
 	sess->iv_length = a_form->iv.length;
 	sess->mac_len = a_form->digest_length;
 
-	cpt_fc_ciph_set_key(ctx, enc_type, a_form->key.data,
-			a_form->key.length, NULL);
-	cpt_fc_auth_set_key(ctx, auth_type, NULL, 0, a_form->digest_length);
+	if (unlikely(cpt_fc_ciph_set_key(ctx, enc_type, a_form->key.data,
+			a_form->key.length, NULL)))
+		return -1;
+
+	if (unlikely(cpt_fc_auth_set_key(ctx, auth_type, NULL, 0,
+			a_form->digest_length)))
+		return -1;
 
 	return 0;
 }
diff --git a/dpdk/drivers/common/dpaax/caamflib/desc.h b/dpdk/drivers/common/dpaax/caamflib/desc.h
index e4139aaa9f..635d6bad07 100644
--- a/dpdk/drivers/common/dpaax/caamflib/desc.h
+++ b/dpdk/drivers/common/dpaax/caamflib/desc.h
@@ -26,7 +26,7 @@ extern enum rta_sec_era rta_sec_era;
 #define CAAM_CMD_SZ sizeof(uint32_t)
 #define CAAM_PTR_SZ sizeof(dma_addr_t)
 #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
-#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
+#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 7 + CAAM_PTR_SZ * 3)
 
 /* Block size of any entity covered/uncovered with a KEK/TKEK */
 #define KEK_BLOCKSIZE		16
diff --git a/dpdk/drivers/common/dpaax/caamflib/desc/pdcp.h b/dpdk/drivers/common/dpaax/caamflib/desc/pdcp.h
index b5e2d24e47..476115323c 100644
--- a/dpdk/drivers/common/dpaax/caamflib/desc/pdcp.h
+++ b/dpdk/drivers/common/dpaax/caamflib/desc/pdcp.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
  * Copyright 2008-2013 Freescale Semiconductor, Inc.
- * Copyright 2019 NXP
+ * Copyright 2019-2020 NXP
  */
 
 #ifndef __DESC_PDCP_H__
@@ -262,6 +262,50 @@ enum pdb_type_e {
 	PDCP_PDB_TYPE_INVALID
 };
 
+/**
+ * rta_inline_pdcp_query() - Provide indications if a key can be passed as
+ *                           immediate data or shall be referenced in a
+ *                           shared descriptor.
+ * Return: 0 if data can be inlined or 1 if referenced.
+ */
+static inline int
+rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
+		      enum cipher_type_pdcp cipher_alg,
+		      enum pdcp_sn_size sn_size,
+		      int8_t hfn_ovd)
+{
+	/**
+	 * Shared Descriptors for some of the cases does not fit in the
+	 * MAX_DESC_SIZE of the descriptor especially when non-protocol
+	 * descriptors are formed as in 18bit cases and when HFN override
+	 * is enabled as 2 extra words are added in the job descriptor.
+	 * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
+	 * enabled and 18bit uplane and either of following Algo combinations.
+	 * - SNOW-AES
+	 * - AES-SNOW
+	 * - SNOW-SNOW
+	 * - ZUC-SNOW
+	 *
+	 * We cannot make inline for all cases, as this will impact performance
+	 * due to extra memory accesses for the keys.
+	 */
+	if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
+			(sn_size == PDCP_SN_SIZE_18) &&
+			((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
+				auth_alg == PDCP_AUTH_TYPE_AES) ||
+			(cipher_alg == PDCP_CIPHER_TYPE_AES &&
+				auth_alg == PDCP_AUTH_TYPE_SNOW) ||
+			(cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
+				auth_alg == PDCP_AUTH_TYPE_SNOW) ||
+			(cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
+				auth_alg == PDCP_AUTH_TYPE_SNOW))) {
+
+		return 1;
+	}
+
+	return 0;
+}
+
 /*
  * Function for appending the portion of a PDCP Control Plane shared descriptor
  * which performs NULL encryption and integrity (i.e. copies the input frame
@@ -3484,6 +3528,15 @@ cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
 				KEY(p, KEY2, authdata->key_enc_flags,
 				    (uint64_t)authdata->key, authdata->keylen,
 				    INLINE_KEY(authdata));
+			else if (authdata && authdata->algtype == 0) {
+				err = pdcp_insert_uplane_with_int_op(p, swap,
+						cipherdata, authdata,
+						sn_size, era_2_sw_hfn_ovrd,
+						OP_TYPE_DECAP_PROTOCOL);
+				if (err)
+					return err;
+				break;
+			}
 
 			/* Insert Cipher Key */
 			KEY(p, KEY1, cipherdata->key_enc_flags,
diff --git a/dpdk/drivers/common/octeontx/octeontx_mbox.c b/dpdk/drivers/common/octeontx/octeontx_mbox.c
index 2fd2531072..effe0b267e 100644
--- a/dpdk/drivers/common/octeontx/octeontx_mbox.c
+++ b/dpdk/drivers/common/octeontx/octeontx_mbox.c
@@ -279,7 +279,7 @@ octeontx_start_domain(void)
 }
 
 static int
-octeontx_check_mbox_version(struct mbox_intf_ver app_intf_ver,
+octeontx_check_mbox_version(struct mbox_intf_ver *app_intf_ver,
 			    struct mbox_intf_ver *intf_ver)
 {
 	struct mbox_intf_ver kernel_intf_ver = {0};
@@ -290,8 +290,9 @@ octeontx_check_mbox_version(struct mbox_intf_ver app_intf_ver,
 	hdr.coproc = NO_COPROC;
 	hdr.msg = RM_INTERFACE_VERSION;
 
-	result = octeontx_mbox_send(&hdr, &app_intf_ver, sizeof(app_intf_ver),
-			&kernel_intf_ver, sizeof(kernel_intf_ver));
+	result = octeontx_mbox_send(&hdr, app_intf_ver,
+				    sizeof(struct mbox_intf_ver),
+				    &kernel_intf_ver, sizeof(kernel_intf_ver));
 	if (result != sizeof(kernel_intf_ver)) {
 		mbox_log_err("Could not send interface version. Err=%d. FuncErr=%d\n",
 			     result, hdr.res_code);
@@ -301,9 +302,9 @@ octeontx_check_mbox_version(struct mbox_intf_ver app_intf_ver,
 	if (intf_ver)
 		*intf_ver = kernel_intf_ver;
 
-	if (app_intf_ver.platform != kernel_intf_ver.platform ||
-			app_intf_ver.major != kernel_intf_ver.major ||
-			app_intf_ver.minor != kernel_intf_ver.minor)
+	if (app_intf_ver->platform != kernel_intf_ver.platform ||
+			app_intf_ver->major != kernel_intf_ver.major ||
+			app_intf_ver->minor != kernel_intf_ver.minor)
 		result = -EINVAL;
 
 	return result;
@@ -312,7 +313,7 @@ octeontx_check_mbox_version(struct mbox_intf_ver app_intf_ver,
 int
 octeontx_mbox_init(void)
 {
-	const struct mbox_intf_ver MBOX_INTERFACE_VERSION = {
+	struct mbox_intf_ver MBOX_INTERFACE_VERSION = {
 		.platform = 0x01,
 		.major = 0x01,
 		.minor = 0x03
@@ -330,7 +331,7 @@ octeontx_mbox_init(void)
 		return ret;
 	}
 
-	ret = octeontx_check_mbox_version(MBOX_INTERFACE_VERSION,
+	ret = octeontx_check_mbox_version(&MBOX_INTERFACE_VERSION,
 					  &rm_intf_ver);
 	if (ret < 0) {
 		mbox_log_err("MBOX version: Kernel(%d.%d.%d) != DPDK(%d.%d.%d)",
diff --git a/dpdk/drivers/common/octeontx2/hw/otx2_npc.h b/dpdk/drivers/common/octeontx2/hw/otx2_npc.h
index a0536e0aed..600084ff31 100644
--- a/dpdk/drivers/common/octeontx2/hw/otx2_npc.h
+++ b/dpdk/drivers/common/octeontx2/hw/otx2_npc.h
@@ -201,7 +201,8 @@ enum npc_kpu_lb_ltype {
 };
 
 enum npc_kpu_lc_ltype {
-	NPC_LT_LC_IP = 1,
+	NPC_LT_LC_PTP = 1,
+	NPC_LT_LC_IP,
 	NPC_LT_LC_IP_OPT,
 	NPC_LT_LC_IP6,
 	NPC_LT_LC_IP6_EXT,
@@ -209,11 +210,10 @@ enum npc_kpu_lc_ltype {
 	NPC_LT_LC_RARP,
 	NPC_LT_LC_MPLS,
 	NPC_LT_LC_NSH,
-	NPC_LT_LC_PTP,
 	NPC_LT_LC_FCOE,
 };
 
-/* Don't modify Ltypes upto SCTP, otherwise it will
+/* Don't modify Ltypes up to SCTP, otherwise it will
  * effect flow tag calculation and thus RSS.
  */
 enum npc_kpu_ld_ltype {
@@ -260,7 +260,7 @@ enum npc_kpu_lg_ltype {
 	NPC_LT_LG_TU_ETHER_IN_NSH,
 };
 
-/* Don't modify Ltypes upto SCTP, otherwise it will
+/* Don't modify Ltypes up to SCTP, otherwise it will
  * effect flow tag calculation and thus RSS.
  */
 enum npc_kpu_lh_ltype {
diff --git a/dpdk/drivers/common/octeontx2/otx2_io_arm64.h b/dpdk/drivers/common/octeontx2/otx2_io_arm64.h
index 7e45329b38..3380c9874f 100644
--- a/dpdk/drivers/common/octeontx2/otx2_io_arm64.h
+++ b/dpdk/drivers/common/octeontx2/otx2_io_arm64.h
@@ -21,6 +21,12 @@
 #define otx2_prefetch_store_keep(ptr) ({\
 	asm volatile("prfm pstl1keep, [%x0]\n" : : "r" (ptr)); })
 
+#if defined(__ARM_FEATURE_SVE)
+#define __LSE_PREAMBLE " .cpu  generic+lse+sve\n"
+#else
+#define __LSE_PREAMBLE " .cpu  generic+lse\n"
+#endif
+
 static __rte_always_inline uint64_t
 otx2_atomic64_add_nosync(int64_t incr, int64_t *ptr)
 {
@@ -28,7 +34,7 @@ otx2_atomic64_add_nosync(int64_t incr, int64_t *ptr)
 
 	/* Atomic add with no ordering */
 	asm volatile (
-		".cpu  generic+lse\n"
+		__LSE_PREAMBLE
 		"ldadd %x[i], %x[r], [%[b]]"
 		: [r] "=r" (result), "+m" (*ptr)
 		: [i] "r" (incr), [b] "r" (ptr)
@@ -43,7 +49,7 @@ otx2_atomic64_add_sync(int64_t incr, int64_t *ptr)
 
 	/* Atomic add with ordering */
 	asm volatile (
-		".cpu  generic+lse\n"
+		__LSE_PREAMBLE
 		"ldadda %x[i], %x[r], [%[b]]"
 		: [r] "=r" (result), "+m" (*ptr)
 		: [i] "r" (incr), [b] "r" (ptr)
@@ -57,7 +63,7 @@ otx2_lmt_submit(rte_iova_t io_address)
 	uint64_t result;
 
 	asm volatile (
-		".cpu  generic+lse\n"
+		__LSE_PREAMBLE
 		"ldeor xzr,%x[rf],[%[rs]]" :
 		 [rf] "=r"(result): [rs] "r"(io_address));
 	return result;
@@ -92,4 +98,5 @@ otx2_lmt_mov_seg(void *out, const void *in, const uint16_t segdw)
 		dst128[i] = src128[i];
 }
 
+#undef __LSE_PREAMBLE
 #endif /* _OTX2_IO_ARM64_H_ */
diff --git a/dpdk/drivers/common/octeontx2/otx2_mbox.c b/dpdk/drivers/common/octeontx2/otx2_mbox.c
index c359bf42f3..18bf5b88ee 100644
--- a/dpdk/drivers/common/octeontx2/otx2_mbox.c
+++ b/dpdk/drivers/common/octeontx2/otx2_mbox.c
@@ -9,6 +9,7 @@
 
 #include <rte_atomic.h>
 #include <rte_cycles.h>
+#include <rte_malloc.h>
 
 #include "otx2_mbox.h"
 
@@ -35,7 +36,7 @@ otx2_mbox_fini(struct otx2_mbox *mbox)
 {
 	mbox->reg_base = 0;
 	mbox->hwbase = 0;
-	free(mbox->dev);
+	rte_free(mbox->dev);
 	mbox->dev = NULL;
 }
 
@@ -126,7 +127,9 @@ otx2_mbox_init(struct otx2_mbox *mbox, uintptr_t hwbase,
 		return -ENODEV;
 	}
 
-	mbox->dev = malloc(ndevs * sizeof(struct otx2_mbox_dev));
+	mbox->dev = rte_zmalloc("mbox dev",
+				ndevs * sizeof(struct otx2_mbox_dev),
+				OTX2_ALIGN);
 	if (!mbox->dev) {
 		otx2_mbox_fini(mbox);
 		return -ENOMEM;
diff --git a/dpdk/drivers/common/qat/qat_adf/icp_qat_fw.h b/dpdk/drivers/common/qat/qat_adf/icp_qat_fw.h
index 8f7cb37b43..be10fc9bde 100644
--- a/dpdk/drivers/common/qat/qat_adf/icp_qat_fw.h
+++ b/dpdk/drivers/common/qat/qat_adf/icp_qat_fw.h
@@ -121,6 +121,8 @@ struct icp_qat_fw_comn_resp {
 #define ICP_QAT_FW_COMN_CNV_FLAG_MASK 0x1
 #define ICP_QAT_FW_COMN_CNVNR_FLAG_BITPOS 5
 #define ICP_QAT_FW_COMN_CNVNR_FLAG_MASK 0x1
+#define ICP_QAT_FW_COMN_NULL_VERSION_FLAG_BITPOS 0
+#define ICP_QAT_FW_COMN_NULL_VERSION_FLAG_MASK 0x1
 
 #define ICP_QAT_FW_COMN_OV_SRV_TYPE_GET(icp_qat_fw_comn_req_hdr_t) \
 	icp_qat_fw_comn_req_hdr_t.service_type
@@ -175,6 +177,9 @@ struct icp_qat_fw_comn_resp {
 #define QAT_COMN_PTR_TYPE_SGL 0x1
 #define QAT_COMN_CD_FLD_TYPE_64BIT_ADR 0x0
 #define QAT_COMN_CD_FLD_TYPE_16BYTE_DATA 0x1
+#define QAT_COMN_EXT_FLAGS_BITPOS 8
+#define QAT_COMN_EXT_FLAGS_MASK 0x1
+#define QAT_COMN_EXT_FLAGS_USED 0x1
 
 #define ICP_QAT_FW_COMN_FLAGS_BUILD(cdt, ptr) \
 	((((cdt) & QAT_COMN_CD_FLD_TYPE_MASK) << QAT_COMN_CD_FLD_TYPE_BITPOS) \
diff --git a/dpdk/drivers/common/qat/qat_adf/icp_qat_fw_la.h b/dpdk/drivers/common/qat/qat_adf/icp_qat_fw_la.h
index 38891eb1f9..20eb145def 100644
--- a/dpdk/drivers/common/qat/qat_adf/icp_qat_fw_la.h
+++ b/dpdk/drivers/common/qat/qat_adf/icp_qat_fw_la.h
@@ -273,6 +273,8 @@ struct icp_qat_fw_cipher_auth_cd_ctrl_hdr {
 
 #define ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED 1
 #define ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED 0
+#define ICP_QAT_FW_AUTH_HDR_FLAG_SNOW3G_UIA2_BITPOS 3
+#define ICP_QAT_FW_AUTH_HDR_FLAG_ZUC_EIA3_BITPOS 4
 #define ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX	240
 #define ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET 24
 #define ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET (0)
diff --git a/dpdk/drivers/common/qat/qat_common.c b/dpdk/drivers/common/qat/qat_common.c
index 4753866976..5343a1451e 100644
--- a/dpdk/drivers/common/qat/qat_common.c
+++ b/dpdk/drivers/common/qat/qat_common.c
@@ -94,6 +94,9 @@ void qat_stats_get(struct qat_pci_device *dev,
 		stats->dequeued_count += qp[i]->stats.dequeued_count;
 		stats->enqueue_err_count += qp[i]->stats.enqueue_err_count;
 		stats->dequeue_err_count += qp[i]->stats.dequeue_err_count;
+		stats->threshold_hit_count += qp[i]->stats.threshold_hit_count;
+		QAT_LOG(DEBUG, "Threshold was used for qp %d %"PRIu64" times",
+				i, stats->threshold_hit_count);
 	}
 }
 
diff --git a/dpdk/drivers/common/qat/qat_common.h b/dpdk/drivers/common/qat/qat_common.h
index de9a3ba555..cf840fea9b 100644
--- a/dpdk/drivers/common/qat/qat_common.h
+++ b/dpdk/drivers/common/qat/qat_common.h
@@ -61,6 +61,9 @@ struct qat_common_stats {
 	/**< Total error count on operations enqueued */
 	uint64_t dequeue_err_count;
 	/**< Total error count on operations dequeued */
+	uint64_t threshold_hit_count;
+	/**< Total number of times min qp threshold condition was fulfilled */
+
 };
 
 struct qat_pci_device;
diff --git a/dpdk/drivers/common/qat/qat_device.c b/dpdk/drivers/common/qat/qat_device.c
index 2a1cf3e179..e3d2b9c79a 100644
--- a/dpdk/drivers/common/qat/qat_device.c
+++ b/dpdk/drivers/common/qat/qat_device.c
@@ -3,6 +3,8 @@
  */
 
 #include <rte_string_fns.h>
+#include <rte_devargs.h>
+#include <ctype.h>
 
 #include "qat_device.h"
 #include "adf_transport_access_macros.h"
@@ -30,8 +32,8 @@ struct qat_gen_hw_data qat_gen_config[] =  {
 	},
 };
 
-
-static struct qat_pci_device qat_pci_devices[RTE_PMD_QAT_MAX_PCI_DEVICES];
+/* per-process array of device data */
+struct qat_device_info qat_pci_devs[RTE_PMD_QAT_MAX_PCI_DEVICES];
 static int qat_nb_pci_devices;
 
 /*
@@ -57,27 +59,21 @@ static const struct rte_pci_id pci_id_qat_map[] = {
 		{.device_id = 0},
 };
 
-static struct qat_pci_device *
-qat_pci_get_dev(uint8_t dev_id)
-{
-	return &qat_pci_devices[dev_id];
-}
-
 static struct qat_pci_device *
 qat_pci_get_named_dev(const char *name)
 {
-	struct qat_pci_device *dev;
 	unsigned int i;
 
 	if (name == NULL)
 		return NULL;
 
 	for (i = 0; i < RTE_PMD_QAT_MAX_PCI_DEVICES; i++) {
-		dev = &qat_pci_devices[i];
-
-		if ((dev->attached == QAT_ATTACHED) &&
-				(strcmp(dev->name, name) == 0))
-			return dev;
+		if (qat_pci_devs[i].mz &&
+				(strcmp(((struct qat_pci_device *)
+				qat_pci_devs[i].mz->addr)->name, name)
+				== 0))
+			return (struct qat_pci_device *)
+				qat_pci_devs[i].mz->addr;
 	}
 
 	return NULL;
@@ -88,8 +84,9 @@ qat_pci_find_free_device_index(void)
 {
 	uint8_t dev_id;
 
-	for (dev_id = 0; dev_id < RTE_PMD_QAT_MAX_PCI_DEVICES; dev_id++) {
-		if (qat_pci_devices[dev_id].attached == QAT_DETACHED)
+	for (dev_id = 0; dev_id < RTE_PMD_QAT_MAX_PCI_DEVICES;
+			dev_id++) {
+		if (qat_pci_devs[dev_id].mz == NULL)
 			break;
 	}
 	return dev_id;
@@ -105,15 +102,95 @@ qat_get_qat_dev_from_pci_dev(struct rte_pci_device *pci_dev)
 	return qat_pci_get_named_dev(name);
 }
 
+static void qat_dev_parse_cmd(const char *str, struct qat_dev_cmd_param
+		*qat_dev_cmd_param)
+{
+	int i = 0;
+	const char *param;
+
+	while (1) {
+		char value_str[4] = { };
+
+		param = qat_dev_cmd_param[i].name;
+		if (param == NULL)
+			return;
+		long value = 0;
+		const char *arg = strstr(str, param);
+		const char *arg2 = NULL;
+
+		if (arg) {
+			arg2 = arg + strlen(param);
+			if (*arg2 != '=') {
+			QAT_LOG(DEBUG, "parsing error '=' sign"
+						" should immediately follow %s",
+						param);
+				arg2 = NULL;
+			} else
+				arg2++;
+		} else {
+			QAT_LOG(DEBUG, "%s not provided", param);
+		}
+		if (arg2) {
+			int iter = 0;
+
+			while (iter < 2) {
+				if (!isdigit(*(arg2 + iter)))
+					break;
+				iter++;
+			}
+			if (!iter) {
+				QAT_LOG(DEBUG, "parsing error %s"
+					       " no number provided",
+					       param);
+			} else {
+				memcpy(value_str, arg2, iter);
+				value = strtol(value_str, NULL, 10);
+				if (value > MAX_QP_THRESHOLD_SIZE) {
+					QAT_LOG(DEBUG, "Exceeded max size of"
+						" threshold, setting to %d",
+						MAX_QP_THRESHOLD_SIZE);
+					value = MAX_QP_THRESHOLD_SIZE;
+				}
+				QAT_LOG(DEBUG, "parsing %s = %ld",
+						param, value);
+			}
+		}
+		qat_dev_cmd_param[i].val = value;
+		i++;
+	}
+}
+
 struct qat_pci_device *
-qat_pci_device_allocate(struct rte_pci_device *pci_dev)
+qat_pci_device_allocate(struct rte_pci_device *pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param)
 {
 	struct qat_pci_device *qat_dev;
-	uint8_t qat_dev_id;
+	uint8_t qat_dev_id = 0;
 	char name[QAT_DEV_NAME_MAX_LEN];
+	struct rte_devargs *devargs = pci_dev->device.devargs;
 
 	rte_pci_device_name(&pci_dev->addr, name, sizeof(name));
 	snprintf(name+strlen(name), QAT_DEV_NAME_MAX_LEN-strlen(name), "_qat");
+
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		const struct rte_memzone *mz = rte_memzone_lookup(name);
+
+		if (mz == NULL) {
+			QAT_LOG(ERR,
+				"Secondary can't find %s mz, did primary create device?",
+				name);
+			return NULL;
+		}
+		qat_dev = mz->addr;
+		qat_pci_devs[qat_dev->qat_dev_id].mz = mz;
+		qat_pci_devs[qat_dev->qat_dev_id].pci_dev = pci_dev;
+		qat_nb_pci_devices++;
+		QAT_LOG(DEBUG, "QAT device %d found, name %s, total QATs %d",
+			qat_dev->qat_dev_id, qat_dev->name, qat_nb_pci_devices);
+		return qat_dev;
+	}
+
+
 	if (qat_pci_get_named_dev(name) != NULL) {
 		QAT_LOG(ERR, "QAT device with name %s already allocated!",
 				name);
@@ -126,12 +203,22 @@ qat_pci_device_allocate(struct rte_pci_device *pci_dev)
 		return NULL;
 	}
 
-	qat_dev = qat_pci_get_dev(qat_dev_id);
+	qat_pci_devs[qat_dev_id].mz = rte_memzone_reserve(name,
+		sizeof(struct qat_pci_device),
+		rte_socket_id(), 0);
+
+	if (qat_pci_devs[qat_dev_id].mz == NULL) {
+		QAT_LOG(ERR, "Error when allocating memzone for QAT_%d",
+			qat_dev_id);
+		return NULL;
+	}
+
+	qat_dev = qat_pci_devs[qat_dev_id].mz->addr;
 	memset(qat_dev, 0, sizeof(*qat_dev));
 	strlcpy(qat_dev->name, name, QAT_DEV_NAME_MAX_LEN);
 	qat_dev->qat_dev_id = qat_dev_id;
-	qat_dev->pci_dev = pci_dev;
-	switch (qat_dev->pci_dev->id.device_id) {
+	qat_pci_devs[qat_dev_id].pci_dev = pci_dev;
+	switch (pci_dev->id.device_id) {
 	case 0x0443:
 		qat_dev->qat_dev_gen = QAT_GEN1;
 		break;
@@ -145,17 +232,19 @@ qat_pci_device_allocate(struct rte_pci_device *pci_dev)
 		break;
 	default:
 		QAT_LOG(ERR, "Invalid dev_id, can't determine generation");
+		rte_memzone_free(qat_pci_devs[qat_dev->qat_dev_id].mz);
 		return NULL;
 	}
 
-	rte_spinlock_init(&qat_dev->arb_csr_lock);
+	if (devargs && devargs->drv_str)
+		qat_dev_parse_cmd(devargs->drv_str, qat_dev_cmd_param);
 
-	qat_dev->attached = QAT_ATTACHED;
+	rte_spinlock_init(&qat_dev->arb_csr_lock);
 
 	qat_nb_pci_devices++;
 
-	QAT_LOG(DEBUG, "QAT device %d allocated, name %s, total QATs %d",
-			qat_dev->qat_dev_id, qat_dev->name, qat_nb_pci_devices);
+	QAT_LOG(DEBUG, "QAT device %d found, name %s, total QATs %d",
+		qat_dev->qat_dev_id, qat_dev->name, qat_nb_pci_devices);
 
 	return qat_dev;
 }
@@ -165,6 +254,7 @@ qat_pci_device_release(struct rte_pci_device *pci_dev)
 {
 	struct qat_pci_device *qat_dev;
 	char name[QAT_DEV_NAME_MAX_LEN];
+	int busy = 0;
 
 	if (pci_dev == NULL)
 		return -EINVAL;
@@ -174,15 +264,35 @@ qat_pci_device_release(struct rte_pci_device *pci_dev)
 	qat_dev = qat_pci_get_named_dev(name);
 	if (qat_dev != NULL) {
 
+		struct qat_device_info *inst =
+				&qat_pci_devs[qat_dev->qat_dev_id];
 		/* Check that there are no service devs still on pci device */
-		if (qat_dev->sym_dev != NULL)
-			return -EBUSY;
 
-		qat_dev->attached = QAT_DETACHED;
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+			if (qat_dev->sym_dev != NULL) {
+				QAT_LOG(DEBUG, "QAT sym device %s is busy",
+					name);
+				busy = 1;
+			}
+			if (qat_dev->asym_dev != NULL) {
+				QAT_LOG(DEBUG, "QAT asym device %s is busy",
+					name);
+				busy = 1;
+			}
+			if (qat_dev->comp_dev != NULL) {
+				QAT_LOG(DEBUG, "QAT comp device %s is busy",
+					name);
+				busy = 1;
+			}
+			if (busy)
+				return -EBUSY;
+			rte_memzone_free(inst->mz);
+		}
+		memset(inst, 0, sizeof(struct qat_device_info));
 		qat_nb_pci_devices--;
+		QAT_LOG(DEBUG, "QAT device %s released, total QATs %d",
+					name, qat_nb_pci_devices);
 	}
-	QAT_LOG(DEBUG, "QAT device %s released, total QATs %d",
-				name, qat_nb_pci_devices);
 	return 0;
 }
 
@@ -199,37 +309,44 @@ qat_pci_dev_destroy(struct qat_pci_device *qat_pci_dev,
 static int qat_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		struct rte_pci_device *pci_dev)
 {
-	int ret = 0;
+	int sym_ret = 0, asym_ret = 0, comp_ret = 0;
 	int num_pmds_created = 0;
 	struct qat_pci_device *qat_pci_dev;
+	struct qat_dev_cmd_param qat_dev_cmd_param[] = {
+			{ SYM_ENQ_THRESHOLD_NAME, 0 },
+			{ ASYM_ENQ_THRESHOLD_NAME, 0 },
+			{ COMP_ENQ_THRESHOLD_NAME, 0 },
+			{ NULL, 0 },
+	};
 
 	QAT_LOG(DEBUG, "Found QAT device at %02x:%02x.%x",
 			pci_dev->addr.bus,
 			pci_dev->addr.devid,
 			pci_dev->addr.function);
 
-	qat_pci_dev = qat_pci_device_allocate(pci_dev);
+	qat_pci_dev = qat_pci_device_allocate(pci_dev, qat_dev_cmd_param);
 	if (qat_pci_dev == NULL)
 		return -ENODEV;
 
-	ret = qat_sym_dev_create(qat_pci_dev);
-	if (ret == 0)
+	sym_ret = qat_sym_dev_create(qat_pci_dev, qat_dev_cmd_param);
+	if (sym_ret == 0) {
 		num_pmds_created++;
+	}
 	else
 		QAT_LOG(WARNING,
 				"Failed to create QAT SYM PMD on device %s",
 				qat_pci_dev->name);
 
-	ret = qat_comp_dev_create(qat_pci_dev);
-	if (ret == 0)
+	comp_ret = qat_comp_dev_create(qat_pci_dev, qat_dev_cmd_param);
+	if (comp_ret == 0)
 		num_pmds_created++;
 	else
 		QAT_LOG(WARNING,
 				"Failed to create QAT COMP PMD on device %s",
 				qat_pci_dev->name);
 
-	ret = qat_asym_dev_create(qat_pci_dev);
-	if (ret == 0)
+	asym_ret = qat_asym_dev_create(qat_pci_dev, qat_dev_cmd_param);
+	if (asym_ret == 0)
 		num_pmds_created++;
 	else
 		QAT_LOG(WARNING,
@@ -264,13 +381,15 @@ static struct rte_pci_driver rte_qat_pmd = {
 };
 
 __rte_weak int
-qat_sym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused)
+qat_sym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused,
+		struct qat_dev_cmd_param *qat_dev_cmd_param __rte_unused)
 {
 	return 0;
 }
 
 __rte_weak int
-qat_asym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused)
+qat_asym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused,
+		struct qat_dev_cmd_param *qat_dev_cmd_param __rte_unused)
 {
 	return 0;
 }
@@ -288,7 +407,8 @@ qat_asym_dev_destroy(struct qat_pci_device *qat_pci_dev __rte_unused)
 }
 
 __rte_weak int
-qat_comp_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused)
+qat_comp_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused,
+		struct qat_dev_cmd_param *qat_dev_cmd_param __rte_unused)
 {
 	return 0;
 }
@@ -301,3 +421,4 @@ qat_comp_dev_destroy(struct qat_pci_device *qat_pci_dev __rte_unused)
 
 RTE_PMD_REGISTER_PCI(QAT_PCI_NAME, rte_qat_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(QAT_PCI_NAME, pci_id_qat_map);
+RTE_PMD_REGISTER_KMOD_DEP(QAT_PCI_NAME, "* igb_uio | uio_pci_generic | vfio-pci");
diff --git a/dpdk/drivers/common/qat/qat_device.h b/dpdk/drivers/common/qat/qat_device.h
index 131375e838..c3f5ae8990 100644
--- a/dpdk/drivers/common/qat/qat_device.h
+++ b/dpdk/drivers/common/qat/qat_device.h
@@ -16,12 +16,53 @@
 
 #define QAT_DEV_NAME_MAX_LEN	64
 
+#define SYM_ENQ_THRESHOLD_NAME "qat_sym_enq_threshold"
+#define ASYM_ENQ_THRESHOLD_NAME "qat_asym_enq_threshold"
+#define COMP_ENQ_THRESHOLD_NAME "qat_comp_enq_threshold"
+#define MAX_QP_THRESHOLD_SIZE	32
+
+struct qat_dev_cmd_param {
+	const char *name;
+	uint16_t val;
+};
+
 enum qat_comp_num_im_buffers {
 	QAT_NUM_INTERM_BUFS_GEN1 = 12,
 	QAT_NUM_INTERM_BUFS_GEN2 = 20,
 	QAT_NUM_INTERM_BUFS_GEN3 = 20
 };
 
+struct qat_device_info {
+	const struct rte_memzone *mz;
+	/**< mz to store the qat_pci_device so it can be
+	 * shared across processes
+	 */
+	struct rte_pci_device *pci_dev;
+	struct rte_device sym_rte_dev;
+	/**< This represents the crypto sym subset of this pci device.
+	 * Register with this rather than with the one in
+	 * pci_dev so that its driver can have a crypto-specific name
+	 */
+
+	struct rte_device asym_rte_dev;
+	/**< This represents the crypto asym subset of this pci device.
+	 * Register with this rather than with the one in
+	 * pci_dev so that its driver can have a crypto-specific name
+	 */
+
+	struct rte_device comp_rte_dev;
+	/**< This represents the compression subset of this pci device.
+	 * Register with this rather than with the one in
+	 * pci_dev so that its driver can have a compression-specific name
+	 */
+};
+
+extern struct qat_device_info qat_pci_devs[];
+
+struct qat_sym_dev_private;
+struct qat_asym_dev_private;
+struct qat_comp_dev_private;
+
 /*
  * This struct holds all the data about a QAT pci device
  * including data about all services it supports.
@@ -29,27 +70,20 @@ enum qat_comp_num_im_buffers {
  *  - hw_data
  *  - config data
  *  - runtime data
+ * Note: as this data can be shared in a multi-process scenario,
+ * any pointers in it must also point to shared memory.
  */
-struct qat_sym_dev_private;
-struct qat_asym_dev_private;
-struct qat_comp_dev_private;
-
 struct qat_pci_device {
 
 	/* Data used by all services */
 	char name[QAT_DEV_NAME_MAX_LEN];
 	/**< Name of qat pci device */
 	uint8_t qat_dev_id;
-	/**< Device instance for this qat pci device */
-	struct rte_pci_device *pci_dev;
-	/**< PCI information. */
+	/**< Id of device instance for this qat pci device */
 	enum qat_device_gen qat_dev_gen;
 	/**< QAT device generation */
 	rte_spinlock_t arb_csr_lock;
 	/**< lock to protect accesses to the arbiter CSR */
-	__extension__
-	uint8_t attached : 1;
-	/**< Flag indicating the device is attached */
 
 	struct qat_qp *qps_in_use[QAT_MAX_SERVICES][ADF_MAX_QPS_ON_ANY_SERVICE];
 	/**< links to qps set up for each service, index same as on API */
@@ -57,32 +91,20 @@ struct qat_pci_device {
 	/* Data relating to symmetric crypto service */
 	struct qat_sym_dev_private *sym_dev;
 	/**< link back to cryptodev private data */
-	struct rte_device sym_rte_dev;
-	/**< This represents the crypto sym subset of this pci device.
-	 * Register with this rather than with the one in
-	 * pci_dev so that its driver can have a crypto-specific name
-	 */
+
+	int qat_sym_driver_id;
+	/**< Symmetric driver id used by this device */
 
 	/* Data relating to asymmetric crypto service */
 	struct qat_asym_dev_private *asym_dev;
 	/**< link back to cryptodev private data */
-	struct rte_device asym_rte_dev;
-	/**< This represents the crypto asym subset of this pci device.
-	 * Register with this rather than with the one in
-	 * pci_dev so that its driver can have a crypto-specific name
-	 */
+
+	int qat_asym_driver_id;
+	/**< Symmetric driver id used by this device */
 
 	/* Data relating to compression service */
 	struct qat_comp_dev_private *comp_dev;
 	/**< link back to compressdev private data */
-	struct rte_device comp_rte_dev;
-	/**< This represents the compression subset of this pci device.
-	 * Register with this rather than with the one in
-	 * pci_dev so that its driver can have a compression-specific name
-	 */
-
-	/* Data relating to asymmetric crypto service */
-
 };
 
 struct qat_gen_hw_data {
@@ -94,7 +116,8 @@ struct qat_gen_hw_data {
 extern struct qat_gen_hw_data qat_gen_config[];
 
 struct qat_pci_device *
-qat_pci_device_allocate(struct rte_pci_device *pci_dev);
+qat_pci_device_allocate(struct rte_pci_device *pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
 qat_pci_device_release(struct rte_pci_device *pci_dev);
@@ -104,10 +127,12 @@ qat_get_qat_dev_from_pci_dev(struct rte_pci_device *pci_dev);
 
 /* declaration needed for weak functions */
 int
-qat_sym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused);
+qat_sym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
-qat_asym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused);
+qat_asym_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
 qat_sym_dev_destroy(struct qat_pci_device *qat_pci_dev __rte_unused);
@@ -116,7 +141,8 @@ int
 qat_asym_dev_destroy(struct qat_pci_device *qat_pci_dev __rte_unused);
 
 int
-qat_comp_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused);
+qat_comp_dev_create(struct qat_pci_device *qat_pci_dev __rte_unused,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
 qat_comp_dev_destroy(struct qat_pci_device *qat_pci_dev __rte_unused);
diff --git a/dpdk/drivers/common/qat/qat_qp.c b/dpdk/drivers/common/qat/qat_qp.c
index 03f11f869e..3f30871562 100644
--- a/dpdk/drivers/common/qat/qat_qp.c
+++ b/dpdk/drivers/common/qat/qat_qp.c
@@ -3,6 +3,7 @@
  */
 
 #include <rte_common.h>
+#include <rte_cycles.h>
 #include <rte_dev.h>
 #include <rte_malloc.h>
 #include <rte_memzone.h>
@@ -19,6 +20,7 @@
 #include "qat_comp.h"
 #include "adf_transport_access_macros.h"
 
+#define QAT_CQ_MAX_DEQ_RETRIES 10
 
 #define ADF_MAX_DESC				4096
 #define ADF_MIN_DESC				128
@@ -191,7 +193,8 @@ int qat_qp_setup(struct qat_pci_device *qat_dev,
 
 {
 	struct qat_qp *qp;
-	struct rte_pci_device *pci_dev = qat_dev->pci_dev;
+	struct rte_pci_device *pci_dev =
+			qat_pci_devs[qat_dev->qat_dev_id].pci_dev;
 	char op_cookie_pool_name[RTE_RING_NAMESIZE];
 	uint32_t i;
 
@@ -230,7 +233,7 @@ int qat_qp_setup(struct qat_pci_device *qat_dev,
 	}
 
 	qp->mmap_bar_addr = pci_dev->mem_resource[0].addr;
-	qp->inflights16 = 0;
+	qp->enqueued = qp->dequeued = 0;
 
 	if (qat_queue_create(qat_dev, &(qp->tx_q), qat_qp_conf,
 					ADF_RING_DIR_TX) != 0) {
@@ -239,6 +242,15 @@ int qat_qp_setup(struct qat_pci_device *qat_dev,
 		goto create_err;
 	}
 
+	qp->max_inflights = ADF_MAX_INFLIGHTS(qp->tx_q.queue_size,
+				ADF_BYTES_TO_MSG_SIZE(qp->tx_q.msg_size));
+
+	if (qp->max_inflights < 2) {
+		QAT_LOG(ERR, "Invalid num inflights");
+		qat_queue_delete(&(qp->tx_q));
+		goto create_err;
+	}
+
 	if (qat_queue_create(qat_dev, &(qp->rx_q), qat_qp_conf,
 					ADF_RING_DIR_RX) != 0) {
 		QAT_LOG(ERR, "Rx queue create failed "
@@ -263,7 +275,7 @@ int qat_qp_setup(struct qat_pci_device *qat_dev,
 				qp->nb_descriptors,
 				qat_qp_conf->cookie_size, 64, 0,
 				NULL, NULL, NULL, NULL,
-				qat_dev->pci_dev->device.numa_node,
+				pci_dev->device.numa_node,
 				0);
 	if (!qp->op_cookie_pool) {
 		QAT_LOG(ERR, "QAT PMD Cannot create"
@@ -312,7 +324,7 @@ int qat_qp_release(struct qat_qp **qp_addr)
 				qp->qat_dev->qat_dev_id);
 
 	/* Don't free memory if there are still responses to be processed */
-	if (qp->inflights16 == 0) {
+	if ((qp->enqueued - qp->dequeued) == 0) {
 		qat_queue_delete(&(qp->tx_q));
 		qat_queue_delete(&(qp->rx_q));
 	} else {
@@ -368,7 +380,8 @@ qat_queue_create(struct qat_pci_device *qat_dev, struct qat_queue *queue,
 	uint64_t queue_base;
 	void *io_addr;
 	const struct rte_memzone *qp_mz;
-	struct rte_pci_device *pci_dev = qat_dev->pci_dev;
+	struct rte_pci_device *pci_dev =
+			qat_pci_devs[qat_dev->qat_dev_id].pci_dev;
 	int ret = 0;
 	uint16_t desc_size = (dir == ADF_RING_DIR_TX ?
 			qp_conf->hw->tx_msg_size : qp_conf->hw->rx_msg_size);
@@ -392,7 +405,7 @@ qat_queue_create(struct qat_pci_device *qat_dev, struct qat_queue *queue,
 		qp_conf->service_str, "qp_mem",
 		queue->hw_bundle_number, queue->hw_queue_number);
 	qp_mz = queue_dma_zone_reserve(queue->memz_name, queue_size_bytes,
-			qat_dev->pci_dev->device.numa_node);
+			pci_dev->device.numa_node);
 	if (qp_mz == NULL) {
 		QAT_LOG(ERR, "Failed to allocate ring memzone");
 		return -ENOMEM;
@@ -416,15 +429,7 @@ qat_queue_create(struct qat_pci_device *qat_dev, struct qat_queue *queue,
 		goto queue_create_err;
 	}
 
-	queue->max_inflights = ADF_MAX_INFLIGHTS(queue->queue_size,
-					ADF_BYTES_TO_MSG_SIZE(desc_size));
 	queue->modulo_mask = (1 << ADF_RING_SIZE_MODULO(queue->queue_size)) - 1;
-
-	if (queue->max_inflights < 2) {
-		QAT_LOG(ERR, "Invalid num inflights");
-		ret = -EINVAL;
-		goto queue_create_err;
-	}
 	queue->head = 0;
 	queue->tail = 0;
 	queue->msg_size = desc_size;
@@ -443,11 +448,11 @@ qat_queue_create(struct qat_pci_device *qat_dev, struct qat_queue *queue,
 			queue->hw_queue_number, queue_base);
 
 	QAT_LOG(DEBUG, "RING: Name:%s, size in CSR: %u, in bytes %u,"
-		" nb msgs %u, msg_size %u, max_inflights %u modulo mask %u",
+		" nb msgs %u, msg_size %u, modulo mask %u",
 			queue->memz_name,
 			queue->queue_size, queue_size_bytes,
 			qp_conf->nb_descriptors, desc_size,
-			queue->max_inflights, queue->modulo_mask);
+			queue->modulo_mask);
 
 	return 0;
 
@@ -538,7 +543,6 @@ static inline void
 txq_write_tail(struct qat_qp *qp, struct qat_queue *q) {
 	WRITE_CSR_RING_TAIL(qp->mmap_bar_addr, q->hw_bundle_number,
 			q->hw_queue_number, q->tail);
-	q->nb_pending_requests = 0;
 	q->csr_tail = q->tail;
 }
 
@@ -575,11 +579,10 @@ qat_enqueue_op_burst(void *qp, void **ops, uint16_t nb_ops)
 	register struct qat_queue *queue;
 	struct qat_qp *tmp_qp = (struct qat_qp *)qp;
 	register uint32_t nb_ops_sent = 0;
-	register int ret;
+	register int ret = -1;
 	uint16_t nb_ops_possible = nb_ops;
 	register uint8_t *base_addr;
 	register uint32_t tail;
-	int overflow;
 
 	if (unlikely(nb_ops == 0))
 		return 0;
@@ -590,26 +593,59 @@ qat_enqueue_op_burst(void *qp, void **ops, uint16_t nb_ops)
 	tail = queue->tail;
 
 	/* Find how many can actually fit on the ring */
-	tmp_qp->inflights16 += nb_ops;
-	overflow = tmp_qp->inflights16 - queue->max_inflights;
-	if (overflow > 0) {
-		tmp_qp->inflights16 -= overflow;
-		nb_ops_possible = nb_ops - overflow;
-		if (nb_ops_possible == 0)
+	{
+		/* dequeued can only be written by one thread, but it may not
+		 * be this thread. As it's 4-byte aligned it will be read
+		 * atomically here by any Intel CPU.
+		 * enqueued can wrap before dequeued, but cannot
+		 * lap it as var size of enq/deq (uint32_t) > var size of
+		 * max_inflights (uint16_t). In reality inflights is never
+		 * even as big as max uint16_t, as it's <= ADF_MAX_DESC.
+		 * On wrapping, the calculation still returns the correct
+		 * positive value as all three vars are unsigned.
+		 */
+		uint32_t inflights =
+			tmp_qp->enqueued - tmp_qp->dequeued;
+
+		if ((inflights + nb_ops) > tmp_qp->max_inflights) {
+			nb_ops_possible = tmp_qp->max_inflights - inflights;
+			if (nb_ops_possible == 0)
+				return 0;
+		}
+		/* QAT has plenty of work queued already, so don't waste cycles
+		 * enqueueing, wait til the application has gathered a bigger
+		 * burst or some completed ops have been dequeued
+		 */
+		if (tmp_qp->min_enq_burst_threshold && inflights >
+				QAT_QP_MIN_INFL_THRESHOLD && nb_ops_possible <
+				tmp_qp->min_enq_burst_threshold) {
+			tmp_qp->stats.threshold_hit_count++;
 			return 0;
+		}
 	}
 
 	while (nb_ops_sent != nb_ops_possible) {
-		ret = tmp_qp->build_request(*ops, base_addr + tail,
+		if (tmp_qp->service_type == QAT_SERVICE_SYMMETRIC) {
+#ifdef BUILD_QAT_SYM
+			ret = qat_sym_build_request(*ops, base_addr + tail,
+				tmp_qp->op_cookies[tail / queue->msg_size],
+				tmp_qp->qat_dev_gen);
+#endif
+		} else if (tmp_qp->service_type == QAT_SERVICE_COMPRESSION) {
+			ret = qat_comp_build_request(*ops, base_addr + tail,
+				tmp_qp->op_cookies[tail / queue->msg_size],
+				tmp_qp->qat_dev_gen);
+		} else if (tmp_qp->service_type == QAT_SERVICE_ASYMMETRIC) {
+#ifdef BUILD_QAT_ASYM
+			ret = qat_asym_build_request(*ops, base_addr + tail,
 				tmp_qp->op_cookies[tail / queue->msg_size],
 				tmp_qp->qat_dev_gen);
+#endif
+		}
+
 		if (ret != 0) {
 			tmp_qp->stats.enqueue_err_count++;
-			/*
-			 * This message cannot be enqueued,
-			 * decrease number of ops that wasn't sent
-			 */
-			tmp_qp->inflights16 -= nb_ops_possible - nb_ops_sent;
+			/* This message cannot be enqueued */
 			if (nb_ops_sent == 0)
 				return 0;
 			goto kick_tail;
@@ -621,26 +657,22 @@ qat_enqueue_op_burst(void *qp, void **ops, uint16_t nb_ops)
 	}
 kick_tail:
 	queue->tail = tail;
+	tmp_qp->enqueued += nb_ops_sent;
 	tmp_qp->stats.enqueued_count += nb_ops_sent;
-	queue->nb_pending_requests += nb_ops_sent;
-	if (tmp_qp->inflights16 < QAT_CSR_TAIL_FORCE_WRITE_THRESH ||
-		    queue->nb_pending_requests > QAT_CSR_TAIL_WRITE_THRESH) {
-		txq_write_tail(tmp_qp, queue);
-	}
+	txq_write_tail(tmp_qp, queue);
 	return nb_ops_sent;
 }
 
 uint16_t
 qat_dequeue_op_burst(void *qp, void **ops, uint16_t nb_ops)
 {
-	struct qat_queue *rx_queue, *tx_queue;
+	struct qat_queue *rx_queue;
 	struct qat_qp *tmp_qp = (struct qat_qp *)qp;
 	uint32_t head;
 	uint32_t resp_counter = 0;
 	uint8_t *resp_msg;
 
 	rx_queue = &(tmp_qp->rx_q);
-	tx_queue = &(tmp_qp->tx_q);
 	head = rx_queue->head;
 	resp_msg = (uint8_t *)rx_queue->base_addr + rx_queue->head;
 
@@ -669,22 +701,109 @@ qat_dequeue_op_burst(void *qp, void **ops, uint16_t nb_ops)
 	}
 	if (resp_counter > 0) {
 		rx_queue->head = head;
+		tmp_qp->dequeued += resp_counter;
 		tmp_qp->stats.dequeued_count += resp_counter;
 		rx_queue->nb_processed_responses += resp_counter;
-		tmp_qp->inflights16 -= resp_counter;
 
 		if (rx_queue->nb_processed_responses >
 						QAT_CSR_HEAD_WRITE_THRESH)
 			rxq_free_desc(tmp_qp, rx_queue);
 	}
-	/* also check if tail needs to be advanced */
-	if (tmp_qp->inflights16 <= QAT_CSR_TAIL_FORCE_WRITE_THRESH &&
-		tx_queue->tail != tx_queue->csr_tail) {
-		txq_write_tail(tmp_qp, tx_queue);
-	}
+
 	return resp_counter;
 }
 
+/* This is almost same as dequeue_op_burst, without the atomic, without stats
+ * and without the op. Dequeues one response.
+ */
+static uint8_t
+qat_cq_dequeue_response(struct qat_qp *qp, void *out_data)
+{
+	uint8_t result = 0;
+	uint8_t retries = 0;
+	struct qat_queue *queue = &(qp->rx_q);
+	struct icp_qat_fw_comn_resp *resp_msg = (struct icp_qat_fw_comn_resp *)
+			((uint8_t *)queue->base_addr + queue->head);
+
+	while (retries++ < QAT_CQ_MAX_DEQ_RETRIES &&
+			*(uint32_t *)resp_msg == ADF_RING_EMPTY_SIG) {
+		/* loop waiting for response until we reach the timeout */
+		rte_delay_ms(20);
+	}
+
+	if (*(uint32_t *)resp_msg != ADF_RING_EMPTY_SIG) {
+		/* response received */
+		result = 1;
+
+		/* check status flag */
+		if (ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(
+				resp_msg->comn_hdr.comn_status) ==
+				ICP_QAT_FW_COMN_STATUS_FLAG_OK) {
+			/* success */
+			memcpy(out_data, resp_msg, queue->msg_size);
+		} else {
+			memset(out_data, 0, queue->msg_size);
+		}
+
+		queue->head = adf_modulo(queue->head + queue->msg_size,
+				queue->modulo_mask);
+		rxq_free_desc(qp, queue);
+	}
+
+	return result;
+}
+
+/* Sends a NULL message and extracts QAT fw version from the response.
+ * Used to determine detailed capabilities based on the fw version number.
+ * This assumes that there are no inflight messages, i.e. assumes there's space
+ * on the qp, one message is sent and only one response collected.
+ * Returns fw version number or 0 for unknown version or a negative error code.
+ */
+int
+qat_cq_get_fw_version(struct qat_qp *qp)
+{
+	struct qat_queue *queue = &(qp->tx_q);
+	uint8_t *base_addr = (uint8_t *)queue->base_addr;
+	struct icp_qat_fw_comn_req null_msg;
+	struct icp_qat_fw_comn_resp response;
+
+	/* prepare the NULL request */
+	memset(&null_msg, 0, sizeof(null_msg));
+	null_msg.comn_hdr.hdr_flags =
+		ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET);
+	null_msg.comn_hdr.service_type = ICP_QAT_FW_COMN_REQ_NULL;
+	null_msg.comn_hdr.service_cmd_id = ICP_QAT_FW_NULL_REQ_SERV_ID;
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+	QAT_DP_HEXDUMP_LOG(DEBUG, "NULL request", &null_msg, sizeof(null_msg));
+#endif
+
+	/* send the NULL request */
+	memcpy(base_addr + queue->tail, &null_msg, sizeof(null_msg));
+	queue->tail = adf_modulo(queue->tail + queue->msg_size,
+			queue->modulo_mask);
+	txq_write_tail(qp, queue);
+
+	/* receive a response */
+	if (qat_cq_dequeue_response(qp, &response)) {
+
+#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
+		QAT_DP_HEXDUMP_LOG(DEBUG, "NULL response:", &response,
+				sizeof(response));
+#endif
+		/* if LW0 bit 24 is set - then the fw version was returned */
+		if (QAT_FIELD_GET(response.comn_hdr.hdr_flags,
+				ICP_QAT_FW_COMN_NULL_VERSION_FLAG_BITPOS,
+				ICP_QAT_FW_COMN_NULL_VERSION_FLAG_MASK))
+			return response.resrvd[0]; /* return LW4 */
+		else
+			return 0; /* not set - we don't know fw version */
+	}
+
+	QAT_LOG(ERR, "No response received");
+	return -EINVAL;
+}
+
 __rte_weak int
 qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
 			  void *op_cookie __rte_unused,
diff --git a/dpdk/drivers/common/qat/qat_qp.h b/dpdk/drivers/common/qat/qat_qp.h
index 980c2ba323..47ad5dd203 100644
--- a/dpdk/drivers/common/qat/qat_qp.h
+++ b/dpdk/drivers/common/qat/qat_qp.h
@@ -11,10 +11,8 @@ struct qat_pci_device;
 
 #define QAT_CSR_HEAD_WRITE_THRESH 32U
 /* number of requests to accumulate before writing head CSR */
-#define QAT_CSR_TAIL_WRITE_THRESH 32U
-/* number of requests to accumulate before writing tail CSR */
-#define QAT_CSR_TAIL_FORCE_WRITE_THRESH 256U
-/* number of inflights below which no tail write coalescing should occur */
+
+#define QAT_QP_MIN_INFL_THRESHOLD	256
 
 typedef int (*build_request_t)(void *op,
 		uint8_t *req, void *op_cookie,
@@ -55,7 +53,6 @@ struct qat_queue {
 	uint32_t	tail;			/* Shadow copy of the tail */
 	uint32_t	modulo_mask;
 	uint32_t	msg_size;
-	uint16_t	max_inflights;
 	uint32_t	queue_size;
 	uint8_t		hw_bundle_number;
 	uint8_t		hw_queue_number;
@@ -64,13 +61,10 @@ struct qat_queue {
 	uint32_t	csr_tail;		/* last written tail value */
 	uint16_t	nb_processed_responses;
 	/* number of responses processed since last CSR head write */
-	uint16_t	nb_pending_requests;
-	/* number of requests pending since last CSR tail write */
 };
 
 struct qat_qp {
 	void			*mmap_bar_addr;
-	uint16_t		inflights16;
 	struct qat_queue	tx_q;
 	struct qat_queue	rx_q;
 	struct qat_common_stats stats;
@@ -82,6 +76,10 @@ struct qat_qp {
 	enum qat_service_type service_type;
 	struct qat_pci_device *qat_dev;
 	/**< qat device this qp is on */
+	uint32_t enqueued;
+	uint32_t dequeued __rte_aligned(4);
+	uint16_t max_inflights;
+	uint16_t min_enq_burst_threshold;
 } __rte_cache_aligned;
 
 extern const struct qat_qp_hw_data qat_gen1_qps[][ADF_MAX_QPS_ON_ANY_SERVICE];
@@ -105,6 +103,9 @@ int
 qat_qps_per_service(const struct qat_qp_hw_data *qp_hw_data,
 			enum qat_service_type service);
 
+int
+qat_cq_get_fw_version(struct qat_qp *qp);
+
 /* Needed for weak function*/
 int
 qat_comp_process_response(void **op __rte_unused, uint8_t *resp __rte_unused,
diff --git a/dpdk/drivers/compress/isal/isal_compress_pmd_ops.c b/dpdk/drivers/compress/isal/isal_compress_pmd_ops.c
index 31c4559915..7d03749da3 100644
--- a/dpdk/drivers/compress/isal/isal_compress_pmd_ops.c
+++ b/dpdk/drivers/compress/isal/isal_compress_pmd_ops.c
@@ -249,16 +249,27 @@ isal_comp_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
 	qp->stream = rte_zmalloc_socket("Isa-l compression stream ",
 			sizeof(struct isal_zstream),  RTE_CACHE_LINE_SIZE,
 			socket_id);
-
+	if (qp->stream == NULL) {
+		ISAL_PMD_LOG(ERR, "Failed to allocate compression stream memory");
+		goto qp_setup_cleanup;
+	}
 	/* Initialize memory for compression level buffer */
 	qp->stream->level_buf = rte_zmalloc_socket("Isa-l compression lev_buf",
 			ISAL_DEF_LVL3_DEFAULT, RTE_CACHE_LINE_SIZE,
 			socket_id);
+	if (qp->stream->level_buf == NULL) {
+		ISAL_PMD_LOG(ERR, "Failed to allocate compression level_buf memory");
+		goto qp_setup_cleanup;
+	}
 
 	/* Initialize memory for decompression state structure */
 	qp->state = rte_zmalloc_socket("Isa-l decompression state",
 			sizeof(struct inflate_state), RTE_CACHE_LINE_SIZE,
 			socket_id);
+	if (qp->state == NULL) {
+		ISAL_PMD_LOG(ERR, "Failed to allocate decompression state memory");
+		goto qp_setup_cleanup;
+	}
 
 	qp->id = qp_id;
 	dev->data->queue_pairs[qp_id] = qp;
@@ -284,8 +295,11 @@ isal_comp_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
 	return 0;
 
 qp_setup_cleanup:
-	if (qp)
-		rte_free(qp);
+	if (qp->stream)
+		rte_free(qp->stream->level_buf);
+	rte_free(qp->stream);
+	rte_free(qp->state);
+	rte_free(qp);
 
 	return -1;
 }
diff --git a/dpdk/drivers/compress/isal/meson.build b/dpdk/drivers/compress/isal/meson.build
index 25578880db..b039dfdfc5 100644
--- a/dpdk/drivers/compress/isal/meson.build
+++ b/dpdk/drivers/compress/isal/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright 2018 Intel Corporation
 
-dep = dependency('libisal', required: false)
+dep = dependency('libisal', required: false, method: 'pkg-config')
 if not dep.found()
 	build = false
 	reason = 'missing dependency, "libisal"'
diff --git a/dpdk/drivers/compress/octeontx/otx_zip_pmd.c b/dpdk/drivers/compress/octeontx/otx_zip_pmd.c
index 9e00c86630..bff8ef035e 100644
--- a/dpdk/drivers/compress/octeontx/otx_zip_pmd.c
+++ b/dpdk/drivers/compress/octeontx/otx_zip_pmd.c
@@ -406,7 +406,7 @@ zip_pmd_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
 
 	qp->name = name;
 
-	/* Create completion queue upto max_inflight_ops */
+	/* Create completion queue up to max_inflight_ops */
 	qp->processed_pkts = zip_pmd_qp_create_processed_pkts_ring(qp,
 						max_inflight_ops, socket_id);
 	if (qp->processed_pkts == NULL)
diff --git a/dpdk/drivers/compress/qat/qat_comp_pmd.c b/dpdk/drivers/compress/qat/qat_comp_pmd.c
index 05b7dfe774..5cdabadef7 100644
--- a/dpdk/drivers/compress/qat/qat_comp_pmd.c
+++ b/dpdk/drivers/compress/qat/qat_comp_pmd.c
@@ -139,6 +139,7 @@ qat_comp_qp_setup(struct rte_compressdev *dev, uint16_t qp_id,
 								= *qp_addr;
 
 	qp = (struct qat_qp *)*qp_addr;
+	qp->min_enq_burst_threshold = qat_private->min_enq_burst_threshold;
 
 	for (i = 0; i < qp->nb_descriptors; i++) {
 
@@ -660,8 +661,12 @@ static const struct rte_driver compdev_qat_driver = {
 	.alias = qat_comp_drv_name
 };
 int
-qat_comp_dev_create(struct qat_pci_device *qat_pci_dev)
+qat_comp_dev_create(struct qat_pci_device *qat_pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param)
 {
+	int i = 0;
+	struct qat_device_info *qat_dev_instance =
+			&qat_pci_devs[qat_pci_dev->qat_dev_id];
 	if (qat_pci_dev->qat_dev_gen == QAT_GEN3) {
 		QAT_LOG(ERR, "Compression PMD not supported on QAT c4xxx");
 		return 0;
@@ -669,24 +674,27 @@ qat_comp_dev_create(struct qat_pci_device *qat_pci_dev)
 
 	struct rte_compressdev_pmd_init_params init_params = {
 		.name = "",
-		.socket_id = qat_pci_dev->pci_dev->device.numa_node,
+		.socket_id = qat_dev_instance->pci_dev->device.numa_node,
 	};
 	char name[RTE_COMPRESSDEV_NAME_MAX_LEN];
+	char capa_memz_name[RTE_COMPRESSDEV_NAME_MAX_LEN];
 	struct rte_compressdev *compressdev;
 	struct qat_comp_dev_private *comp_dev;
+	const struct rte_compressdev_capabilities *capabilities;
+	uint64_t capa_size;
 
 	snprintf(name, RTE_COMPRESSDEV_NAME_MAX_LEN, "%s_%s",
 			qat_pci_dev->name, "comp");
 	QAT_LOG(DEBUG, "Creating QAT COMP device %s", name);
 
 	/* Populate subset device to use in compressdev device creation */
-	qat_pci_dev->comp_rte_dev.driver = &compdev_qat_driver;
-	qat_pci_dev->comp_rte_dev.numa_node =
-					qat_pci_dev->pci_dev->device.numa_node;
-	qat_pci_dev->comp_rte_dev.devargs = NULL;
+	qat_dev_instance->comp_rte_dev.driver = &compdev_qat_driver;
+	qat_dev_instance->comp_rte_dev.numa_node =
+			qat_dev_instance->pci_dev->device.numa_node;
+	qat_dev_instance->comp_rte_dev.devargs = NULL;
 
 	compressdev = rte_compressdev_pmd_create(name,
-			&(qat_pci_dev->comp_rte_dev),
+			&(qat_dev_instance->comp_rte_dev),
 			sizeof(struct qat_comp_dev_private),
 			&init_params);
 
@@ -700,25 +708,62 @@ qat_comp_dev_create(struct qat_pci_device *qat_pci_dev)
 
 	compressdev->feature_flags = RTE_COMPDEV_FF_HW_ACCELERATED;
 
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	snprintf(capa_memz_name, RTE_COMPRESSDEV_NAME_MAX_LEN,
+			"QAT_COMP_CAPA_GEN_%d",
+			qat_pci_dev->qat_dev_gen);
+
 	comp_dev = compressdev->data->dev_private;
 	comp_dev->qat_dev = qat_pci_dev;
 	comp_dev->compressdev = compressdev;
-	qat_pci_dev->comp_dev = comp_dev;
 
 	switch (qat_pci_dev->qat_dev_gen) {
 	case QAT_GEN1:
 	case QAT_GEN2:
 	case QAT_GEN3:
-		comp_dev->qat_dev_capabilities = qat_comp_gen_capabilities;
+		capabilities = qat_comp_gen_capabilities;
+		capa_size = sizeof(qat_comp_gen_capabilities);
 		break;
 	default:
-		comp_dev->qat_dev_capabilities = qat_comp_gen_capabilities;
+		capabilities = qat_comp_gen_capabilities;
+		capa_size = sizeof(qat_comp_gen_capabilities);
 		QAT_LOG(DEBUG,
 			"QAT gen %d capabilities unknown, default to GEN1",
 					qat_pci_dev->qat_dev_gen);
 		break;
 	}
 
+	comp_dev->capa_mz = rte_memzone_lookup(capa_memz_name);
+	if (comp_dev->capa_mz == NULL) {
+		comp_dev->capa_mz = rte_memzone_reserve(capa_memz_name,
+			capa_size,
+			rte_socket_id(), 0);
+	}
+	if (comp_dev->capa_mz == NULL) {
+		QAT_LOG(DEBUG,
+			"Error allocating memzone for capabilities, destroying PMD for %s",
+			name);
+		memset(&qat_dev_instance->comp_rte_dev, 0,
+			sizeof(qat_dev_instance->comp_rte_dev));
+		rte_compressdev_pmd_destroy(compressdev);
+		return -EFAULT;
+	}
+
+	memcpy(comp_dev->capa_mz->addr, capabilities, capa_size);
+	comp_dev->qat_dev_capabilities = comp_dev->capa_mz->addr;
+
+	while (1) {
+		if (qat_dev_cmd_param[i].name == NULL)
+			break;
+		if (!strcmp(qat_dev_cmd_param[i].name, COMP_ENQ_THRESHOLD_NAME))
+			comp_dev->min_enq_burst_threshold =
+					qat_dev_cmd_param[i].val;
+		i++;
+	}
+
+	qat_pci_dev->comp_dev = comp_dev;
 	QAT_LOG(DEBUG,
 		    "Created QAT COMP device %s as compressdev instance %d",
 			name, compressdev->data->dev_id);
@@ -737,6 +782,9 @@ qat_comp_dev_destroy(struct qat_pci_device *qat_pci_dev)
 	if (comp_dev == NULL)
 		return 0;
 
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_memzone_free(qat_pci_dev->comp_dev->capa_mz);
+
 	/* clean up any resources used by the device */
 	qat_comp_dev_close(comp_dev->compressdev);
 
diff --git a/dpdk/drivers/compress/qat/qat_comp_pmd.h b/dpdk/drivers/compress/qat/qat_comp_pmd.h
index 6979de14d4..ed27120604 100644
--- a/dpdk/drivers/compress/qat/qat_comp_pmd.h
+++ b/dpdk/drivers/compress/qat/qat_comp_pmd.h
@@ -32,10 +32,14 @@ struct qat_comp_dev_private {
 	/**< The device's pool for qat_comp_xforms */
 	struct rte_mempool *streampool;
 	/**< The device's pool for qat_comp_streams */
+	const struct rte_memzone *capa_mz;
+	/* Shared memzone for storing capabilities */
+	uint16_t min_enq_burst_threshold;
 };
 
 int
-qat_comp_dev_create(struct qat_pci_device *qat_pci_dev);
+qat_comp_dev_create(struct qat_pci_device *qat_pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
 qat_comp_dev_destroy(struct qat_pci_device *qat_pci_dev);
diff --git a/dpdk/drivers/compress/zlib/meson.build b/dpdk/drivers/compress/zlib/meson.build
index b1328c535e..3bb7769494 100644
--- a/dpdk/drivers/compress/zlib/meson.build
+++ b/dpdk/drivers/compress/zlib/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2018 Cavium Networks
 
-dep = dependency('zlib', required: false)
+dep = dependency('zlib', required: false, method: 'pkg-config')
 if not dep.found()
 	build = false
 	reason = 'missing dependency, "zlib"'
diff --git a/dpdk/drivers/compress/zlib/zlib_pmd.c b/dpdk/drivers/compress/zlib/zlib_pmd.c
index 19f9200c22..e39be2ed86 100644
--- a/dpdk/drivers/compress/zlib/zlib_pmd.c
+++ b/dpdk/drivers/compress/zlib/zlib_pmd.c
@@ -7,6 +7,8 @@
 
 #include "zlib_pmd_private.h"
 
+int zlib_logtype_driver;
+
 /** Compute next mbuf in the list, assign data buffer and length,
  *  returns 0 if mbuf is NULL
  */
diff --git a/dpdk/drivers/compress/zlib/zlib_pmd_private.h b/dpdk/drivers/compress/zlib/zlib_pmd_private.h
index bda49759dc..e36c5dc615 100644
--- a/dpdk/drivers/compress/zlib/zlib_pmd_private.h
+++ b/dpdk/drivers/compress/zlib/zlib_pmd_private.h
@@ -14,7 +14,7 @@
 
 #define DEF_MEM_LEVEL			8
 
-int zlib_logtype_driver;
+extern int zlib_logtype_driver;
 #define ZLIB_PMD_LOG(level, fmt, args...) \
 	rte_log(RTE_LOG_ ## level, zlib_logtype_driver, "%s(): "fmt "\n", \
 			__func__, ##args)
diff --git a/dpdk/drivers/crypto/aesni_gcm/Makefile b/dpdk/drivers/crypto/aesni_gcm/Makefile
index d8190a2ff4..b443167d51 100644
--- a/dpdk/drivers/crypto/aesni_gcm/Makefile
+++ b/dpdk/drivers/crypto/aesni_gcm/Makefile
@@ -20,7 +20,8 @@ LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_cryptodev
 LDLIBS += -lrte_bus_vdev
 
-IMB_HDR = $(shell echo '\#include <intel-ipsec-mb.h>' | \
+H := \#
+IMB_HDR = $(shell echo '$Hinclude <intel-ipsec-mb.h>' | \
 	$(CC) -E $(EXTRA_CFLAGS) - | grep 'intel-ipsec-mb.h' | \
 	head -n1 | cut -d'"' -f2)
 
diff --git a/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 1a03be31dc..c9c9eb8ca9 100644
--- a/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -13,6 +13,8 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+int aesni_gcm_logtype_driver;
+
 static uint8_t cryptodev_driver_id;
 
 /** Parse crypto xform chain and set private session parameters */
diff --git a/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd_private.h b/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd_private.h
index 2039adb533..7347c4769f 100644
--- a/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd_private.h
+++ b/dpdk/drivers/crypto/aesni_gcm/aesni_gcm_pmd_private.h
@@ -20,7 +20,7 @@
 /**< AES-NI GCM PMD device name */
 
 /** AES-NI GCM PMD  LOGTYPE DRIVER */
-int aesni_gcm_logtype_driver;
+extern int aesni_gcm_logtype_driver;
 #define AESNI_GCM_LOG(level, fmt, ...) \
 	rte_log(RTE_LOG_ ## level, aesni_gcm_logtype_driver,	\
 			"%s() line %u: "fmt "\n", __func__, __LINE__,	\
diff --git a/dpdk/drivers/crypto/aesni_mb/Makefile b/dpdk/drivers/crypto/aesni_mb/Makefile
index f1530e74c4..aa2e428106 100644
--- a/dpdk/drivers/crypto/aesni_mb/Makefile
+++ b/dpdk/drivers/crypto/aesni_mb/Makefile
@@ -20,7 +20,8 @@ LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_cryptodev
 LDLIBS += -lrte_bus_vdev
 
-IMB_HDR = $(shell echo '\#include <intel-ipsec-mb.h>' | \
+H := \#
+IMB_HDR = $(shell echo '$Hinclude <intel-ipsec-mb.h>' | \
 	$(CC) -E $(EXTRA_CFLAGS) - | grep 'intel-ipsec-mb.h' | \
 	head -n1 | cut -d'"' -f2)
 
diff --git a/dpdk/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h b/dpdk/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
index 3456693c25..03da3dc999 100644
--- a/dpdk/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
+++ b/dpdk/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
@@ -19,7 +19,7 @@ enum aesni_mb_vector_mode {
 /**< AES-NI Multi buffer PMD device name */
 
 /** AESNI_MB PMD LOGTYPE DRIVER */
-int aesni_mb_logtype_driver;
+extern int aesni_mb_logtype_driver;
 
 #define AESNI_MB_LOG(level, fmt, ...)  \
 	rte_log(RTE_LOG_ ## level, aesni_mb_logtype_driver,  \
@@ -74,7 +74,7 @@ static const unsigned auth_truncated_digest_byte_lengths[] = {
 		[AES_CMAC]	= 12,
 		[AES_CCM]	= 8,
 		[NULL_HASH]	= 0,
-		[AES_GMAC]	= 16,
+		[AES_GMAC]	= 12,
 		[PLAIN_SHA1]	= 20,
 		[PLAIN_SHA_224]	= 28,
 		[PLAIN_SHA_256]	= 32,
@@ -105,7 +105,7 @@ static const unsigned auth_digest_byte_lengths[] = {
 		[AES_XCBC]	= 16,
 		[AES_CMAC]	= 16,
 		[AES_CCM]	= 16,
-		[AES_GMAC]	= 12,
+		[AES_GMAC]	= 16,
 		[NULL_HASH]	= 0,
 		[PLAIN_SHA1]	= 20,
 		[PLAIN_SHA_224]	= 28,
diff --git a/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 97d9f81766..d2fa0664e3 100644
--- a/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -14,6 +14,8 @@
 
 #include "aesni_mb_pmd_private.h"
 
+int aesni_mb_logtype_driver;
+
 #define AES_CCM_DIGEST_MIN_LEN 4
 #define AES_CCM_DIGEST_MAX_LEN 16
 #define HMAC_MAX_BLOCK_SIZE 128
@@ -201,19 +203,11 @@ aesni_mb_set_session_auth_parameters(const MB_MGR *mb_mgr,
 			sess->cipher.direction = DECRYPT;
 
 		sess->auth.algo = AES_GMAC;
-		/*
-		 * Multi-buffer lib supports 8, 12 and 16 bytes of digest.
-		 * If size requested is different, generate the full digest
-		 * (16 bytes) in a temporary location and then memcpy
-		 * the requested number of bytes.
-		 */
-		if (sess->auth.req_digest_len != 16 &&
-				sess->auth.req_digest_len != 12 &&
-				sess->auth.req_digest_len != 8) {
-			sess->auth.gen_digest_len = 16;
-		} else {
-			sess->auth.gen_digest_len = sess->auth.req_digest_len;
+		if (sess->auth.req_digest_len > get_digest_byte_length(AES_GMAC)) {
+			AESNI_MB_LOG(ERR, "Invalid digest size\n");
+			return -EINVAL;
 		}
+		sess->auth.gen_digest_len = sess->auth.req_digest_len;
 		sess->iv.length = xform->auth.iv.length;
 		sess->iv.offset = xform->auth.iv.offset;
 
@@ -535,6 +529,14 @@ aesni_mb_set_session_aead_parameters(const MB_MGR *mb_mgr,
 		return -EINVAL;
 	}
 
+	/* Set IV parameters */
+	sess->iv.offset = xform->aead.iv.offset;
+	sess->iv.length = xform->aead.iv.length;
+
+	/* Set digest sizes */
+	sess->auth.req_digest_len = xform->aead.digest_length;
+	sess->auth.gen_digest_len = sess->auth.req_digest_len;
+
 	switch (xform->aead.algo) {
 	case RTE_CRYPTO_AEAD_AES_CCM:
 		sess->cipher.mode = CCM;
@@ -553,6 +555,13 @@ aesni_mb_set_session_aead_parameters(const MB_MGR *mb_mgr,
 			return -EINVAL;
 		}
 
+		/* CCM digests must be between 4 and 16 and an even number */
+		if (sess->auth.req_digest_len < AES_CCM_DIGEST_MIN_LEN ||
+				sess->auth.req_digest_len > AES_CCM_DIGEST_MAX_LEN ||
+				(sess->auth.req_digest_len & 1) == 1) {
+			AESNI_MB_LOG(ERR, "Invalid digest size\n");
+			return -EINVAL;
+		}
 		break;
 
 	case RTE_CRYPTO_AEAD_AES_GCM:
@@ -580,6 +589,12 @@ aesni_mb_set_session_aead_parameters(const MB_MGR *mb_mgr,
 			return -EINVAL;
 		}
 
+		/* GCM digest size must be between 1 and 16 */
+		if (sess->auth.req_digest_len == 0 ||
+				sess->auth.req_digest_len > 16) {
+			AESNI_MB_LOG(ERR, "Invalid digest size\n");
+			return -EINVAL;
+		}
 		break;
 
 	default:
@@ -587,20 +602,6 @@ aesni_mb_set_session_aead_parameters(const MB_MGR *mb_mgr,
 		return -ENOTSUP;
 	}
 
-	/* Set IV parameters */
-	sess->iv.offset = xform->aead.iv.offset;
-	sess->iv.length = xform->aead.iv.length;
-
-	sess->auth.req_digest_len = xform->aead.digest_length;
-	/* CCM digests must be between 4 and 16 and an even number */
-	if (sess->auth.req_digest_len < AES_CCM_DIGEST_MIN_LEN ||
-			sess->auth.req_digest_len > AES_CCM_DIGEST_MAX_LEN ||
-			(sess->auth.req_digest_len & 1) == 1) {
-		AESNI_MB_LOG(ERR, "Invalid digest size\n");
-		return -EINVAL;
-	}
-	sess->auth.gen_digest_len = sess->auth.req_digest_len;
-
 	return 0;
 }
 
@@ -729,10 +730,10 @@ get_session(struct aesni_mb_qp *qp, struct rte_crypto_op *op)
 					op->sym->session,
 					cryptodev_driver_id);
 	} else {
-		void *_sess = NULL;
+		void *_sess = rte_cryptodev_sym_session_create(qp->sess_mp);
 		void *_sess_private_data = NULL;
 
-		if (rte_mempool_get(qp->sess_mp, (void **)&_sess))
+		if (_sess == NULL)
 			return NULL;
 
 		if (rte_mempool_get(qp->sess_mp_priv,
diff --git a/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index d8609ad114..da614768b4 100644
--- a/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/dpdk/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -449,9 +449,9 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
 					.increment = 8
 				},
 				.digest_size = {
-					.min = 8,
+					.min = 1,
 					.max = 16,
-					.increment = 4
+					.increment = 1
 				},
 				.aad_size = {
 					.min = 0,
@@ -479,9 +479,9 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
 					.increment = 8
 				},
 				.digest_size = {
-					.min = 8,
+					.min = 1,
 					.max = 16,
-					.increment = 4
+					.increment = 1
 				},
 				.iv_size = {
 					.min = 12,
diff --git a/dpdk/drivers/crypto/armv8/armv8_pmd_private.h b/dpdk/drivers/crypto/armv8/armv8_pmd_private.h
index 24040dda26..aeda47b1b9 100644
--- a/dpdk/drivers/crypto/armv8/armv8_pmd_private.h
+++ b/dpdk/drivers/crypto/armv8/armv8_pmd_private.h
@@ -8,36 +8,34 @@
 #define CRYPTODEV_NAME_ARMV8_PMD	crypto_armv8
 /**< ARMv8 Crypto PMD device name */
 
-#define ARMV8_CRYPTO_LOG_ERR(fmt, args...) \
-	RTE_LOG(ERR, CRYPTODEV, "[%s] %s() line %u: " fmt "\n",  \
-			RTE_STR(CRYPTODEV_NAME_ARMV8_CRYPTO_PMD), \
+extern int crypto_armv8_log_type;
+
+#define ARMV8_CRYPTO_LOG_ERR(fmt, args...)			\
+	rte_log(RTE_LOG_ERR, crypto_armv8_log_type,		\
+			"[%s] %s() line %u: " fmt "\n",		\
+			RTE_STR(CRYPTODEV_NAME_ARMV8_PMD),	\
 			__func__, __LINE__, ## args)
 
-#ifdef RTE_LIBRTE_ARMV8_CRYPTO_DEBUG
-#define ARMV8_CRYPTO_LOG_INFO(fmt, args...) \
-	RTE_LOG(INFO, CRYPTODEV, "[%s] %s() line %u: " fmt "\n", \
-			RTE_STR(CRYPTODEV_NAME_ARMV8_CRYPTO_PMD), \
+#define ARMV8_CRYPTO_LOG_INFO(fmt, args...)			\
+	rte_log(RTE_LOG_INFO, crypto_armv8_log_type,		\
+			"[%s] %s() line %u: " fmt "\n",		\
+			RTE_STR(CRYPTODEV_NAME_ARMV8_PMD),	\
 			__func__, __LINE__, ## args)
 
-#define ARMV8_CRYPTO_LOG_DBG(fmt, args...) \
-	RTE_LOG(DEBUG, CRYPTODEV, "[%s] %s() line %u: " fmt "\n", \
-			RTE_STR(CRYPTODEV_NAME_ARMV8_CRYPTO_PMD), \
+#define ARMV8_CRYPTO_LOG_DBG(fmt, args...)			\
+	rte_log(RTE_LOG_DEBUG, crypto_armv8_log_type,		\
+			"[%s] %s() line %u: " fmt "\n",		\
+			RTE_STR(CRYPTODEV_NAME_ARMV8_PMD),	\
 			__func__, __LINE__, ## args)
 
 #define ARMV8_CRYPTO_ASSERT(con)				\
 do {								\
 	if (!(con)) {						\
-		rte_panic("%s(): "				\
-		    con "condition failed, line %u", __func__);	\
+		rte_panic("condition failed, line %u",		\
+			__LINE__);				\
 	}							\
 } while (0)
 
-#else
-#define ARMV8_CRYPTO_LOG_INFO(fmt, args...)
-#define ARMV8_CRYPTO_LOG_DBG(fmt, args...)
-#define ARMV8_CRYPTO_ASSERT(con)
-#endif
-
 #define NBBY		8		/* Number of bits in a byte */
 #define BYTE_LENGTH(x)	((x) / NBBY)	/* Number of bytes in x (round down) */
 
diff --git a/dpdk/drivers/crypto/armv8/rte_armv8_pmd.c b/dpdk/drivers/crypto/armv8/rte_armv8_pmd.c
index 7dc83e69e1..3c5af17e68 100644
--- a/dpdk/drivers/crypto/armv8/rte_armv8_pmd.c
+++ b/dpdk/drivers/crypto/armv8/rte_armv8_pmd.c
@@ -84,12 +84,12 @@ crypto_op_ca_encrypt = {
 
 static const crypto_func_tbl_t
 crypto_op_ca_decrypt = {
-	NULL
+	{ {NULL} }
 };
 
 static const crypto_func_tbl_t
 crypto_op_ac_encrypt = {
-	NULL
+	{ {NULL} }
 };
 
 static const crypto_func_tbl_t
@@ -369,7 +369,16 @@ armv8_crypto_set_session_chained_parameters(struct armv8_crypto_session *sess,
 	/* Select cipher key */
 	sess->cipher.key.length = cipher_xform->cipher.key.length;
 	/* Set cipher direction */
-	cop = sess->cipher.direction;
+	switch (sess->cipher.direction) {
+	case RTE_CRYPTO_CIPHER_OP_ENCRYPT:
+		cop = ARMV8_CRYPTO_CIPHER_OP_ENCRYPT;
+		break;
+	case RTE_CRYPTO_CIPHER_OP_DECRYPT:
+		cop = ARMV8_CRYPTO_CIPHER_OP_DECRYPT;
+		break;
+	default:
+		return -ENOTSUP;
+	}
 	/* Set cipher algorithm */
 	calg = cipher_xform->cipher.algo;
 
@@ -657,8 +666,8 @@ process_op(struct armv8_crypto_qp *qp, struct rte_crypto_op *op,
 		memset(op->sym->session, 0,
 			rte_cryptodev_sym_get_existing_header_session_size(
 				op->sym->session));
-		rte_mempool_put(qp->sess_mp, sess);
-		rte_mempool_put(qp->sess_mp_priv, op->sym->session);
+		rte_mempool_put(qp->sess_mp_priv, sess);
+		rte_mempool_put(qp->sess_mp, op->sym->session);
 		op->sym->session = NULL;
 	}
 
@@ -843,6 +852,8 @@ static struct rte_vdev_driver armv8_crypto_pmd_drv = {
 
 static struct cryptodev_driver armv8_crypto_drv;
 
+RTE_LOG_REGISTER(crypto_armv8_log_type, pmd.crypto.armv8, ERR);
+
 RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_ARMV8_PMD, armv8_crypto_pmd_drv);
 RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_ARMV8_PMD, cryptodev_armv8_pmd);
 RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_ARMV8_PMD,
diff --git a/dpdk/drivers/crypto/caam_jr/Makefile b/dpdk/drivers/crypto/caam_jr/Makefile
index 1b1f25a2a2..5b27b84c09 100644
--- a/dpdk/drivers/crypto/caam_jr/Makefile
+++ b/dpdk/drivers/crypto/caam_jr/Makefile
@@ -16,6 +16,13 @@ CFLAGS += -D _GNU_SOURCE
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 
+# FIXME: temporary solution for Bugzilla 469
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+ifeq ($(shell test $(GCC_VERSION) -ge 100 && echo 1), 1)
+CFLAGS += -fcommon
+endif
+endif
+
 CFLAGS += -I$(RTE_SDK)/drivers/bus/dpaa/include
 CFLAGS += -I$(RTE_SDK)/drivers/common/dpaax
 CFLAGS += -I$(RTE_SDK)/drivers/common/dpaax/caamflib/
diff --git a/dpdk/drivers/crypto/caam_jr/caam_jr.c b/dpdk/drivers/crypto/caam_jr/caam_jr.c
index 8aaa3d45f6..d6fa8cf7e8 100644
--- a/dpdk/drivers/crypto/caam_jr/caam_jr.c
+++ b/dpdk/drivers/crypto/caam_jr/caam_jr.c
@@ -2084,7 +2084,7 @@ static struct rte_security_ops caam_jr_security_ops = {
 static void
 close_job_ring(struct sec_job_ring_t *job_ring)
 {
-	if (job_ring->irq_fd) {
+	if (job_ring->irq_fd != -1) {
 		/* Producer index is frozen. If consumer index is not equal
 		 * with producer index, then we have descs to flush.
 		 */
@@ -2093,7 +2093,7 @@ close_job_ring(struct sec_job_ring_t *job_ring)
 
 		/* free the uio job ring */
 		free_job_ring(job_ring->irq_fd);
-		job_ring->irq_fd = 0;
+		job_ring->irq_fd = -1;
 		caam_jr_dma_free(job_ring->input_ring);
 		caam_jr_dma_free(job_ring->output_ring);
 		g_job_rings_no--;
@@ -2197,7 +2197,7 @@ caam_jr_dev_uninit(struct rte_cryptodev *dev)
  *
  */
 static void *
-init_job_ring(void *reg_base_addr, uint32_t irq_id)
+init_job_ring(void *reg_base_addr, int irq_id)
 {
 	struct sec_job_ring_t *job_ring = NULL;
 	int i, ret = 0;
@@ -2207,7 +2207,7 @@ init_job_ring(void *reg_base_addr, uint32_t irq_id)
 	int irq_coalescing_count = 0;
 
 	for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
-		if (g_job_rings[i].irq_fd == 0) {
+		if (g_job_rings[i].irq_fd == -1) {
 			job_ring = &g_job_rings[i];
 			g_job_rings_no++;
 			break;
@@ -2398,6 +2398,8 @@ caam_jr_dev_init(const char *name,
 static int
 cryptodev_caam_jr_probe(struct rte_vdev_device *vdev)
 {
+	int ret;
+
 	struct rte_cryptodev_pmd_init_params init_params = {
 		"",
 		sizeof(struct sec_job_ring_t),
@@ -2414,6 +2416,12 @@ cryptodev_caam_jr_probe(struct rte_vdev_device *vdev)
 	input_args = rte_vdev_device_args(vdev);
 	rte_cryptodev_pmd_parse_input_args(&init_params, input_args);
 
+	ret = of_init();
+	if (ret) {
+		RTE_LOG(ERR, PMD,
+		"of_init failed\n");
+		return -EINVAL;
+	}
 	/* if sec device version is not configured */
 	if (!rta_get_sec_era()) {
 		const struct device_node *caam_node;
@@ -2424,7 +2432,7 @@ cryptodev_caam_jr_probe(struct rte_vdev_device *vdev)
 					NULL);
 			if (prop) {
 				rta_set_sec_era(
-					INTL_SEC_ERA(cpu_to_caam32(*prop)));
+					INTL_SEC_ERA(rte_be_to_cpu_32(*prop)));
 				break;
 			}
 		}
@@ -2460,6 +2468,15 @@ cryptodev_caam_jr_remove(struct rte_vdev_device *vdev)
 	return rte_cryptodev_pmd_destroy(cryptodev);
 }
 
+static void
+sec_job_rings_init(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_SEC_JOB_RINGS; i++)
+		g_job_rings[i].irq_fd = -1;
+}
+
 static struct rte_vdev_driver cryptodev_caam_jr_drv = {
 	.probe = cryptodev_caam_jr_probe,
 	.remove = cryptodev_caam_jr_remove
@@ -2474,6 +2491,12 @@ RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_CAAM_JR_PMD,
 RTE_PMD_REGISTER_CRYPTO_DRIVER(caam_jr_crypto_drv, cryptodev_caam_jr_drv.driver,
 		cryptodev_driver_id);
 
+RTE_INIT(caam_jr_init)
+{
+	sec_uio_job_rings_init();
+	sec_job_rings_init();
+}
+
 RTE_INIT(caam_jr_init_log)
 {
 	caam_jr_logtype = rte_log_register("pmd.crypto.caam");
diff --git a/dpdk/drivers/crypto/caam_jr/caam_jr_hw_specific.h b/dpdk/drivers/crypto/caam_jr/caam_jr_hw_specific.h
index 5f58a585d7..bbe8bc3f90 100644
--- a/dpdk/drivers/crypto/caam_jr/caam_jr_hw_specific.h
+++ b/dpdk/drivers/crypto/caam_jr/caam_jr_hw_specific.h
@@ -360,7 +360,7 @@ struct sec_job_ring_t {
 				 * bitwise operations.
 				 */
 
-	uint32_t irq_fd;	/* The file descriptor used for polling from
+	int irq_fd;		/* The file descriptor used for polling from
 				 * user space for interrupts notifications
 				 */
 	uint32_t jr_mode;	/* Model used by SEC Driver to receive
diff --git a/dpdk/drivers/crypto/caam_jr/caam_jr_pvt.h b/dpdk/drivers/crypto/caam_jr/caam_jr_pvt.h
index 98cd4438aa..552d6b9b1b 100644
--- a/dpdk/drivers/crypto/caam_jr/caam_jr_pvt.h
+++ b/dpdk/drivers/crypto/caam_jr/caam_jr_pvt.h
@@ -216,7 +216,7 @@ calc_chksum(void *buffer, int len)
 }
 struct uio_job_ring {
 	uint32_t jr_id;
-	uint32_t uio_fd;
+	int uio_fd;
 	void *register_base_addr;
 	int map_size;
 	int uio_minor_number;
@@ -224,8 +224,9 @@ struct uio_job_ring {
 
 int sec_cleanup(void);
 int sec_configure(void);
+void sec_uio_job_rings_init(void);
 struct uio_job_ring *config_job_ring(void);
-void free_job_ring(uint32_t uio_fd);
+void free_job_ring(int uio_fd);
 
 /* For Dma memory allocation of specified length and alignment */
 static inline void *
@@ -279,7 +280,7 @@ static inline rte_iova_t caam_jr_dma_vtop(void *ptr)
  * @retval 0 for success
  * @retval -1 value for error
  */
-uint32_t caam_jr_enable_irqs(uint32_t uio_fd);
+int caam_jr_enable_irqs(int uio_fd);
 
 /** @brief Request to SEC kernel driver to disable interrupts for descriptor
  *  finished processing
@@ -292,6 +293,6 @@ uint32_t caam_jr_enable_irqs(uint32_t uio_fd);
  * @retval -1 value for error
  *
  */
-uint32_t caam_jr_disable_irqs(uint32_t uio_fd);
+int caam_jr_disable_irqs(int uio_fd);
 
 #endif
diff --git a/dpdk/drivers/crypto/caam_jr/caam_jr_uio.c b/dpdk/drivers/crypto/caam_jr/caam_jr_uio.c
index b1bb44ca42..e4ee102344 100644
--- a/dpdk/drivers/crypto/caam_jr/caam_jr_uio.c
+++ b/dpdk/drivers/crypto/caam_jr/caam_jr_uio.c
@@ -145,7 +145,7 @@ file_read_first_line(const char root[], const char subdir[],
 		 "%s/%s/%s", root, subdir, filename);
 
 	fd = open(absolute_file_name, O_RDONLY);
-	SEC_ASSERT(fd > 0, fd, "Error opening file %s",
+	SEC_ASSERT(fd >= 0, fd, "Error opening file %s",
 			absolute_file_name);
 
 	/* read UIO device name from first line in file */
@@ -179,7 +179,7 @@ file_read_first_line(const char root[], const char subdir[],
  *         kernel driver as well. No special return values are used.
  */
 static int
-sec_uio_send_command(uint32_t uio_fd, int32_t uio_command)
+sec_uio_send_command(int uio_fd, int32_t uio_command)
 {
 	int ret;
 
@@ -201,8 +201,8 @@ sec_uio_send_command(uint32_t uio_fd, int32_t uio_command)
  * @retval 0 for success
  * @retval -1 value for error
  */
-uint32_t
-caam_jr_enable_irqs(uint32_t uio_fd)
+int
+caam_jr_enable_irqs(int uio_fd)
 {
 	int ret;
 
@@ -232,8 +232,8 @@ caam_jr_enable_irqs(uint32_t uio_fd)
  * @retval -1 value for error
  *
  */
-uint32_t
-caam_jr_disable_irqs(uint32_t uio_fd)
+int
+caam_jr_disable_irqs(int uio_fd)
 {
 	int ret;
 
@@ -322,12 +322,12 @@ uio_map_registers(int uio_device_fd, int uio_device_id,
 }
 
 void
-free_job_ring(uint32_t uio_fd)
+free_job_ring(int uio_fd)
 {
 	struct uio_job_ring *job_ring = NULL;
 	int i;
 
-	if (!uio_fd)
+	if (uio_fd == -1)
 		return;
 
 	for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
@@ -347,7 +347,7 @@ free_job_ring(uint32_t uio_fd)
 			job_ring->jr_id, job_ring->uio_fd);
 	close(job_ring->uio_fd);
 	g_uio_jr_num--;
-	job_ring->uio_fd = 0;
+	job_ring->uio_fd = -1;
 	if (job_ring->register_base_addr == NULL)
 		return;
 
@@ -370,7 +370,7 @@ uio_job_ring *config_job_ring(void)
 	int i;
 
 	for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
-		if (g_uio_job_ring[i].uio_fd == 0) {
+		if (g_uio_job_ring[i].uio_fd == -1) {
 			job_ring = &g_uio_job_ring[i];
 			g_uio_jr_num++;
 			break;
@@ -389,7 +389,7 @@ uio_job_ring *config_job_ring(void)
 
 	/* Open device file */
 	job_ring->uio_fd = open(uio_device_file_name, O_RDWR);
-	SEC_ASSERT(job_ring->uio_fd > 0, NULL,
+	SEC_ASSERT(job_ring->uio_fd >= 0, NULL,
 		"Failed to open UIO device file for job ring %d",
 		job_ring->jr_id);
 
@@ -488,12 +488,22 @@ sec_cleanup(void)
 		/* I need to close the fd after shutdown UIO commands need to be
 		 * sent using the fd
 		 */
-		if (job_ring->uio_fd != 0) {
+		if (job_ring->uio_fd != -1) {
 			CAAM_JR_INFO(
 			"Closed device file for job ring %d , fd = %d",
 			job_ring->jr_id, job_ring->uio_fd);
 			close(job_ring->uio_fd);
+			job_ring->uio_fd = -1;
 		}
 	}
 	return 0;
 }
+
+void
+sec_uio_job_rings_init(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_SEC_JOB_RINGS; i++)
+		g_uio_job_ring[i].uio_fd = -1;
+}
diff --git a/dpdk/drivers/crypto/caam_jr/meson.build b/dpdk/drivers/crypto/caam_jr/meson.build
index 50132aebef..0dbfa2ee9c 100644
--- a/dpdk/drivers/crypto/caam_jr/meson.build
+++ b/dpdk/drivers/crypto/caam_jr/meson.build
@@ -14,6 +14,11 @@ sources = files('caam_jr_capabilities.c',
 
 allow_experimental_apis = true
 
+# FIXME: temporary solution for Bugzilla 469
+if (toolchain == 'gcc' and cc.version().version_compare('>=10.0.0'))
+	cflags += '-fcommon'
+endif
+
 includes += include_directories('../../bus/dpaa/include/')
 includes += include_directories('../../common/dpaax/')
 includes += include_directories('../../common/dpaax/caamflib/')
diff --git a/dpdk/drivers/crypto/ccp/ccp_dev.c b/dpdk/drivers/crypto/ccp/ccp_dev.c
index 80fe6a4533..7d98b2eb25 100644
--- a/dpdk/drivers/crypto/ccp/ccp_dev.c
+++ b/dpdk/drivers/crypto/ccp/ccp_dev.c
@@ -760,7 +760,7 @@ ccp_probe_device(const char *dirname, uint16_t domain,
 	return 0;
 fail:
 	CCP_LOG_ERR("CCP Device probe failed");
-	if (uio_fd > 0)
+	if (uio_fd >= 0)
 		close(uio_fd);
 	if (ccp_dev)
 		rte_free(ccp_dev);
diff --git a/dpdk/drivers/crypto/ccp/ccp_dev.h b/dpdk/drivers/crypto/ccp/ccp_dev.h
index f4ad9eafd5..37e04218ce 100644
--- a/dpdk/drivers/crypto/ccp/ccp_dev.h
+++ b/dpdk/drivers/crypto/ccp/ccp_dev.h
@@ -220,7 +220,7 @@ struct ccp_queue {
 	/**< lsb assigned for sha ctx */
 	uint32_t sb_hmac;
 	/**< lsb assigned for hmac ctx */
-} ____cacheline_aligned;
+} __rte_cache_aligned;
 
 /**
  * A structure describing a CCP device.
diff --git a/dpdk/drivers/crypto/ccp/meson.build b/dpdk/drivers/crypto/ccp/meson.build
index 6f7217adbf..99c7684e50 100644
--- a/dpdk/drivers/crypto/ccp/meson.build
+++ b/dpdk/drivers/crypto/ccp/meson.build
@@ -5,7 +5,7 @@ if not is_linux
 	build = false
 	reason = 'only supported on linux'
 endif
-dep = dependency('libcrypto', required: false)
+dep = dependency('libcrypto', required: false, method: 'pkg-config')
 if not dep.found()
 	build = false
 	reason = 'missing dependency, "libcrypto"'
diff --git a/dpdk/drivers/crypto/dpaa2_sec/Makefile b/dpdk/drivers/crypto/dpaa2_sec/Makefile
index 96b9c78435..183e9412ae 100644
--- a/dpdk/drivers/crypto/dpaa2_sec/Makefile
+++ b/dpdk/drivers/crypto/dpaa2_sec/Makefile
@@ -20,6 +20,13 @@ CFLAGS += -Wno-implicit-fallthrough
 endif
 endif
 
+# FIXME: temporary solution for Bugzilla 469
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+ifeq ($(shell test $(GCC_VERSION) -ge 100 && echo 1), 1)
+CFLAGS += -fcommon
+endif
+endif
+
 CFLAGS += -I$(RTE_SDK)/drivers/common/dpaax
 CFLAGS += -I$(RTE_SDK)/drivers/common/dpaax/caamflib
 CFLAGS += -I$(RTE_SDK)/drivers/crypto/dpaa2_sec/
diff --git a/dpdk/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/dpdk/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
index 6ed2701ab6..8df915e610 100644
--- a/dpdk/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
+++ b/dpdk/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  *
  *   Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
- *   Copyright 2016-2019 NXP
+ *   Copyright 2016-2020 NXP
  *
  */
 
@@ -168,7 +168,8 @@ build_proto_compound_sg_fd(dpaa2_sec_session *sess,
 	 * mbuf priv after sym_op.
 	 */
 	if (sess->ctxt_type == DPAA2_SEC_PDCP && sess->pdcp.hfn_ovd) {
-		uint32_t hfn_ovd = *((uint8_t *)op + sess->pdcp.hfn_ovd_offset);
+		uint32_t hfn_ovd = *(uint32_t *)((uint8_t *)op +
+					sess->pdcp.hfn_ovd_offset);
 		/*enable HFN override override */
 		DPAA2_SET_FLE_INTERNAL_JD(ip_fle, hfn_ovd);
 		DPAA2_SET_FLE_INTERNAL_JD(op_fle, hfn_ovd);
@@ -243,7 +244,8 @@ build_proto_compound_fd(dpaa2_sec_session *sess,
 	 * mbuf priv after sym_op.
 	 */
 	if (sess->ctxt_type == DPAA2_SEC_PDCP && sess->pdcp.hfn_ovd) {
-		uint32_t hfn_ovd = *((uint8_t *)op + sess->pdcp.hfn_ovd_offset);
+		uint32_t hfn_ovd = *(uint32_t *)((uint8_t *)op +
+					sess->pdcp.hfn_ovd_offset);
 		/*enable HFN override override */
 		DPAA2_SET_FLE_INTERNAL_JD(ip_fle, hfn_ovd);
 		DPAA2_SET_FLE_INTERNAL_JD(op_fle, hfn_ovd);
@@ -1845,7 +1847,7 @@ dpaa2_sec_cipher_init(struct rte_cryptodev *dev,
 	session->ctxt_type = DPAA2_SEC_CIPHER;
 	session->cipher_key.data = rte_zmalloc(NULL, xform->cipher.key.length,
 			RTE_CACHE_LINE_SIZE);
-	if (session->cipher_key.data == NULL) {
+	if (session->cipher_key.data == NULL && xform->cipher.key.length > 0) {
 		DPAA2_SEC_ERR("No Memory for cipher key");
 		rte_free(priv);
 		return -1;
@@ -2192,7 +2194,7 @@ dpaa2_sec_aead_init(struct rte_cryptodev *dev,
 
 	priv->flc_desc[0].desc[0] = aeaddata.keylen;
 	err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-			       MIN_JOB_DESC_SIZE,
+			       DESC_JOB_IO_LEN,
 			       (unsigned int *)priv->flc_desc[0].desc,
 			       &priv->flc_desc[0].desc[1], 1);
 
@@ -2410,7 +2412,7 @@ dpaa2_sec_aead_chain_init(struct rte_cryptodev *dev,
 	priv->flc_desc[0].desc[0] = cipherdata.keylen;
 	priv->flc_desc[0].desc[1] = authdata.keylen;
 	err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-			       MIN_JOB_DESC_SIZE,
+			       DESC_JOB_IO_LEN,
 			       (unsigned int *)priv->flc_desc[0].desc,
 			       &priv->flc_desc[0].desc[2], 2);
 
@@ -2744,12 +2746,6 @@ dpaa2_sec_ipsec_proto_init(struct rte_crypto_cipher_xform *cipher_xform,
 	return 0;
 }
 
-#ifdef RTE_LIBRTE_SECURITY_TEST
-static uint8_t aes_cbc_iv[] = {
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
-#endif
-
 static int
 dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev,
 			    struct rte_security_session_conf *conf,
@@ -3145,6 +3141,14 @@ dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
 		goto out;
 	}
 
+	if (rta_inline_pdcp_query(authdata.algtype,
+				cipherdata.algtype,
+				session->pdcp.sn_size,
+				session->pdcp.hfn_ovd)) {
+		cipherdata.key = DPAA2_VADDR_TO_IOVA(cipherdata.key);
+		cipherdata.key_type = RTA_DATA_PTR;
+	}
+
 	if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
 		if (session->dir == DIR_ENC)
 			bufsize = cnstr_shdsc_pdcp_c_plane_encap(
@@ -3482,7 +3486,7 @@ void dpaa2_sec_stats_get(struct rte_cryptodev *dev,
 		return;
 	}
 	for (i = 0; i < dev->data->nb_queue_pairs; i++) {
-		if (qp[i] == NULL) {
+		if (qp == NULL || qp[i] == NULL) {
 			DPAA2_SEC_DEBUG("Uninitialised queue pair");
 			continue;
 		}
diff --git a/dpdk/drivers/crypto/dpaa2_sec/meson.build b/dpdk/drivers/crypto/dpaa2_sec/meson.build
index ab9c8c8bf9..3f1dfd67da 100644
--- a/dpdk/drivers/crypto/dpaa2_sec/meson.build
+++ b/dpdk/drivers/crypto/dpaa2_sec/meson.build
@@ -12,4 +12,9 @@ sources = files('dpaa2_sec_dpseci.c',
 
 allow_experimental_apis = true
 
+# FIXME: temporary solution for Bugzilla 469
+if (toolchain == 'gcc' and cc.version().version_compare('>=10.0.0'))
+	cflags += '-fcommon'
+endif
+
 includes += include_directories('mc', '../../common/dpaax', '../../common/dpaax/caamflib')
diff --git a/dpdk/drivers/crypto/dpaa_sec/Makefile b/dpdk/drivers/crypto/dpaa_sec/Makefile
index fbfd775855..b5a97b9f6e 100644
--- a/dpdk/drivers/crypto/dpaa_sec/Makefile
+++ b/dpdk/drivers/crypto/dpaa_sec/Makefile
@@ -14,6 +14,13 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 
+# FIXME: temporary solution for Bugzilla 469
+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)
+ifeq ($(shell test $(GCC_VERSION) -ge 100 && echo 1), 1)
+CFLAGS += -fcommon
+endif
+endif
+
 CFLAGS += -I$(RTE_SDK)/drivers/bus/dpaa
 CFLAGS += -I$(RTE_SDK)/drivers/bus/dpaa/include
 CFLAGS += -I$(RTE_SDK)/drivers/bus/dpaa/base/qbman
diff --git a/dpdk/drivers/crypto/dpaa_sec/dpaa_sec.c b/dpdk/drivers/crypto/dpaa_sec/dpaa_sec.c
index e0b307cecd..a650313cdb 100644
--- a/dpdk/drivers/crypto/dpaa_sec/dpaa_sec.c
+++ b/dpdk/drivers/crypto/dpaa_sec/dpaa_sec.c
@@ -94,31 +94,6 @@ dpaa_sec_alloc_ctx(dpaa_sec_session *ses, int sg_count)
 	return ctx;
 }
 
-static inline rte_iova_t
-dpaa_mem_vtop(void *vaddr)
-{
-	const struct rte_memseg *ms;
-
-	ms = rte_mem_virt2memseg(vaddr, NULL);
-	if (ms) {
-		dpaax_iova_table_update(ms->iova, ms->addr, ms->len);
-		return ms->iova + RTE_PTR_DIFF(vaddr, ms->addr);
-	}
-	return (size_t)NULL;
-}
-
-static inline void *
-dpaa_mem_ptov(rte_iova_t paddr)
-{
-	void *va;
-
-	va = (void *)dpaax_iova_table_get_va(paddr);
-	if (likely(va))
-		return va;
-
-	return rte_mem_iova2virt(paddr);
-}
-
 static void
 ern_sec_fq_handler(struct qman_portal *qm __rte_unused,
 		   struct qman_fq *fq,
@@ -183,7 +158,7 @@ dqrr_out_fq_cb_rx(struct qman_portal *qm __always_unused,
 	 * sg[0] is for output
 	 * sg[1] for input
 	 */
-	job = dpaa_mem_ptov(qm_fd_addr_get64(fd));
+	job = rte_dpaa_mem_ptov(qm_fd_addr_get64(fd));
 
 	ctx = container_of(job, struct dpaa_sec_op_ctx, job);
 	ctx->fd_status = fd->status;
@@ -262,7 +237,6 @@ dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 	struct sec_cdb *cdb = &ses->cdb;
 	struct alginfo *p_authdata = NULL;
 	int32_t shared_desc_len = 0;
-	int err;
 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
 	int swap = false;
 #else
@@ -276,10 +250,6 @@ dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 	cipherdata.algtype = ses->cipher_key.alg;
 	cipherdata.algmode = ses->cipher_key.algmode;
 
-	cdb->sh_desc[0] = cipherdata.keylen;
-	cdb->sh_desc[1] = 0;
-	cdb->sh_desc[2] = 0;
-
 	if (ses->auth_alg) {
 		authdata.key = (size_t)ses->auth_key.data;
 		authdata.keylen = ses->auth_key.length;
@@ -289,33 +259,17 @@ dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 		authdata.algmode = ses->auth_key.algmode;
 
 		p_authdata = &authdata;
-
-		cdb->sh_desc[1] = authdata.keylen;
 	}
 
-	err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-			       MIN_JOB_DESC_SIZE,
-			       (unsigned int *)cdb->sh_desc,
-			       &cdb->sh_desc[2], 2);
-	if (err < 0) {
-		DPAA_SEC_ERR("Crypto: Incorrect key lengths");
-		return err;
-	}
-
-	if (!(cdb->sh_desc[2] & 1) && cipherdata.keylen) {
+	if (rta_inline_pdcp_query(authdata.algtype,
+				cipherdata.algtype,
+				ses->pdcp.sn_size,
+				ses->pdcp.hfn_ovd)) {
 		cipherdata.key =
-			(size_t)dpaa_mem_vtop((void *)(size_t)cipherdata.key);
+			(size_t)rte_dpaa_mem_vtop((void *)
+					(size_t)cipherdata.key);
 		cipherdata.key_type = RTA_DATA_PTR;
 	}
-	if (!(cdb->sh_desc[2] & (1 << 1)) &&  authdata.keylen) {
-		authdata.key =
-			(size_t)dpaa_mem_vtop((void *)(size_t)authdata.key);
-		authdata.key_type = RTA_DATA_PTR;
-	}
-
-	cdb->sh_desc[0] = 0;
-	cdb->sh_desc[1] = 0;
-	cdb->sh_desc[2] = 0;
 
 	if (ses->pdcp.domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
 		if (ses->dir == DIR_ENC)
@@ -394,7 +348,7 @@ dpaa_sec_prep_ipsec_cdb(dpaa_sec_session *ses)
 	cdb->sh_desc[0] = cipherdata.keylen;
 	cdb->sh_desc[1] = authdata.keylen;
 	err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-			       MIN_JOB_DESC_SIZE,
+			       DESC_JOB_IO_LEN,
 			       (unsigned int *)cdb->sh_desc,
 			       &cdb->sh_desc[2], 2);
 
@@ -405,14 +359,14 @@ dpaa_sec_prep_ipsec_cdb(dpaa_sec_session *ses)
 	if (cdb->sh_desc[2] & 1)
 		cipherdata.key_type = RTA_DATA_IMM;
 	else {
-		cipherdata.key = (size_t)dpaa_mem_vtop(
+		cipherdata.key = (size_t)rte_dpaa_mem_vtop(
 					(void *)(size_t)cipherdata.key);
 		cipherdata.key_type = RTA_DATA_PTR;
 	}
 	if (cdb->sh_desc[2] & (1<<1))
 		authdata.key_type = RTA_DATA_IMM;
 	else {
-		authdata.key = (size_t)dpaa_mem_vtop(
+		authdata.key = (size_t)rte_dpaa_mem_vtop(
 					(void *)(size_t)authdata.key);
 		authdata.key_type = RTA_DATA_PTR;
 	}
@@ -580,7 +534,7 @@ dpaa_sec_prep_cdb(dpaa_sec_session *ses)
 		cdb->sh_desc[0] = alginfo_c.keylen;
 		cdb->sh_desc[1] = alginfo_a.keylen;
 		err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-				       MIN_JOB_DESC_SIZE,
+				       DESC_JOB_IO_LEN,
 				       (unsigned int *)cdb->sh_desc,
 				       &cdb->sh_desc[2], 2);
 
@@ -591,14 +545,14 @@ dpaa_sec_prep_cdb(dpaa_sec_session *ses)
 		if (cdb->sh_desc[2] & 1)
 			alginfo_c.key_type = RTA_DATA_IMM;
 		else {
-			alginfo_c.key = (size_t)dpaa_mem_vtop(
+			alginfo_c.key = (size_t)rte_dpaa_mem_vtop(
 						(void *)(size_t)alginfo_c.key);
 			alginfo_c.key_type = RTA_DATA_PTR;
 		}
 		if (cdb->sh_desc[2] & (1<<1))
 			alginfo_a.key_type = RTA_DATA_IMM;
 		else {
-			alginfo_a.key = (size_t)dpaa_mem_vtop(
+			alginfo_a.key = (size_t)rte_dpaa_mem_vtop(
 						(void *)(size_t)alginfo_a.key);
 			alginfo_a.key_type = RTA_DATA_PTR;
 		}
@@ -674,7 +628,7 @@ dpaa_sec_deq(struct dpaa_sec_qp *qp, struct rte_crypto_op **ops, int nb_ops)
 		 * sg[0] is for output
 		 * sg[1] for input
 		 */
-		job = dpaa_mem_ptov(qm_fd_addr_get64(fd));
+		job = rte_dpaa_mem_ptov(qm_fd_addr_get64(fd));
 
 		ctx = container_of(job, struct dpaa_sec_op_ctx, job);
 		ctx->fd_status = fd->status;
@@ -768,7 +722,7 @@ build_auth_only_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	in_sg->extension = 1;
 	in_sg->final = 1;
 	in_sg->length = data_len;
-	qm_sg_entry_set64(in_sg, dpaa_mem_vtop(&cf->sg[2]));
+	qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
 
 	/* 1st seg */
 	sg = in_sg + 1;
@@ -788,7 +742,7 @@ build_auth_only_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		} else {
 			sg->length = ses->iv.length;
 		}
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(iv_ptr));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(iv_ptr));
 		in_sg->length += sg->length;
 		cpu_to_hw_sg(sg);
 		sg++;
@@ -821,7 +775,7 @@ build_auth_only_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg++;
 		rte_memcpy(old_digest, sym->auth.digest.data,
 				ses->digest_length);
-		start_addr = dpaa_mem_vtop(old_digest);
+		start_addr = rte_dpaa_mem_vtop(old_digest);
 		qm_sg_entry_set64(sg, start_addr);
 		sg->length = ses->digest_length;
 		in_sg->length += ses->digest_length;
@@ -888,7 +842,7 @@ build_auth_only(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	in_sg->extension = 1;
 	in_sg->final = 1;
 	in_sg->length = data_len;
-	qm_sg_entry_set64(in_sg, dpaa_mem_vtop(&cf->sg[2]));
+	qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
 	sg = &cf->sg[2];
 
 	if (ses->iv.length) {
@@ -906,7 +860,7 @@ build_auth_only(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		} else {
 			sg->length = ses->iv.length;
 		}
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(iv_ptr));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(iv_ptr));
 		in_sg->length += sg->length;
 		cpu_to_hw_sg(sg);
 		sg++;
@@ -923,7 +877,7 @@ build_auth_only(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		rte_memcpy(old_digest, sym->auth.digest.data,
 				ses->digest_length);
 		/* let's check digest by hw */
-		start_addr = dpaa_mem_vtop(old_digest);
+		start_addr = rte_dpaa_mem_vtop(old_digest);
 		sg++;
 		qm_sg_entry_set64(sg, start_addr);
 		sg->length = ses->digest_length;
@@ -987,7 +941,7 @@ build_cipher_only_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	out_sg = &cf->sg[0];
 	out_sg->extension = 1;
 	out_sg->length = data_len;
-	qm_sg_entry_set64(out_sg, dpaa_mem_vtop(&cf->sg[2]));
+	qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
 	cpu_to_hw_sg(out_sg);
 
 	/* 1st seg */
@@ -1016,11 +970,11 @@ build_cipher_only_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	in_sg->length = data_len + ses->iv.length;
 
 	sg++;
-	qm_sg_entry_set64(in_sg, dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
 	cpu_to_hw_sg(in_sg);
 
 	/* IV */
-	qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+	qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 	sg->length = ses->iv.length;
 	cpu_to_hw_sg(sg);
 
@@ -1098,11 +1052,11 @@ build_cipher_only(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	sg->extension = 1;
 	sg->final = 1;
 	sg->length = data_len + ses->iv.length;
-	qm_sg_entry_set64(sg, dpaa_mem_vtop(&cf->sg[2]));
+	qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(&cf->sg[2]));
 	cpu_to_hw_sg(sg);
 
 	sg = &cf->sg[2];
-	qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+	qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 	sg->length = ses->iv.length;
 	cpu_to_hw_sg(sg);
 
@@ -1163,7 +1117,7 @@ build_cipher_auth_gcm_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 
 	/* output sg entries */
 	sg = &cf->sg[2];
-	qm_sg_entry_set64(out_sg, dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(sg));
 	cpu_to_hw_sg(out_sg);
 
 	/* 1st seg */
@@ -1206,18 +1160,18 @@ build_cipher_auth_gcm_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 
 	/* input sg entries */
 	sg++;
-	qm_sg_entry_set64(in_sg, dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
 	cpu_to_hw_sg(in_sg);
 
 	/* 1st seg IV */
-	qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+	qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 	sg->length = ses->iv.length;
 	cpu_to_hw_sg(sg);
 
 	/* 2nd seg auth only */
 	if (ses->auth_only_len) {
 		sg++;
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(sym->aead.aad.data));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(sym->aead.aad.data));
 		sg->length = ses->auth_only_len;
 		cpu_to_hw_sg(sg);
 	}
@@ -1243,7 +1197,7 @@ build_cipher_auth_gcm_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg++;
 		memcpy(ctx->digest, sym->aead.digest.data,
 			ses->digest_length);
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(ctx->digest));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(ctx->digest));
 		sg->length = ses->digest_length;
 	}
 	sg->final = 1;
@@ -1281,9 +1235,9 @@ build_cipher_auth_gcm(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	/* input */
 	rte_prefetch0(cf->sg);
 	sg = &cf->sg[2];
-	qm_sg_entry_set64(&cf->sg[1], dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(&cf->sg[1], rte_dpaa_mem_vtop(sg));
 	if (is_encode(ses)) {
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 		sg->length = ses->iv.length;
 		length += sg->length;
 		cpu_to_hw_sg(sg);
@@ -1291,7 +1245,7 @@ build_cipher_auth_gcm(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg++;
 		if (ses->auth_only_len) {
 			qm_sg_entry_set64(sg,
-					  dpaa_mem_vtop(sym->aead.aad.data));
+					  rte_dpaa_mem_vtop(sym->aead.aad.data));
 			sg->length = ses->auth_only_len;
 			length += sg->length;
 			cpu_to_hw_sg(sg);
@@ -1303,7 +1257,7 @@ build_cipher_auth_gcm(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg->final = 1;
 		cpu_to_hw_sg(sg);
 	} else {
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 		sg->length = ses->iv.length;
 		length += sg->length;
 		cpu_to_hw_sg(sg);
@@ -1311,7 +1265,7 @@ build_cipher_auth_gcm(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg++;
 		if (ses->auth_only_len) {
 			qm_sg_entry_set64(sg,
-					  dpaa_mem_vtop(sym->aead.aad.data));
+					  rte_dpaa_mem_vtop(sym->aead.aad.data));
 			sg->length = ses->auth_only_len;
 			length += sg->length;
 			cpu_to_hw_sg(sg);
@@ -1326,7 +1280,7 @@ build_cipher_auth_gcm(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		       ses->digest_length);
 		sg++;
 
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(ctx->digest));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(ctx->digest));
 		sg->length = ses->digest_length;
 		length += sg->length;
 		sg->final = 1;
@@ -1340,7 +1294,7 @@ build_cipher_auth_gcm(struct rte_crypto_op *op, dpaa_sec_session *ses)
 
 	/* output */
 	sg++;
-	qm_sg_entry_set64(&cf->sg[0], dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(&cf->sg[0], rte_dpaa_mem_vtop(sg));
 	qm_sg_entry_set64(sg,
 		dst_start_addr + sym->aead.data.offset);
 	sg->length = sym->aead.data.length;
@@ -1409,7 +1363,7 @@ build_cipher_auth_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 
 	/* output sg entries */
 	sg = &cf->sg[2];
-	qm_sg_entry_set64(out_sg, dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(sg));
 	cpu_to_hw_sg(out_sg);
 
 	/* 1st seg */
@@ -1451,11 +1405,11 @@ build_cipher_auth_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 
 	/* input sg entries */
 	sg++;
-	qm_sg_entry_set64(in_sg, dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
 	cpu_to_hw_sg(in_sg);
 
 	/* 1st seg IV */
-	qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+	qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 	sg->length = ses->iv.length;
 	cpu_to_hw_sg(sg);
 
@@ -1481,7 +1435,7 @@ build_cipher_auth_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg++;
 		memcpy(ctx->digest, sym->auth.digest.data,
 			ses->digest_length);
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(ctx->digest));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(ctx->digest));
 		sg->length = ses->digest_length;
 	}
 	sg->final = 1;
@@ -1518,9 +1472,9 @@ build_cipher_auth(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	/* input */
 	rte_prefetch0(cf->sg);
 	sg = &cf->sg[2];
-	qm_sg_entry_set64(&cf->sg[1], dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(&cf->sg[1], rte_dpaa_mem_vtop(sg));
 	if (is_encode(ses)) {
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 		sg->length = ses->iv.length;
 		length += sg->length;
 		cpu_to_hw_sg(sg);
@@ -1532,7 +1486,7 @@ build_cipher_auth(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		sg->final = 1;
 		cpu_to_hw_sg(sg);
 	} else {
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(IV_ptr));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(IV_ptr));
 		sg->length = ses->iv.length;
 		length += sg->length;
 		cpu_to_hw_sg(sg);
@@ -1548,7 +1502,7 @@ build_cipher_auth(struct rte_crypto_op *op, dpaa_sec_session *ses)
 		       ses->digest_length);
 		sg++;
 
-		qm_sg_entry_set64(sg, dpaa_mem_vtop(ctx->digest));
+		qm_sg_entry_set64(sg, rte_dpaa_mem_vtop(ctx->digest));
 		sg->length = ses->digest_length;
 		length += sg->length;
 		sg->final = 1;
@@ -1562,7 +1516,7 @@ build_cipher_auth(struct rte_crypto_op *op, dpaa_sec_session *ses)
 
 	/* output */
 	sg++;
-	qm_sg_entry_set64(&cf->sg[0], dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(&cf->sg[0], rte_dpaa_mem_vtop(sg));
 	qm_sg_entry_set64(sg, dst_start_addr + sym->cipher.data.offset);
 	sg->length = sym->cipher.data.length;
 	length = sg->length;
@@ -1656,7 +1610,7 @@ build_proto_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	/* output */
 	out_sg = &cf->sg[0];
 	out_sg->extension = 1;
-	qm_sg_entry_set64(out_sg, dpaa_mem_vtop(&cf->sg[2]));
+	qm_sg_entry_set64(out_sg, rte_dpaa_mem_vtop(&cf->sg[2]));
 
 	/* 1st seg */
 	sg = &cf->sg[2];
@@ -1689,7 +1643,7 @@ build_proto_sg(struct rte_crypto_op *op, dpaa_sec_session *ses)
 	in_len = mbuf->data_len;
 
 	sg++;
-	qm_sg_entry_set64(in_sg, dpaa_mem_vtop(sg));
+	qm_sg_entry_set64(in_sg, rte_dpaa_mem_vtop(sg));
 
 	/* 1st seg */
 	qm_sg_entry_set64(sg, rte_pktmbuf_mtophys(mbuf));
@@ -1884,7 +1838,7 @@ dpaa_sec_enqueue_burst(void *qp, struct rte_crypto_op **ops,
 			inq[loop] = ses->inq[rte_lcore_id() % MAX_DPAA_CORES];
 			fd->opaque_addr = 0;
 			fd->cmd = 0;
-			qm_fd_addr_set64(fd, dpaa_mem_vtop(cf->sg));
+			qm_fd_addr_set64(fd, rte_dpaa_mem_vtop(cf->sg));
 			fd->_format1 = qm_fd_compound;
 			fd->length29 = 2 * sizeof(struct qm_sg_entry);
 
@@ -2349,7 +2303,7 @@ dpaa_sec_attach_sess_q(struct dpaa_sec_qp *qp, dpaa_sec_session *sess)
 		}
 	}
 	ret = dpaa_sec_init_rx(sess->inq[rte_lcore_id() % MAX_DPAA_CORES],
-			       dpaa_mem_vtop(&sess->cdb),
+			       rte_dpaa_mem_vtop(&sess->cdb),
 			       qman_fq_fqid(&qp->outq));
 	if (ret)
 		DPAA_SEC_ERR("Unable to init sec queue");
@@ -3005,7 +2959,8 @@ dpaa_sec_set_pdcp_session(struct rte_cryptodev *dev,
 	session->pdcp.hfn = pdcp_xform->hfn;
 	session->pdcp.hfn_threshold = pdcp_xform->hfn_threshold;
 	session->pdcp.hfn_ovd = pdcp_xform->hfn_ovrd;
-	session->pdcp.hfn_ovd_offset = cipher_xform->iv.offset;
+	if (cipher_xform)
+		session->pdcp.hfn_ovd_offset = cipher_xform->iv.offset;
 
 	rte_spinlock_lock(&dev_priv->lock);
 	for (i = 0; i < MAX_DPAA_CORES; i++) {
@@ -3149,7 +3104,7 @@ dpaa_sec_process_parallel_event(void *event,
 	 * sg[0] is for output
 	 * sg[1] for input
 	 */
-	job = dpaa_mem_ptov(qm_fd_addr_get64(fd));
+	job = rte_dpaa_mem_ptov(qm_fd_addr_get64(fd));
 
 	ctx = container_of(job, struct dpaa_sec_op_ctx, job);
 	ctx->fd_status = fd->status;
@@ -3204,7 +3159,7 @@ dpaa_sec_process_atomic_event(void *event,
 	 * sg[0] is for output
 	 * sg[1] for input
 	 */
-	job = dpaa_mem_ptov(qm_fd_addr_get64(fd));
+	job = rte_dpaa_mem_ptov(qm_fd_addr_get64(fd));
 
 	ctx = container_of(job, struct dpaa_sec_op_ctx, job);
 	ctx->fd_status = fd->status;
diff --git a/dpdk/drivers/crypto/dpaa_sec/meson.build b/dpdk/drivers/crypto/dpaa_sec/meson.build
index 9f17d3a43e..e819f9cf1b 100644
--- a/dpdk/drivers/crypto/dpaa_sec/meson.build
+++ b/dpdk/drivers/crypto/dpaa_sec/meson.build
@@ -6,11 +6,16 @@ if not is_linux
 	reason = 'only supported on linux'
 endif
 
-deps += ['bus_dpaa', 'security']
+deps += ['bus_dpaa', 'mempool_dpaa', 'security']
 sources = files('dpaa_sec.c')
 
 allow_experimental_apis = true
 
+# FIXME: temporary solution for Bugzilla 469
+if (toolchain == 'gcc' and cc.version().version_compare('>=10.0.0'))
+	cflags += '-fcommon'
+endif
+
 includes += include_directories('../../bus/dpaa/include')
 includes += include_directories('../../common/dpaax')
 includes += include_directories('../../common/dpaax/caamflib/')
diff --git a/dpdk/drivers/crypto/kasumi/kasumi_pmd_private.h b/dpdk/drivers/crypto/kasumi/kasumi_pmd_private.h
index 7ac19c5735..f0b83f2272 100644
--- a/dpdk/drivers/crypto/kasumi/kasumi_pmd_private.h
+++ b/dpdk/drivers/crypto/kasumi/kasumi_pmd_private.h
@@ -11,7 +11,7 @@
 /**< KASUMI PMD device name */
 
 /** KASUMI PMD LOGTYPE DRIVER */
-int kasumi_logtype_driver;
+extern int kasumi_logtype_driver;
 
 #define KASUMI_LOG(level, fmt, ...)  \
 	rte_log(RTE_LOG_ ## level, kasumi_logtype_driver,  \
@@ -72,6 +72,6 @@ kasumi_set_session_parameters(struct kasumi_session *sess,
 
 
 /** device specific operations function pointer structure */
-struct rte_cryptodev_ops *rte_kasumi_pmd_ops;
+extern struct rte_cryptodev_ops *rte_kasumi_pmd_ops;
 
 #endif /* _KASUMI_PMD_PRIVATE_H_ */
diff --git a/dpdk/drivers/crypto/kasumi/rte_kasumi_pmd.c b/dpdk/drivers/crypto/kasumi/rte_kasumi_pmd.c
index d0583ef073..dd85928c52 100644
--- a/dpdk/drivers/crypto/kasumi/rte_kasumi_pmd.c
+++ b/dpdk/drivers/crypto/kasumi/rte_kasumi_pmd.c
@@ -17,6 +17,7 @@
 #define KASUMI_MAX_BURST 4
 #define BYTE_LEN 8
 
+int kasumi_logtype_driver;
 static uint8_t cryptodev_driver_id;
 
 /** Get xform chain order. */
@@ -556,6 +557,7 @@ cryptodev_kasumi_create(const char *name,
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			cpu_flags;
 
 	internals = dev->data->dev_private;
diff --git a/dpdk/drivers/crypto/mvsam/mrvl_pmd_private.h b/dpdk/drivers/crypto/mvsam/mrvl_pmd_private.h
index 09702b9e3e..e575330ef5 100644
--- a/dpdk/drivers/crypto/mvsam/mrvl_pmd_private.h
+++ b/dpdk/drivers/crypto/mvsam/mrvl_pmd_private.h
@@ -13,7 +13,7 @@
 /**< Marvell PMD device name */
 
 /** MRVL PMD LOGTYPE DRIVER */
-int mrvl_logtype_driver;
+extern int mrvl_logtype_driver;
 
 #define MRVL_LOG(level, fmt, ...) \
 	rte_log(RTE_LOG_ ## level, mrvl_logtype_driver, \
diff --git a/dpdk/drivers/crypto/mvsam/rte_mrvl_pmd.c b/dpdk/drivers/crypto/mvsam/rte_mrvl_pmd.c
index 3c0fe216f0..63782ce974 100644
--- a/dpdk/drivers/crypto/mvsam/rte_mrvl_pmd.c
+++ b/dpdk/drivers/crypto/mvsam/rte_mrvl_pmd.c
@@ -19,6 +19,7 @@
 #define MRVL_PMD_MAX_NB_SESS_ARG		("max_nb_sessions")
 #define MRVL_PMD_DEFAULT_MAX_NB_SESSIONS	2048
 
+int mrvl_logtype_driver;
 static uint8_t cryptodev_driver_id;
 
 struct mrvl_pmd_init_params {
diff --git a/dpdk/drivers/crypto/nitrox/nitrox_csr.h b/dpdk/drivers/crypto/nitrox/nitrox_csr.h
index 8cd92e38be..de7a3c6713 100644
--- a/dpdk/drivers/crypto/nitrox/nitrox_csr.h
+++ b/dpdk/drivers/crypto/nitrox/nitrox_csr.h
@@ -12,18 +12,18 @@
 #define NITROX_CSR_ADDR(bar_addr, offset) (bar_addr + (offset))
 
 /* NPS packet registers */
-#define NPS_PKT_IN_INSTR_CTLX(_i)	(0x10060 + ((_i) * 0x40000))
-#define NPS_PKT_IN_INSTR_BADDRX(_i)	(0x10068 + ((_i) * 0x40000))
-#define NPS_PKT_IN_INSTR_RSIZEX(_i)	(0x10070 + ((_i) * 0x40000))
-#define NPS_PKT_IN_DONE_CNTSX(_i)	(0x10080 + ((_i) * 0x40000))
-#define NPS_PKT_IN_INSTR_BAOFF_DBELLX(_i)	(0x10078 + ((_i) * 0x40000))
-#define NPS_PKT_IN_INT_LEVELSX(_i)		(0x10088 + ((_i) * 0x40000))
-#define NPS_PKT_SLC_CTLX(_i)		(0x10000 + ((_i) * 0x40000))
-#define NPS_PKT_SLC_CNTSX(_i)		(0x10008 + ((_i) * 0x40000))
-#define NPS_PKT_SLC_INT_LEVELSX(_i)	(0x10010 + ((_i) * 0x40000))
+#define NPS_PKT_IN_INSTR_CTLX(_i)	(0x10060UL + ((_i) * 0x40000UL))
+#define NPS_PKT_IN_INSTR_BADDRX(_i)	(0x10068UL + ((_i) * 0x40000UL))
+#define NPS_PKT_IN_INSTR_RSIZEX(_i)	(0x10070UL + ((_i) * 0x40000UL))
+#define NPS_PKT_IN_DONE_CNTSX(_i)	(0x10080UL + ((_i) * 0x40000UL))
+#define NPS_PKT_IN_INSTR_BAOFF_DBELLX(_i)	(0x10078UL + ((_i) * 0x40000UL))
+#define NPS_PKT_IN_INT_LEVELSX(_i)		(0x10088UL + ((_i) * 0x40000UL))
+#define NPS_PKT_SLC_CTLX(_i)		(0x10000UL + ((_i) * 0x40000UL))
+#define NPS_PKT_SLC_CNTSX(_i)		(0x10008UL + ((_i) * 0x40000UL))
+#define NPS_PKT_SLC_INT_LEVELSX(_i)	(0x10010UL + ((_i) * 0x40000UL))
 
 /* AQM Virtual Function Registers */
-#define AQMQ_QSZX(_i)			(0x20008 + ((_i)*0x40000))
+#define AQMQ_QSZX(_i)			(0x20008UL + ((_i) * 0x40000UL))
 
 static inline uint64_t
 nitrox_read_csr(uint8_t *bar_addr, uint64_t offset)
diff --git a/dpdk/drivers/crypto/nitrox/nitrox_sym.c b/dpdk/drivers/crypto/nitrox/nitrox_sym.c
index 56410c44d7..d1b32fec92 100644
--- a/dpdk/drivers/crypto/nitrox/nitrox_sym.c
+++ b/dpdk/drivers/crypto/nitrox/nitrox_sym.c
@@ -683,7 +683,8 @@ nitrox_sym_pmd_create(struct nitrox_device *ndev)
 	struct rte_cryptodev *cdev;
 
 	rte_pci_device_name(&ndev->pdev->addr, name, sizeof(name));
-	snprintf(name + strlen(name), RTE_CRYPTODEV_NAME_MAX_LEN, "_n5sym");
+	snprintf(name + strlen(name), RTE_CRYPTODEV_NAME_MAX_LEN - strlen(name),
+		 "_n5sym");
 	ndev->rte_sym_dev.driver = &nitrox_rte_sym_drv;
 	ndev->rte_sym_dev.numa_node = ndev->pdev->device.numa_node;
 	ndev->rte_sym_dev.devargs = NULL;
diff --git a/dpdk/drivers/crypto/octeontx/otx_cryptodev_ops.c b/dpdk/drivers/crypto/octeontx/otx_cryptodev_ops.c
index ba56b212b9..4eadb773ef 100644
--- a/dpdk/drivers/crypto/octeontx/otx_cryptodev_ops.c
+++ b/dpdk/drivers/crypto/octeontx/otx_cryptodev_ops.c
@@ -905,6 +905,7 @@ otx_cpt_dev_create(struct rte_cryptodev *c_dev)
 				RTE_CRYPTODEV_FF_HW_ACCELERATED |
 				RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
 				RTE_CRYPTODEV_FF_IN_PLACE_SGL |
+				RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 				RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
 				RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT;
 		break;
diff --git a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.c b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.c
index 7fd216bb39..8523817847 100644
--- a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.c
+++ b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.c
@@ -24,6 +24,8 @@
 
 int otx2_cpt_logtype;
 
+uint8_t otx2_cryptodev_driver_id;
+
 static struct rte_pci_id pci_id_cpt_table[] = {
 	{
 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
@@ -68,45 +70,53 @@ otx2_cpt_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 
 	otx2_dev = &vf->otx2_dev;
 
-	/* Initialize the base otx2_dev object */
-	ret = otx2_dev_init(pci_dev, otx2_dev);
-	if (ret) {
-		CPT_LOG_ERR("Could not initialize otx2_dev");
-		goto pmd_destroy;
-	}
-
-	/* Get number of queues available on the device */
-	ret = otx2_cpt_available_queues_get(dev, &nb_queues);
-	if (ret) {
-		CPT_LOG_ERR("Could not determine the number of queues available");
-		goto otx2_dev_fini;
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		/* Initialize the base otx2_dev object */
+		ret = otx2_dev_init(pci_dev, otx2_dev);
+		if (ret) {
+			CPT_LOG_ERR("Could not initialize otx2_dev");
+			goto pmd_destroy;
+		}
+
+		/* Get number of queues available on the device */
+		ret = otx2_cpt_available_queues_get(dev, &nb_queues);
+		if (ret) {
+			CPT_LOG_ERR("Could not determine the number of queues available");
+			goto otx2_dev_fini;
+		}
+
+		/* Don't exceed the limits set per VF */
+		nb_queues = RTE_MIN(nb_queues, OTX2_CPT_MAX_QUEUES_PER_VF);
+
+		if (nb_queues == 0) {
+			CPT_LOG_ERR("No free queues available on the device");
+			goto otx2_dev_fini;
+		}
+
+		vf->max_queues = nb_queues;
+
+		CPT_LOG_INFO("Max queues supported by device: %d",
+				vf->max_queues);
 	}
 
-	/* Don't exceed the limits set per VF */
-	nb_queues = RTE_MIN(nb_queues, OTX2_CPT_MAX_QUEUES_PER_VF);
-
-	if (nb_queues == 0) {
-		CPT_LOG_ERR("No free queues available on the device");
-		goto otx2_dev_fini;
-	}
-
-	vf->max_queues = nb_queues;
-
-	CPT_LOG_INFO("Max queues supported by device: %d", vf->max_queues);
-
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			     RTE_CRYPTODEV_FF_HW_ACCELERATED |
 			     RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
 			     RTE_CRYPTODEV_FF_IN_PLACE_SGL |
+			     RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			     RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
 			     RTE_CRYPTODEV_FF_OOP_SGL_IN_SGL_OUT |
 			     RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO |
 			     RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT;
 
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+		otx2_cpt_set_enqdeq_fns(dev);
+
 	return 0;
 
 otx2_dev_fini:
-	otx2_dev_fini(pci_dev, otx2_dev);
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		otx2_dev_fini(pci_dev, otx2_dev);
 pmd_destroy:
 	rte_cryptodev_pmd_destroy(dev);
 exit:
@@ -145,6 +155,7 @@ static struct cryptodev_driver otx2_cryptodev_drv;
 RTE_INIT(otx2_cpt_init_log);
 RTE_PMD_REGISTER_PCI(CRYPTODEV_NAME_OCTEONTX2_PMD, otx2_cryptodev_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(CRYPTODEV_NAME_OCTEONTX2_PMD, pci_id_cpt_table);
+RTE_PMD_REGISTER_KMOD_DEP(CRYPTODEV_NAME_OCTEONTX2_PMD, "vfio-pci");
 RTE_PMD_REGISTER_CRYPTO_DRIVER(otx2_cryptodev_drv, otx2_cryptodev_pmd.driver,
 		otx2_cryptodev_driver_id);
 
diff --git a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.h b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.h
index 8e0ebc292a..17c0bee661 100644
--- a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.h
+++ b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev.h
@@ -38,6 +38,8 @@ extern int otx2_cpt_logtype;
 /*
  * Crypto device driver ID
  */
-uint8_t otx2_cryptodev_driver_id;
+extern uint8_t otx2_cryptodev_driver_id;
+
+void otx2_cpt_set_enqdeq_fns(struct rte_cryptodev *dev);
 
 #endif /* _OTX2_CRYPTODEV_H_ */
diff --git a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.c b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.c
index 65101b0d2f..292aff1928 100644
--- a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.c
+++ b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.c
@@ -518,8 +518,8 @@ otx2_cpt_enqueue_sym_sessless(struct otx2_cpt_qp *qp, struct rte_crypto_op *op,
 	int ret;
 
 	/* Create temporary session */
-
-	if (rte_mempool_get(qp->sess_mp, (void **)&sess))
+	sess = rte_cryptodev_sym_session_create(qp->sess_mp);
+	if (sess == NULL)
 		return -ENOMEM;
 
 	ret = sym_session_configure(driver_id, sym_op->xform, sess,
@@ -671,6 +671,8 @@ static inline void
 otx2_cpt_dequeue_post_process(struct otx2_cpt_qp *qp, struct rte_crypto_op *cop,
 			      uintptr_t *rsp, uint8_t cc)
 {
+	unsigned int sz;
+
 	if (cop->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {
 		if (likely(cc == NO_ERR)) {
 			/* Verify authentication data if required */
@@ -689,6 +691,9 @@ otx2_cpt_dequeue_post_process(struct otx2_cpt_qp *qp, struct rte_crypto_op *cop,
 		if (unlikely(cop->sess_type == RTE_CRYPTO_OP_SESSIONLESS)) {
 			sym_session_clear(otx2_cryptodev_driver_id,
 					  cop->sym->session);
+			sz = rte_cryptodev_sym_get_existing_header_session_size(
+					cop->sym->session);
+			memset(cop->sym->session, 0, sz);
 			rte_mempool_put(qp->sess_mp, cop->sym->session);
 			cop->sym->session = NULL;
 		}
@@ -808,6 +813,15 @@ otx2_cpt_dequeue_burst(void *qptr, struct rte_crypto_op **ops, uint16_t nb_ops)
 	return nb_completed;
 }
 
+void
+otx2_cpt_set_enqdeq_fns(struct rte_cryptodev *dev)
+{
+	dev->enqueue_burst = otx2_cpt_enqueue_burst;
+	dev->dequeue_burst = otx2_cpt_dequeue_burst;
+
+	rte_mb();
+}
+
 /* PMD ops */
 
 static int
@@ -857,10 +871,8 @@ otx2_cpt_dev_config(struct rte_cryptodev *dev,
 		goto queues_detach;
 	}
 
-	dev->enqueue_burst = otx2_cpt_enqueue_burst;
-	dev->dequeue_burst = otx2_cpt_dequeue_burst;
+	otx2_cpt_set_enqdeq_fns(dev);
 
-	rte_mb();
 	return 0;
 
 queues_detach:
diff --git a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.h b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.h
index a2724f7227..f83e36b486 100644
--- a/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.h
+++ b/dpdk/drivers/crypto/octeontx2/otx2_cryptodev_ops.h
@@ -16,6 +16,6 @@ enum otx2_cpt_egrp {
 	OTX2_CPT_EGRP_AE = 2
 };
 
-struct rte_cryptodev_ops otx2_cpt_ops;
+extern struct rte_cryptodev_ops otx2_cpt_ops;
 
 #endif /* _OTX2_CRYPTODEV_OPS_H_ */
diff --git a/dpdk/drivers/crypto/openssl/meson.build b/dpdk/drivers/crypto/openssl/meson.build
index 394e74c9eb..cd05f1dbaf 100644
--- a/dpdk/drivers/crypto/openssl/meson.build
+++ b/dpdk/drivers/crypto/openssl/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-dep = dependency('libcrypto', required: false)
+dep = dependency('libcrypto', required: false, method: 'pkg-config')
 if not dep.found()
 	build = false
 	reason = 'missing dependency, "libcrypto"'
diff --git a/dpdk/drivers/crypto/openssl/openssl_pmd_private.h b/dpdk/drivers/crypto/openssl/openssl_pmd_private.h
index 43ac3813df..b2054b3754 100644
--- a/dpdk/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/dpdk/drivers/crypto/openssl/openssl_pmd_private.h
@@ -16,7 +16,7 @@
 /**< Open SSL Crypto PMD device name */
 
 /** OPENSSL PMD LOGTYPE DRIVER */
-int openssl_logtype_driver;
+extern int openssl_logtype_driver;
 #define OPENSSL_LOG(level, fmt, ...)  \
 	rte_log(RTE_LOG_ ## level, openssl_logtype_driver,  \
 			"%s() line %u: " fmt "\n", __func__, __LINE__,  \
diff --git a/dpdk/drivers/crypto/openssl/rte_openssl_pmd.c b/dpdk/drivers/crypto/openssl/rte_openssl_pmd.c
index 91f028308c..c294f60b7d 100644
--- a/dpdk/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/dpdk/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -18,6 +18,7 @@
 
 #define DES_BLOCK_SIZE 8
 
+int openssl_logtype_driver;
 static uint8_t cryptodev_driver_id;
 
 #if (OPENSSL_VERSION_NUMBER < 0x10100000L)
@@ -762,10 +763,10 @@ get_session(struct openssl_qp *qp, struct rte_crypto_op *op)
 			return NULL;
 
 		/* provide internal session */
-		void *_sess = NULL;
+		void *_sess = rte_cryptodev_sym_session_create(qp->sess_mp);
 		void *_sess_private_data = NULL;
 
-		if (rte_mempool_get(qp->sess_mp, (void **)&_sess))
+		if (_sess == NULL)
 			return NULL;
 
 		if (rte_mempool_get(qp->sess_mp_priv,
@@ -2037,6 +2038,26 @@ process_asym_op(struct openssl_qp *qp, struct rte_crypto_op *op,
 	return retval;
 }
 
+static void
+copy_plaintext(struct rte_mbuf *m_src, struct rte_mbuf *m_dst,
+		struct rte_crypto_op *op)
+{
+	uint8_t *p_src, *p_dst;
+
+	p_src = rte_pktmbuf_mtod(m_src, uint8_t *);
+	p_dst = rte_pktmbuf_mtod(m_dst, uint8_t *);
+
+	/**
+	 * Copy the content between cipher offset and auth offset
+	 * for generating correct digest.
+	 */
+	if (op->sym->cipher.data.offset > op->sym->auth.data.offset)
+		memcpy(p_dst + op->sym->auth.data.offset,
+				p_src + op->sym->auth.data.offset,
+				op->sym->cipher.data.offset -
+				op->sym->auth.data.offset);
+}
+
 /** Process crypto operation for mbuf */
 static int
 process_op(struct openssl_qp *qp, struct rte_crypto_op *op,
@@ -2059,6 +2080,9 @@ process_op(struct openssl_qp *qp, struct rte_crypto_op *op,
 		break;
 	case OPENSSL_CHAIN_CIPHER_AUTH:
 		process_openssl_cipher_op(op, sess, msrc, mdst);
+		/* OOP */
+		if (msrc != mdst)
+			copy_plaintext(msrc, mdst, op);
 		process_openssl_auth_op(qp, op, sess, mdst, mdst);
 		break;
 	case OPENSSL_CHAIN_AUTH_CIPHER:
diff --git a/dpdk/drivers/crypto/qat/meson.build b/dpdk/drivers/crypto/qat/meson.build
index fc65923a76..8d1e25a845 100644
--- a/dpdk/drivers/crypto/qat/meson.build
+++ b/dpdk/drivers/crypto/qat/meson.build
@@ -5,7 +5,7 @@
 # driver which comes later. Here we just add our sources files to the list
 build = false
 reason = '' # sentinal value to suppress printout
-dep = dependency('libcrypto', required: false)
+dep = dependency('libcrypto', required: false, method: 'pkg-config')
 qat_includes += include_directories('.')
 qat_deps += 'cryptodev'
 if dep.found()
diff --git a/dpdk/drivers/crypto/qat/qat_asym.c b/dpdk/drivers/crypto/qat/qat_asym.c
index ae0dd79562..85973812a8 100644
--- a/dpdk/drivers/crypto/qat/qat_asym.c
+++ b/dpdk/drivers/crypto/qat/qat_asym.c
@@ -475,7 +475,7 @@ qat_asym_build_request(void *in_op,
 	if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
 		ctx = (struct qat_asym_session *)
 			get_asym_session_private_data(
-			op->asym->session, cryptodev_qat_asym_driver_id);
+			op->asym->session, qat_asym_driver_id);
 		if (unlikely(ctx == NULL)) {
 			QAT_LOG(ERR, "Session has not been created for this device");
 			goto error;
@@ -693,7 +693,7 @@ qat_asym_process_response(void **op, uint8_t *resp,
 
 	if (rx_op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
 		ctx = (struct qat_asym_session *)get_asym_session_private_data(
-			rx_op->asym->session, cryptodev_qat_asym_driver_id);
+			rx_op->asym->session, qat_asym_driver_id);
 		qat_asym_collect_response(rx_op, cookie, ctx->xform);
 	} else if (rx_op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
 		qat_asym_collect_response(rx_op, cookie, rx_op->asym->xform);
diff --git a/dpdk/drivers/crypto/qat/qat_asym_pmd.c b/dpdk/drivers/crypto/qat/qat_asym_pmd.c
index c8a52b669b..2b69b8ecf9 100644
--- a/dpdk/drivers/crypto/qat/qat_asym_pmd.c
+++ b/dpdk/drivers/crypto/qat/qat_asym_pmd.c
@@ -11,7 +11,7 @@
 #include "qat_sym_capabilities.h"
 #include "qat_asym_capabilities.h"
 
-uint8_t cryptodev_qat_asym_driver_id;
+uint8_t qat_asym_driver_id;
 
 static const struct rte_cryptodev_capabilities qat_gen1_asym_capabilities[] = {
 	QAT_BASE_GEN1_ASYM_CAPABILITIES,
@@ -63,7 +63,7 @@ static void qat_asym_dev_info_get(struct rte_cryptodev *dev,
 							QAT_SERVICE_ASYMMETRIC);
 		info->feature_flags = dev->feature_flags;
 		info->capabilities = internals->qat_dev_capabilities;
-		info->driver_id = cryptodev_qat_asym_driver_id;
+		info->driver_id = qat_asym_driver_id;
 		/* No limit of number of sessions */
 		info->sym.max_nb_sessions = 0;
 	}
@@ -160,6 +160,7 @@ static int qat_asym_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
 							= *qp_addr;
 
 	qp = (struct qat_qp *)*qp_addr;
+	qp->min_enq_burst_threshold = qat_private->min_enq_burst_threshold;
 
 	for (i = 0; i < qp->nb_descriptors; i++) {
 		int j;
@@ -235,35 +236,55 @@ static const struct rte_driver cryptodev_qat_asym_driver = {
 };
 
 int
-qat_asym_dev_create(struct qat_pci_device *qat_pci_dev)
+qat_asym_dev_create(struct qat_pci_device *qat_pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param)
 {
+	int i = 0;
+	struct qat_device_info *qat_dev_instance =
+			&qat_pci_devs[qat_pci_dev->qat_dev_id];
+
 	struct rte_cryptodev_pmd_init_params init_params = {
 			.name = "",
-			.socket_id = qat_pci_dev->pci_dev->device.numa_node,
+			.socket_id =
+				qat_dev_instance->pci_dev->device.numa_node,
 			.private_data_size = sizeof(struct qat_asym_dev_private)
 	};
 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
+	char capa_memz_name[RTE_CRYPTODEV_NAME_MAX_LEN];
 	struct rte_cryptodev *cryptodev;
 	struct qat_asym_dev_private *internals;
 
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		qat_pci_dev->qat_asym_driver_id =
+				qat_asym_driver_id;
+	} else if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		if (qat_pci_dev->qat_asym_driver_id !=
+				qat_asym_driver_id) {
+			QAT_LOG(ERR,
+				"Device %s have different driver id than corresponding device in primary process",
+				name);
+			return -(EFAULT);
+		}
+	}
+
 	snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s_%s",
 			qat_pci_dev->name, "asym");
 	QAT_LOG(DEBUG, "Creating QAT ASYM device %s\n", name);
 
 	/* Populate subset device to use in cryptodev device creation */
-	qat_pci_dev->asym_rte_dev.driver = &cryptodev_qat_asym_driver;
-	qat_pci_dev->asym_rte_dev.numa_node =
-				qat_pci_dev->pci_dev->device.numa_node;
-	qat_pci_dev->asym_rte_dev.devargs = NULL;
+	qat_dev_instance->asym_rte_dev.driver = &cryptodev_qat_asym_driver;
+	qat_dev_instance->asym_rte_dev.numa_node =
+			qat_dev_instance->pci_dev->device.numa_node;
+	qat_dev_instance->asym_rte_dev.devargs = NULL;
 
 	cryptodev = rte_cryptodev_pmd_create(name,
-			&(qat_pci_dev->asym_rte_dev), &init_params);
+			&(qat_dev_instance->asym_rte_dev), &init_params);
 
 	if (cryptodev == NULL)
 		return -ENODEV;
 
-	qat_pci_dev->asym_rte_dev.name = cryptodev->data->name;
-	cryptodev->driver_id = cryptodev_qat_asym_driver_id;
+	qat_dev_instance->asym_rte_dev.name = cryptodev->data->name;
+	cryptodev->driver_id = qat_asym_driver_id;
 	cryptodev->dev_ops = &crypto_qat_ops;
 
 	cryptodev->enqueue_burst = qat_asym_pmd_enqueue_op_burst;
@@ -274,13 +295,49 @@ qat_asym_dev_create(struct qat_pci_device *qat_pci_dev)
 			RTE_CRYPTODEV_FF_ASYM_SESSIONLESS |
 			RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP |
 			RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	snprintf(capa_memz_name, RTE_CRYPTODEV_NAME_MAX_LEN,
+			"QAT_ASYM_CAPA_GEN_%d",
+			qat_pci_dev->qat_dev_gen);
+
 	internals = cryptodev->data->dev_private;
 	internals->qat_dev = qat_pci_dev;
-	qat_pci_dev->asym_dev = internals;
-
 	internals->asym_dev_id = cryptodev->data->dev_id;
 	internals->qat_dev_capabilities = qat_gen1_asym_capabilities;
 
+	internals->capa_mz = rte_memzone_lookup(capa_memz_name);
+	if (internals->capa_mz == NULL) {
+		internals->capa_mz = rte_memzone_reserve(capa_memz_name,
+			sizeof(qat_gen1_asym_capabilities),
+			rte_socket_id(), 0);
+	}
+	if (internals->capa_mz == NULL) {
+		QAT_LOG(DEBUG,
+			"Error allocating memzone for capabilities, destroying PMD for %s",
+			name);
+		rte_cryptodev_pmd_destroy(cryptodev);
+		memset(&qat_dev_instance->asym_rte_dev, 0,
+			sizeof(qat_dev_instance->asym_rte_dev));
+		return -EFAULT;
+	}
+
+	memcpy(internals->capa_mz->addr, qat_gen1_asym_capabilities,
+			sizeof(qat_gen1_asym_capabilities));
+	internals->qat_dev_capabilities = internals->capa_mz->addr;
+
+	while (1) {
+		if (qat_dev_cmd_param[i].name == NULL)
+			break;
+		if (!strcmp(qat_dev_cmd_param[i].name, ASYM_ENQ_THRESHOLD_NAME))
+			internals->min_enq_burst_threshold =
+					qat_dev_cmd_param[i].val;
+		i++;
+	}
+
+	qat_pci_dev->asym_dev = internals;
 	QAT_LOG(DEBUG, "Created QAT ASYM device %s as cryptodev instance %d",
 			cryptodev->data->name, internals->asym_dev_id);
 	return 0;
@@ -295,12 +352,14 @@ qat_asym_dev_destroy(struct qat_pci_device *qat_pci_dev)
 		return -ENODEV;
 	if (qat_pci_dev->asym_dev == NULL)
 		return 0;
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_memzone_free(qat_pci_dev->asym_dev->capa_mz);
 
 	/* free crypto device */
 	cryptodev = rte_cryptodev_pmd_get_dev(
 			qat_pci_dev->asym_dev->asym_dev_id);
 	rte_cryptodev_pmd_destroy(cryptodev);
-	qat_pci_dev->asym_rte_dev.name = NULL;
+	qat_pci_devs[qat_pci_dev->qat_dev_id].asym_rte_dev.name = NULL;
 	qat_pci_dev->asym_dev = NULL;
 
 	return 0;
@@ -309,4 +368,4 @@ qat_asym_dev_destroy(struct qat_pci_device *qat_pci_dev)
 static struct cryptodev_driver qat_crypto_drv;
 RTE_PMD_REGISTER_CRYPTO_DRIVER(qat_crypto_drv,
 		cryptodev_qat_asym_driver,
-		cryptodev_qat_asym_driver_id);
+		qat_asym_driver_id);
diff --git a/dpdk/drivers/crypto/qat/qat_asym_pmd.h b/dpdk/drivers/crypto/qat/qat_asym_pmd.h
index 895d0f6d6a..3b5abddec8 100644
--- a/dpdk/drivers/crypto/qat/qat_asym_pmd.h
+++ b/dpdk/drivers/crypto/qat/qat_asym_pmd.h
@@ -13,7 +13,7 @@
 #define CRYPTODEV_NAME_QAT_ASYM_PMD	crypto_qat_asym
 
 
-extern uint8_t cryptodev_qat_asym_driver_id;
+extern uint8_t qat_asym_driver_id;
 
 /** private data structure for a QAT device.
  * This QAT device is a device offering only asymmetric crypto service,
@@ -26,6 +26,9 @@ struct qat_asym_dev_private {
 	/**< Device instance for this rte_cryptodev */
 	const struct rte_cryptodev_capabilities *qat_dev_capabilities;
 	/* QAT device asymmetric crypto capabilities */
+	const struct rte_memzone *capa_mz;
+	/* Shared memzone for storing capabilities */
+	uint16_t min_enq_burst_threshold;
 };
 
 uint16_t
@@ -42,7 +45,8 @@ int qat_asym_session_configure(struct rte_cryptodev *dev,
 		struct rte_mempool *mempool);
 
 int
-qat_asym_dev_create(struct qat_pci_device *qat_pci_dev);
+qat_asym_dev_create(struct qat_pci_device *qat_pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
 qat_asym_dev_destroy(struct qat_pci_device *qat_pci_dev);
diff --git a/dpdk/drivers/crypto/qat/qat_sym.c b/dpdk/drivers/crypto/qat/qat_sym.c
index 5c9904cbf9..fda20ad26d 100644
--- a/dpdk/drivers/crypto/qat/qat_sym.c
+++ b/dpdk/drivers/crypto/qat/qat_sym.c
@@ -179,7 +179,7 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 	}
 
 	ctx = (struct qat_sym_session *)get_sym_session_private_data(
-			op->sym->session, cryptodev_qat_driver_id);
+				op->sym->session, qat_sym_driver_id);
 
 	if (unlikely(ctx == NULL)) {
 		QAT_DP_LOG(ERR, "Session was not created for this device");
diff --git a/dpdk/drivers/crypto/qat/qat_sym.h b/dpdk/drivers/crypto/qat/qat_sym.h
index bc6426c327..758b06d865 100644
--- a/dpdk/drivers/crypto/qat/qat_sym.h
+++ b/dpdk/drivers/crypto/qat/qat_sym.h
@@ -155,7 +155,7 @@ qat_sym_process_response(void **op, uint8_t *resp)
 		struct qat_sym_session *sess = (struct qat_sym_session *)
 						get_sym_session_private_data(
 						rx_op->sym->session,
-						cryptodev_qat_driver_id);
+						qat_sym_driver_id);
 
 
 		if (sess->bpi_ctx)
diff --git a/dpdk/drivers/crypto/qat/qat_sym_capabilities.h b/dpdk/drivers/crypto/qat/qat_sym_capabilities.h
index 028a56c568..8591795aa0 100644
--- a/dpdk/drivers/crypto/qat/qat_sym_capabilities.h
+++ b/dpdk/drivers/crypto/qat/qat_sym_capabilities.h
@@ -6,6 +6,111 @@
 #define _QAT_SYM_CAPABILITIES_H_
 
 #define QAT_BASE_GEN1_SYM_CAPABILITIES					\
+	{	/* SHA1 */						\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,	\
+			{.auth = {					\
+				.algo = RTE_CRYPTO_AUTH_SHA1,		\
+				.block_size = 64,			\
+				.key_size = {				\
+					.min = 0,			\
+					.max = 0,			\
+					.increment = 0			\
+				},					\
+				.digest_size = {			\
+					.min = 1,			\
+					.max = 20,			\
+					.increment = 1			\
+				},					\
+				.iv_size = { 0 }			\
+			}, }						\
+		}, }							\
+	},								\
+	{	/* SHA224 */						\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,	\
+			{.auth = {					\
+				.algo = RTE_CRYPTO_AUTH_SHA224,		\
+				.block_size = 64,			\
+				.key_size = {				\
+					.min = 0,			\
+					.max = 0,			\
+					.increment = 0			\
+				},					\
+				.digest_size = {			\
+					.min = 1,			\
+					.max = 28,			\
+					.increment = 1			\
+				},					\
+				.iv_size = { 0 }			\
+			}, }						\
+		}, }							\
+	},								\
+	{	/* SHA256 */						\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,	\
+			{.auth = {					\
+				.algo = RTE_CRYPTO_AUTH_SHA256,		\
+				.block_size = 64,			\
+				.key_size = {				\
+					.min = 0,			\
+					.max = 0,			\
+					.increment = 0			\
+				},					\
+				.digest_size = {			\
+					.min = 1,			\
+					.max = 32,			\
+					.increment = 1			\
+				},					\
+				.iv_size = { 0 }			\
+			}, }						\
+		}, }							\
+	},								\
+	{	/* SHA384 */						\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,	\
+			{.auth = {					\
+				.algo = RTE_CRYPTO_AUTH_SHA384,		\
+				.block_size = 128,			\
+				.key_size = {				\
+					.min = 0,			\
+					.max = 0,			\
+					.increment = 0			\
+				},					\
+				.digest_size = {			\
+					.min = 1,			\
+					.max = 48,			\
+					.increment = 1			\
+				},					\
+				.iv_size = { 0 }			\
+			}, }						\
+		}, }							\
+	},								\
+	{	/* SHA512 */						\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,	\
+			{.auth = {					\
+				.algo = RTE_CRYPTO_AUTH_SHA512,		\
+				.block_size = 128,			\
+				.key_size = {				\
+					.min = 0,			\
+					.max = 0,			\
+					.increment = 0			\
+				},					\
+				.digest_size = {			\
+					.min = 1,			\
+					.max = 64,			\
+					.increment = 1			\
+				},					\
+				.iv_size = { 0 }			\
+			}, }						\
+		}, }							\
+	},								\
 	{	/* SHA1 HMAC */						\
 		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
 		{.sym = {						\
@@ -314,7 +419,7 @@
 				.key_size = {				\
 					.min = 32,			\
 					.max = 64,			\
-					.increment = 0			\
+					.increment = 32			\
 				},					\
 				.iv_size = {				\
 					.min = 16,			\
diff --git a/dpdk/drivers/crypto/qat/qat_sym_pmd.c b/dpdk/drivers/crypto/qat/qat_sym_pmd.c
index 71f21ceb25..31ed6a99aa 100644
--- a/dpdk/drivers/crypto/qat/qat_sym_pmd.c
+++ b/dpdk/drivers/crypto/qat/qat_sym_pmd.c
@@ -14,7 +14,9 @@
 #include "qat_sym_session.h"
 #include "qat_sym_pmd.h"
 
-uint8_t cryptodev_qat_driver_id;
+#define MIXED_CRYPTO_MIN_FW_VER 0x04090000
+
+uint8_t qat_sym_driver_id;
 
 static const struct rte_cryptodev_capabilities qat_gen1_sym_capabilities[] = {
 	QAT_BASE_GEN1_SYM_CAPABILITIES,
@@ -27,6 +29,12 @@ static const struct rte_cryptodev_capabilities qat_gen2_sym_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+static const struct rte_cryptodev_capabilities qat_gen3_sym_capabilities[] = {
+	QAT_BASE_GEN1_SYM_CAPABILITIES,
+	QAT_EXTRA_GEN2_SYM_CAPABILITIES,
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static int qat_sym_qp_release(struct rte_cryptodev *dev,
 	uint16_t queue_pair_id);
 
@@ -72,7 +80,7 @@ static void qat_sym_dev_info_get(struct rte_cryptodev *dev,
 			qat_qps_per_service(sym_hw_qps, QAT_SERVICE_SYMMETRIC);
 		info->feature_flags = dev->feature_flags;
 		info->capabilities = internals->qat_dev_capabilities;
-		info->driver_id = cryptodev_qat_driver_id;
+		info->driver_id = qat_sym_driver_id;
 		/* No limit of number of sessions */
 		info->sym.max_nb_sessions = 0;
 	}
@@ -169,6 +177,7 @@ static int qat_sym_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
 							= *qp_addr;
 
 	qp = (struct qat_qp *)*qp_addr;
+	qp->min_enq_burst_threshold = qat_private->min_enq_burst_threshold;
 
 	for (i = 0; i < qp->nb_descriptors; i++) {
 
@@ -186,6 +195,31 @@ static int qat_sym_qp_setup(struct rte_cryptodev *dev, uint16_t qp_id,
 				qat_sgl_dst);
 	}
 
+	/* Get fw version from QAT (GEN2), skip if we've got it already */
+	if (qp->qat_dev_gen == QAT_GEN2 && !(qat_private->internal_capabilities
+			& QAT_SYM_CAP_VALID)) {
+		ret = qat_cq_get_fw_version(qp);
+
+		if (ret < 0) {
+			qat_sym_qp_release(dev, qp_id);
+			return ret;
+		}
+
+		if (ret != 0)
+			QAT_LOG(DEBUG, "QAT firmware version: %d.%d.%d",
+					(ret >> 24) & 0xff,
+					(ret >> 16) & 0xff,
+					(ret >> 8) & 0xff);
+		else
+			QAT_LOG(DEBUG, "unknown QAT firmware version");
+
+		/* set capabilities based on the fw version */
+		qat_private->internal_capabilities = QAT_SYM_CAP_VALID |
+				((ret >= MIXED_CRYPTO_MIN_FW_VER) ?
+						QAT_SYM_CAP_MIXED_CRYPTO : 0);
+		ret = 0;
+	}
+
 	return ret;
 }
 
@@ -237,35 +271,63 @@ static const struct rte_driver cryptodev_qat_sym_driver = {
 };
 
 int
-qat_sym_dev_create(struct qat_pci_device *qat_pci_dev)
+qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param __rte_unused)
 {
+	int i = 0;
+	struct qat_device_info *qat_dev_instance =
+			&qat_pci_devs[qat_pci_dev->qat_dev_id];
+
 	struct rte_cryptodev_pmd_init_params init_params = {
 			.name = "",
-			.socket_id = qat_pci_dev->pci_dev->device.numa_node,
+			.socket_id =
+				qat_dev_instance->pci_dev->device.numa_node,
 			.private_data_size = sizeof(struct qat_sym_dev_private)
 	};
 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
+	char capa_memz_name[RTE_CRYPTODEV_NAME_MAX_LEN];
 	struct rte_cryptodev *cryptodev;
 	struct qat_sym_dev_private *internals;
+	const struct rte_cryptodev_capabilities *capabilities;
+	uint64_t capa_size;
+
+	/*
+	 * All processes must use same driver id so they can share sessions.
+	 * Store driver_id so we can validate that all processes have the same
+	 * value, typically they have, but could differ if binaries built
+	 * separately.
+	 */
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		qat_pci_dev->qat_sym_driver_id =
+				qat_sym_driver_id;
+	} else if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		if (qat_pci_dev->qat_sym_driver_id !=
+				qat_sym_driver_id) {
+			QAT_LOG(ERR,
+				"Device %s have different driver id than corresponding device in primary process",
+				name);
+			return -(EFAULT);
+		}
+	}
 
 	snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s_%s",
 			qat_pci_dev->name, "sym");
 	QAT_LOG(DEBUG, "Creating QAT SYM device %s", name);
 
 	/* Populate subset device to use in cryptodev device creation */
-	qat_pci_dev->sym_rte_dev.driver = &cryptodev_qat_sym_driver;
-	qat_pci_dev->sym_rte_dev.numa_node =
-				qat_pci_dev->pci_dev->device.numa_node;
-	qat_pci_dev->sym_rte_dev.devargs = NULL;
+	qat_dev_instance->sym_rte_dev.driver = &cryptodev_qat_sym_driver;
+	qat_dev_instance->sym_rte_dev.numa_node =
+			qat_dev_instance->pci_dev->device.numa_node;
+	qat_dev_instance->sym_rte_dev.devargs = NULL;
 
 	cryptodev = rte_cryptodev_pmd_create(name,
-			&(qat_pci_dev->sym_rte_dev), &init_params);
+			&(qat_dev_instance->sym_rte_dev), &init_params);
 
 	if (cryptodev == NULL)
 		return -ENODEV;
 
-	qat_pci_dev->sym_rte_dev.name = cryptodev->data->name;
-	cryptodev->driver_id = cryptodev_qat_driver_id;
+	qat_dev_instance->sym_rte_dev.name = cryptodev->data->name;
+	cryptodev->driver_id = qat_sym_driver_id;
 	cryptodev->dev_ops = &crypto_qat_ops;
 
 	cryptodev->enqueue_burst = qat_sym_pmd_enqueue_op_burst;
@@ -281,27 +343,68 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev)
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
 
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	snprintf(capa_memz_name, RTE_CRYPTODEV_NAME_MAX_LEN,
+			"QAT_SYM_CAPA_GEN_%d",
+			qat_pci_dev->qat_dev_gen);
+
 	internals = cryptodev->data->dev_private;
 	internals->qat_dev = qat_pci_dev;
-	qat_pci_dev->sym_dev = internals;
 
 	internals->sym_dev_id = cryptodev->data->dev_id;
 	switch (qat_pci_dev->qat_dev_gen) {
 	case QAT_GEN1:
-		internals->qat_dev_capabilities = qat_gen1_sym_capabilities;
+		capabilities = qat_gen1_sym_capabilities;
+		capa_size = sizeof(qat_gen1_sym_capabilities);
 		break;
 	case QAT_GEN2:
+		capabilities = qat_gen2_sym_capabilities;
+		capa_size = sizeof(qat_gen2_sym_capabilities);
+		break;
 	case QAT_GEN3:
-		internals->qat_dev_capabilities = qat_gen2_sym_capabilities;
+		capabilities = qat_gen3_sym_capabilities;
+		capa_size = sizeof(qat_gen3_sym_capabilities);
 		break;
 	default:
-		internals->qat_dev_capabilities = qat_gen2_sym_capabilities;
 		QAT_LOG(DEBUG,
-			"QAT gen %d capabilities unknown, default to GEN2",
-					qat_pci_dev->qat_dev_gen);
-		break;
+			"QAT gen %d capabilities unknown",
+			qat_pci_dev->qat_dev_gen);
+		rte_cryptodev_pmd_destroy(cryptodev);
+		memset(&qat_dev_instance->sym_rte_dev, 0,
+			sizeof(qat_dev_instance->sym_rte_dev));
+		return -(EINVAL);
+	}
+	internals->capa_mz = rte_memzone_lookup(capa_memz_name);
+	if (internals->capa_mz == NULL) {
+	internals->capa_mz = rte_memzone_reserve(capa_memz_name,
+		capa_size,
+		rte_socket_id(), 0);
 	}
+	if (internals->capa_mz == NULL) {
+	QAT_LOG(DEBUG,
+		"Error allocating memzone for capabilities, destroying PMD for %s",
+		name);
+	rte_cryptodev_pmd_destroy(cryptodev);
+	memset(&qat_dev_instance->sym_rte_dev, 0,
+		sizeof(qat_dev_instance->sym_rte_dev));
+	return -EFAULT;
+	}
+
+	memcpy(internals->capa_mz->addr, capabilities, capa_size);
+	internals->qat_dev_capabilities = internals->capa_mz->addr;
 
+	while (1) {
+		if (qat_dev_cmd_param[i].name == NULL)
+			break;
+		if (!strcmp(qat_dev_cmd_param[i].name, SYM_ENQ_THRESHOLD_NAME))
+			internals->min_enq_burst_threshold =
+					qat_dev_cmd_param[i].val;
+		i++;
+	}
+
+	qat_pci_dev->sym_dev = internals;
 	QAT_LOG(DEBUG, "Created QAT SYM device %s as cryptodev instance %d",
 			cryptodev->data->name, internals->sym_dev_id);
 	return 0;
@@ -316,11 +419,13 @@ qat_sym_dev_destroy(struct qat_pci_device *qat_pci_dev)
 		return -ENODEV;
 	if (qat_pci_dev->sym_dev == NULL)
 		return 0;
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+		rte_memzone_free(qat_pci_dev->sym_dev->capa_mz);
 
 	/* free crypto device */
 	cryptodev = rte_cryptodev_pmd_get_dev(qat_pci_dev->sym_dev->sym_dev_id);
 	rte_cryptodev_pmd_destroy(cryptodev);
-	qat_pci_dev->sym_rte_dev.name = NULL;
+	qat_pci_devs[qat_pci_dev->qat_dev_id].sym_rte_dev.name = NULL;
 	qat_pci_dev->sym_dev = NULL;
 
 	return 0;
@@ -329,4 +434,4 @@ qat_sym_dev_destroy(struct qat_pci_device *qat_pci_dev)
 static struct cryptodev_driver qat_crypto_drv;
 RTE_PMD_REGISTER_CRYPTO_DRIVER(qat_crypto_drv,
 		cryptodev_qat_sym_driver,
-		cryptodev_qat_driver_id);
+		qat_sym_driver_id);
diff --git a/dpdk/drivers/crypto/qat/qat_sym_pmd.h b/dpdk/drivers/crypto/qat/qat_sym_pmd.h
index 7ddaf453e9..e2ed112cb1 100644
--- a/dpdk/drivers/crypto/qat/qat_sym_pmd.h
+++ b/dpdk/drivers/crypto/qat/qat_sym_pmd.h
@@ -15,7 +15,11 @@
 /** Intel(R) QAT Symmetric Crypto PMD driver name */
 #define CRYPTODEV_NAME_QAT_SYM_PMD	crypto_qat
 
-extern uint8_t cryptodev_qat_driver_id;
+/* Internal capabilities */
+#define QAT_SYM_CAP_MIXED_CRYPTO	(1 << 0)
+#define QAT_SYM_CAP_VALID		(1 << 31)
+
+extern uint8_t qat_sym_driver_id;
 
 /** private data structure for a QAT device.
  * This QAT device is a device offering only symmetric crypto service,
@@ -27,11 +31,16 @@ struct qat_sym_dev_private {
 	uint8_t sym_dev_id;
 	/**< Device instance for this rte_cryptodev */
 	const struct rte_cryptodev_capabilities *qat_dev_capabilities;
-	/* QAT device symmetric crypto capabilities */
+	/**< QAT device symmetric crypto capabilities */
+	uint32_t internal_capabilities; /* see flags QAT_SYM_CAP_xxx */
+	const struct rte_memzone *capa_mz;
+	/* Shared memzone for storing capabilities */
+	uint16_t min_enq_burst_threshold;
 };
 
 int
-qat_sym_dev_create(struct qat_pci_device *qat_pci_dev);
+qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
+		struct qat_dev_cmd_param *qat_dev_cmd_param);
 
 int
 qat_sym_dev_destroy(struct qat_pci_device *qat_pci_dev);
diff --git a/dpdk/drivers/crypto/qat/qat_sym_session.c b/dpdk/drivers/crypto/qat/qat_sym_session.c
index 72290ba480..8545be2791 100644
--- a/dpdk/drivers/crypto/qat/qat_sym_session.c
+++ b/dpdk/drivers/crypto/qat/qat_sym_session.c
@@ -19,6 +19,41 @@
 #include "qat_sym_session.h"
 #include "qat_sym_pmd.h"
 
+/* SHA1 - 20 bytes - Initialiser state can be found in FIPS stds 180-2 */
+static const uint8_t sha1InitialState[] = {
+	0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba,
+	0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0};
+
+/* SHA 224 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */
+static const uint8_t sha224InitialState[] = {
+	0xc1, 0x05, 0x9e, 0xd8, 0x36, 0x7c, 0xd5, 0x07, 0x30, 0x70, 0xdd,
+	0x17, 0xf7, 0x0e, 0x59, 0x39, 0xff, 0xc0, 0x0b, 0x31, 0x68, 0x58,
+	0x15, 0x11, 0x64, 0xf9, 0x8f, 0xa7, 0xbe, 0xfa, 0x4f, 0xa4};
+
+/* SHA 256 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */
+static const uint8_t sha256InitialState[] = {
+	0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3,
+	0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05,
+	0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19};
+
+/* SHA 384 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */
+static const uint8_t sha384InitialState[] = {
+	0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29,
+	0x2a, 0x36, 0x7c, 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70,
+	0xdd, 0x17, 0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39, 0x67,
+	0x33, 0x26, 0x67, 0xff, 0xc0, 0x0b, 0x31, 0x8e, 0xb4, 0x4a, 0x87,
+	0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c, 0x2e, 0x0d, 0x64, 0xf9, 0x8f,
+	0xa7, 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, 0xa4};
+
+/* SHA 512 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */
+static const uint8_t sha512InitialState[] = {
+	0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae,
+	0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94,
+	0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51,
+	0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c,
+	0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd,
+	0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79};
+
 /** Frees a context previously created
  *  Depends on openssl libcrypto
  */
@@ -416,6 +451,79 @@ qat_sym_session_configure(struct rte_cryptodev *dev,
 	return 0;
 }
 
+static void
+qat_sym_session_set_ext_hash_flags(struct qat_sym_session *session,
+		uint8_t hash_flag)
+{
+	struct icp_qat_fw_comn_req_hdr *header = &session->fw_req.comn_hdr;
+	struct icp_qat_fw_cipher_auth_cd_ctrl_hdr *cd_ctrl =
+			(struct icp_qat_fw_cipher_auth_cd_ctrl_hdr *)
+			session->fw_req.cd_ctrl.content_desc_ctrl_lw;
+
+	/* Set the Use Extended Protocol Flags bit in LW 1 */
+	QAT_FIELD_SET(header->comn_req_flags,
+			QAT_COMN_EXT_FLAGS_USED,
+			QAT_COMN_EXT_FLAGS_BITPOS,
+			QAT_COMN_EXT_FLAGS_MASK);
+
+	/* Set Hash Flags in LW 28 */
+	cd_ctrl->hash_flags |= hash_flag;
+
+	/* Set proto flags in LW 1 */
+	switch (session->qat_cipher_alg) {
+	case ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2:
+		ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags,
+				ICP_QAT_FW_LA_SNOW_3G_PROTO);
+		ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(
+				header->serv_specif_flags, 0);
+		break;
+	case ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3:
+		ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags,
+				ICP_QAT_FW_LA_NO_PROTO);
+		ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(
+				header->serv_specif_flags,
+				ICP_QAT_FW_LA_ZUC_3G_PROTO);
+		break;
+	default:
+		ICP_QAT_FW_LA_PROTO_SET(header->serv_specif_flags,
+				ICP_QAT_FW_LA_NO_PROTO);
+		ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET(
+				header->serv_specif_flags, 0);
+		break;
+	}
+}
+
+static void
+qat_sym_session_handle_mixed(const struct rte_cryptodev *dev,
+		struct qat_sym_session *session)
+{
+	const struct qat_sym_dev_private *qat_private = dev->data->dev_private;
+	enum qat_device_gen min_dev_gen = (qat_private->internal_capabilities &
+			QAT_SYM_CAP_MIXED_CRYPTO) ? QAT_GEN2 : QAT_GEN3;
+
+	if (session->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3 &&
+			session->qat_cipher_alg !=
+			ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3) {
+		session->min_qat_dev_gen = min_dev_gen;
+		qat_sym_session_set_ext_hash_flags(session,
+			1 << ICP_QAT_FW_AUTH_HDR_FLAG_ZUC_EIA3_BITPOS);
+	} else if (session->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2 &&
+			session->qat_cipher_alg !=
+			ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2) {
+		session->min_qat_dev_gen = min_dev_gen;
+		qat_sym_session_set_ext_hash_flags(session,
+			1 << ICP_QAT_FW_AUTH_HDR_FLAG_SNOW3G_UIA2_BITPOS);
+	} else if ((session->aes_cmac ||
+			session->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_NULL) &&
+			(session->qat_cipher_alg ==
+			ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2 ||
+			session->qat_cipher_alg ==
+			ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3)) {
+		session->min_qat_dev_gen = min_dev_gen;
+		qat_sym_session_set_ext_hash_flags(session, 0);
+	}
+}
+
 int
 qat_sym_session_set_parameters(struct rte_cryptodev *dev,
 		struct rte_crypto_sym_xform *xform, void *session_private)
@@ -463,6 +571,8 @@ qat_sym_session_set_parameters(struct rte_cryptodev *dev,
 					xform, session);
 			if (ret < 0)
 				return ret;
+			/* Special handling of mixed hash+cipher algorithms */
+			qat_sym_session_handle_mixed(dev, session);
 		}
 		break;
 	case ICP_QAT_FW_LA_CMD_HASH_CIPHER:
@@ -480,6 +590,8 @@ qat_sym_session_set_parameters(struct rte_cryptodev *dev,
 					xform, session);
 			if (ret < 0)
 				return ret;
+			/* Special handling of mixed hash+cipher algorithms */
+			qat_sym_session_handle_mixed(dev, session);
 		}
 		break;
 	case ICP_QAT_FW_LA_CMD_TRNG_GET_RANDOM:
@@ -580,8 +692,29 @@ qat_sym_session_configure_auth(struct rte_cryptodev *dev,
 	const uint8_t *key_data = auth_xform->key.data;
 	uint8_t key_length = auth_xform->key.length;
 	session->aes_cmac = 0;
+	session->auth_mode = ICP_QAT_HW_AUTH_MODE1;
 
 	switch (auth_xform->algo) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_SHA1;
+		session->auth_mode = ICP_QAT_HW_AUTH_MODE0;
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_SHA224;
+		session->auth_mode = ICP_QAT_HW_AUTH_MODE0;
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_SHA256;
+		session->auth_mode = ICP_QAT_HW_AUTH_MODE0;
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_SHA384;
+		session->auth_mode = ICP_QAT_HW_AUTH_MODE0;
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_SHA512;
+		session->auth_mode = ICP_QAT_HW_AUTH_MODE0;
+		break;
 	case RTE_CRYPTO_AUTH_SHA1_HMAC:
 		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_SHA1;
 		break;
@@ -635,11 +768,6 @@ qat_sym_session_configure_auth(struct rte_cryptodev *dev,
 		}
 		session->qat_hash_alg = ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3;
 		break;
-	case RTE_CRYPTO_AUTH_SHA1:
-	case RTE_CRYPTO_AUTH_SHA256:
-	case RTE_CRYPTO_AUTH_SHA512:
-	case RTE_CRYPTO_AUTH_SHA224:
-	case RTE_CRYPTO_AUTH_SHA384:
 	case RTE_CRYPTO_AUTH_MD5:
 	case RTE_CRYPTO_AUTH_AES_CBC_MAC:
 		QAT_LOG(ERR, "Crypto: Unsupported hash alg %u",
@@ -727,6 +855,8 @@ qat_sym_session_configure_aead(struct rte_cryptodev *dev,
 	session->cipher_iv.offset = xform->aead.iv.offset;
 	session->cipher_iv.length = xform->aead.iv.length;
 
+	session->auth_mode = ICP_QAT_HW_AUTH_MODE1;
+
 	switch (aead_xform->algo) {
 	case RTE_CRYPTO_AEAD_AES_GCM:
 		if (qat_sym_validate_aes_key(aead_xform->key.length,
@@ -1524,7 +1654,7 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 		(struct icp_qat_fw_la_auth_req_params *)
 		((char *)&req_tmpl->serv_specif_rqpars +
 		ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET);
-	uint16_t state1_size = 0, state2_size = 0;
+	uint16_t state1_size = 0, state2_size = 0, cd_extra_size = 0;
 	uint16_t hash_offset, cd_size;
 	uint32_t *aad_len = NULL;
 	uint32_t wordIndex  = 0;
@@ -1574,10 +1704,11 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 	hash = (struct icp_qat_hw_auth_setup *)cdesc->cd_cur_ptr;
 	hash->auth_config.reserved = 0;
 	hash->auth_config.config =
-			ICP_QAT_HW_AUTH_CONFIG_BUILD(ICP_QAT_HW_AUTH_MODE1,
+			ICP_QAT_HW_AUTH_CONFIG_BUILD(cdesc->auth_mode,
 				cdesc->qat_hash_alg, digestsize);
 
-	if (cdesc->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2
+	if (cdesc->auth_mode == ICP_QAT_HW_AUTH_MODE0
+		|| cdesc->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2
 		|| cdesc->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_KASUMI_F9
 		|| cdesc->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3
 		|| cdesc->qat_hash_alg == ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC
@@ -1600,6 +1731,15 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 	 */
 	switch (cdesc->qat_hash_alg) {
 	case ICP_QAT_HW_AUTH_ALGO_SHA1:
+		if (cdesc->auth_mode == ICP_QAT_HW_AUTH_MODE0) {
+			/* Plain SHA-1 */
+			rte_memcpy(cdesc->cd_cur_ptr, sha1InitialState,
+					sizeof(sha1InitialState));
+			state1_size = qat_hash_get_state1_size(
+					cdesc->qat_hash_alg);
+			break;
+		}
+		/* SHA-1 HMAC */
 		if (qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA1, authkey,
 			authkeylen, cdesc->cd_cur_ptr, &state1_size,
 			cdesc->aes_cmac)) {
@@ -1609,6 +1749,15 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 		state2_size = RTE_ALIGN_CEIL(ICP_QAT_HW_SHA1_STATE2_SZ, 8);
 		break;
 	case ICP_QAT_HW_AUTH_ALGO_SHA224:
+		if (cdesc->auth_mode == ICP_QAT_HW_AUTH_MODE0) {
+			/* Plain SHA-224 */
+			rte_memcpy(cdesc->cd_cur_ptr, sha224InitialState,
+					sizeof(sha224InitialState));
+			state1_size = qat_hash_get_state1_size(
+					cdesc->qat_hash_alg);
+			break;
+		}
+		/* SHA-224 HMAC */
 		if (qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA224, authkey,
 			authkeylen, cdesc->cd_cur_ptr, &state1_size,
 			cdesc->aes_cmac)) {
@@ -1618,6 +1767,15 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 		state2_size = ICP_QAT_HW_SHA224_STATE2_SZ;
 		break;
 	case ICP_QAT_HW_AUTH_ALGO_SHA256:
+		if (cdesc->auth_mode == ICP_QAT_HW_AUTH_MODE0) {
+			/* Plain SHA-256 */
+			rte_memcpy(cdesc->cd_cur_ptr, sha256InitialState,
+					sizeof(sha256InitialState));
+			state1_size = qat_hash_get_state1_size(
+					cdesc->qat_hash_alg);
+			break;
+		}
+		/* SHA-256 HMAC */
 		if (qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA256, authkey,
 			authkeylen, cdesc->cd_cur_ptr,	&state1_size,
 			cdesc->aes_cmac)) {
@@ -1627,6 +1785,15 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 		state2_size = ICP_QAT_HW_SHA256_STATE2_SZ;
 		break;
 	case ICP_QAT_HW_AUTH_ALGO_SHA384:
+		if (cdesc->auth_mode == ICP_QAT_HW_AUTH_MODE0) {
+			/* Plain SHA-384 */
+			rte_memcpy(cdesc->cd_cur_ptr, sha384InitialState,
+					sizeof(sha384InitialState));
+			state1_size = qat_hash_get_state1_size(
+					cdesc->qat_hash_alg);
+			break;
+		}
+		/* SHA-384 HMAC */
 		if (qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA384, authkey,
 			authkeylen, cdesc->cd_cur_ptr, &state1_size,
 			cdesc->aes_cmac)) {
@@ -1636,6 +1803,15 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 		state2_size = ICP_QAT_HW_SHA384_STATE2_SZ;
 		break;
 	case ICP_QAT_HW_AUTH_ALGO_SHA512:
+		if (cdesc->auth_mode == ICP_QAT_HW_AUTH_MODE0) {
+			/* Plain SHA-512 */
+			rte_memcpy(cdesc->cd_cur_ptr, sha512InitialState,
+					sizeof(sha512InitialState));
+			state1_size = qat_hash_get_state1_size(
+					cdesc->qat_hash_alg);
+			break;
+		}
+		/* SHA-512 HMAC */
 		if (qat_sym_do_precomputes(ICP_QAT_HW_AUTH_ALGO_SHA512, authkey,
 			authkeylen, cdesc->cd_cur_ptr,	&state1_size,
 			cdesc->aes_cmac)) {
@@ -1700,7 +1876,7 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 		memcpy(cipherconfig->key, authkey, authkeylen);
 		memset(cipherconfig->key + authkeylen,
 				0, ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ);
-		cdesc->cd_cur_ptr += sizeof(struct icp_qat_hw_cipher_config) +
+		cd_extra_size += sizeof(struct icp_qat_hw_cipher_config) +
 				authkeylen + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ;
 		auth_param->hash_state_sz = ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ >> 3;
 		break;
@@ -1716,8 +1892,7 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 			+ ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ);
 
 		memcpy(cdesc->cd_cur_ptr + state1_size, authkey, authkeylen);
-		cdesc->cd_cur_ptr += state1_size + state2_size
-			+ ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ;
+		cd_extra_size += ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ;
 		auth_param->hash_state_sz = ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ >> 3;
 		cdesc->min_qat_dev_gen = QAT_GEN2;
 
@@ -1803,7 +1978,7 @@ int qat_sym_session_aead_create_cd_auth(struct qat_sym_session *cdesc,
 			 RTE_ALIGN_CEIL(hash_cd_ctrl->inner_state1_sz, 8))
 					>> 3);
 
-	cdesc->cd_cur_ptr += state1_size + state2_size;
+	cdesc->cd_cur_ptr += state1_size + state2_size + cd_extra_size;
 	cd_size = cdesc->cd_cur_ptr-(uint8_t *)&cdesc->cd;
 
 	cd_pars->u.s.content_desc_addr = cdesc->cd_paddr;
diff --git a/dpdk/drivers/crypto/qat/qat_sym_session.h b/dpdk/drivers/crypto/qat/qat_sym_session.h
index 98985d6867..bcab5b2b60 100644
--- a/dpdk/drivers/crypto/qat/qat_sym_session.h
+++ b/dpdk/drivers/crypto/qat/qat_sym_session.h
@@ -62,6 +62,7 @@ struct qat_sym_session {
 	enum icp_qat_hw_cipher_mode qat_mode;
 	enum icp_qat_hw_auth_algo qat_hash_alg;
 	enum icp_qat_hw_auth_op auth_op;
+	enum icp_qat_hw_auth_mode auth_mode;
 	void *bpi_ctx;
 	struct qat_sym_cd cd;
 	uint8_t *cd_cur_ptr;
diff --git a/dpdk/drivers/crypto/scheduler/meson.build b/dpdk/drivers/crypto/scheduler/meson.build
index c5ba2d6804..cb0f3a8ba9 100644
--- a/dpdk/drivers/crypto/scheduler/meson.build
+++ b/dpdk/drivers/crypto/scheduler/meson.build
@@ -13,7 +13,7 @@ sources = files(
 	'scheduler_roundrobin.c',
 )
 
-headers = files(
+install_headers(
 	'rte_cryptodev_scheduler.h',
 	'rte_cryptodev_scheduler_operations.h',
 )
diff --git a/dpdk/drivers/crypto/scheduler/scheduler_pmd_private.h b/dpdk/drivers/crypto/scheduler/scheduler_pmd_private.h
index 3ed480c183..d6870177b1 100644
--- a/dpdk/drivers/crypto/scheduler/scheduler_pmd_private.h
+++ b/dpdk/drivers/crypto/scheduler/scheduler_pmd_private.h
@@ -59,7 +59,6 @@ struct scheduler_qp_ctx {
 	uint32_t max_nb_objs;
 
 	struct rte_ring *order_ring;
-	uint32_t seqn;
 } __rte_cache_aligned;
 
 
diff --git a/dpdk/drivers/crypto/snow3g/rte_snow3g_pmd.c b/dpdk/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 9d07e1ab2c..32d94c5ab5 100644
--- a/dpdk/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/dpdk/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -16,6 +16,7 @@
 #define SNOW3G_MAX_BURST 8
 #define BYTE_LEN 8
 
+int snow3g_logtype_driver;
 static uint8_t cryptodev_driver_id;
 
 /** Get xform chain order. */
@@ -567,6 +568,7 @@ cryptodev_snow3g_create(const char *name,
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			cpu_flags;
 
 	internals = dev->data->dev_private;
diff --git a/dpdk/drivers/crypto/snow3g/snow3g_pmd_private.h b/dpdk/drivers/crypto/snow3g/snow3g_pmd_private.h
index 1fe05eb567..1070800960 100644
--- a/dpdk/drivers/crypto/snow3g/snow3g_pmd_private.h
+++ b/dpdk/drivers/crypto/snow3g/snow3g_pmd_private.h
@@ -11,7 +11,7 @@
 /**< SNOW 3G PMD device name */
 
 /** SNOW 3G PMD LOGTYPE DRIVER */
-int snow3g_logtype_driver;
+extern int snow3g_logtype_driver;
 
 #define SNOW3G_LOG(level, fmt, ...)  \
 	rte_log(RTE_LOG_ ## level, snow3g_logtype_driver,  \
diff --git a/dpdk/drivers/crypto/zuc/rte_zuc_pmd.c b/dpdk/drivers/crypto/zuc/rte_zuc_pmd.c
index 8e214cd50e..bc02d9d4af 100644
--- a/dpdk/drivers/crypto/zuc/rte_zuc_pmd.c
+++ b/dpdk/drivers/crypto/zuc/rte_zuc_pmd.c
@@ -14,6 +14,7 @@
 #define ZUC_MAX_BURST 4
 #define BYTE_LEN 8
 
+int zuc_logtype_driver;
 static uint8_t cryptodev_driver_id;
 
 /** Get xform chain order. */
@@ -475,6 +476,7 @@ cryptodev_zuc_create(const char *name,
 
 	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			cpu_flags;
 
 	internals = dev->data->dev_private;
diff --git a/dpdk/drivers/crypto/zuc/zuc_pmd_private.h b/dpdk/drivers/crypto/zuc/zuc_pmd_private.h
index 428efd4bb5..dc492b1710 100644
--- a/dpdk/drivers/crypto/zuc/zuc_pmd_private.h
+++ b/dpdk/drivers/crypto/zuc/zuc_pmd_private.h
@@ -8,10 +8,10 @@
 #include <sso_zuc.h>
 
 #define CRYPTODEV_NAME_ZUC_PMD		crypto_zuc
-/**< KASUMI PMD device name */
+/**< ZUC PMD device name */
 
 /** ZUC PMD LOGTYPE DRIVER */
-int zuc_logtype_driver;
+extern int zuc_logtype_driver;
 #define ZUC_LOG(level, fmt, ...)  \
 	rte_log(RTE_LOG_ ## level, zuc_logtype_driver,  \
 			"%s()... line %u: " fmt "\n", __func__, __LINE__,  \
diff --git a/dpdk/drivers/event/dpaa/dpaa_eventdev.c b/dpdk/drivers/event/dpaa/dpaa_eventdev.c
index a7d57edce7..29b18fe62b 100644
--- a/dpdk/drivers/event/dpaa/dpaa_eventdev.c
+++ b/dpdk/drivers/event/dpaa/dpaa_eventdev.c
@@ -173,7 +173,7 @@ dpaa_event_dequeue_burst(void *port, struct rte_event ev[],
 	int ret;
 	u16 ch_id;
 	void *buffers[8];
-	u32 num_frames, i, irq = 0;
+	u32 num_frames, i;
 	uint64_t cur_ticks = 0, wait_time_ticks = 0;
 	struct dpaa_port *portal = (struct dpaa_port *)port;
 	struct rte_mbuf *mbuf;
@@ -222,8 +222,6 @@ dpaa_event_dequeue_burst(void *port, struct rte_event ev[],
 	do {
 		/* Lets dequeue the frames */
 		num_frames = qman_portal_dequeue(ev, nb_events, buffers);
-		if (irq)
-			irq = 0;
 		if (num_frames)
 			break;
 		cur_ticks = rte_get_timer_cycles();
diff --git a/dpdk/drivers/event/dpaa2/dpaa2_eventdev.c b/dpdk/drivers/event/dpaa2/dpaa2_eventdev.c
index d71361666c..5ae76d4d9d 100644
--- a/dpdk/drivers/event/dpaa2/dpaa2_eventdev.c
+++ b/dpdk/drivers/event/dpaa2/dpaa2_eventdev.c
@@ -391,7 +391,7 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev,
 	dev_info->max_event_priority_levels =
 		DPAA2_EVENT_MAX_EVENT_PRIORITY_LEVELS;
 	dev_info->max_event_ports = rte_fslmc_get_device_count(DPAA2_IO);
-	/* we only support dpio upto number of cores*/
+	/* we only support dpio up to number of cores */
 	if (dev_info->max_event_ports > rte_lcore_count())
 		dev_info->max_event_ports = rte_lcore_count();
 	dev_info->max_event_port_dequeue_depth =
@@ -403,7 +403,8 @@ dpaa2_eventdev_info_get(struct rte_eventdev *dev,
 		RTE_EVENT_DEV_CAP_BURST_MODE|
 		RTE_EVENT_DEV_CAP_RUNTIME_PORT_LINK |
 		RTE_EVENT_DEV_CAP_MULTIPLE_QUEUE_PORT |
-		RTE_EVENT_DEV_CAP_NONSEQ_MODE;
+		RTE_EVENT_DEV_CAP_NONSEQ_MODE |
+		RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES;
 
 }
 
@@ -479,6 +480,8 @@ dpaa2_eventdev_queue_def_conf(struct rte_eventdev *dev, uint8_t queue_id,
 	RTE_SET_USED(queue_id);
 
 	queue_conf->nb_atomic_flows = DPAA2_EVENT_QUEUE_ATOMIC_FLOWS;
+	queue_conf->nb_atomic_order_sequences =
+				DPAA2_EVENT_QUEUE_ORDER_SEQUENCES;
 	queue_conf->schedule_type = RTE_SCHED_TYPE_PARALLEL;
 	queue_conf->priority = RTE_EVENT_DEV_PRIORITY_NORMAL;
 }
@@ -564,14 +567,14 @@ dpaa2_eventdev_port_release(void *port)
 
 	EVENTDEV_INIT_FUNC_TRACE();
 
+	if (portal == NULL)
+		return;
+
 	/* TODO: Cleanup is required when ports are in linked state. */
 	if (portal->is_port_linked)
 		DPAA2_EVENTDEV_WARN("Event port must be unlinked before release");
 
-	if (portal)
-		rte_free(portal);
-
-	portal = NULL;
+	rte_free(portal);
 }
 
 static int
diff --git a/dpdk/drivers/event/dpaa2/dpaa2_eventdev_selftest.c b/dpdk/drivers/event/dpaa2/dpaa2_eventdev_selftest.c
index ba4f4bd234..1f35807b21 100644
--- a/dpdk/drivers/event/dpaa2/dpaa2_eventdev_selftest.c
+++ b/dpdk/drivers/event/dpaa2/dpaa2_eventdev_selftest.c
@@ -47,17 +47,6 @@ struct event_attr {
 	uint8_t seq;
 };
 
-static uint32_t seqn_list_index;
-static int seqn_list[NUM_PACKETS];
-
-static void
-seqn_list_init(void)
-{
-	RTE_BUILD_BUG_ON(NUM_PACKETS < MAX_EVENTS);
-	memset(seqn_list, 0, sizeof(seqn_list));
-	seqn_list_index = 0;
-}
-
 struct test_core_param {
 	rte_atomic32_t *total_events;
 	uint64_t dequeue_tmo_ticks;
@@ -516,7 +505,7 @@ launch_workers_and_wait(int (*master_worker)(void *),
 		return 0;
 
 	rte_atomic32_set(&atomic_total_events, total_events);
-	seqn_list_init();
+	RTE_BUILD_BUG_ON(NUM_PACKETS < MAX_EVENTS);
 
 	param = malloc(sizeof(struct test_core_param) * nb_workers);
 	if (!param)
diff --git a/dpdk/drivers/event/dsw/dsw_event.c b/dpdk/drivers/event/dsw/dsw_event.c
index 61a66fabf3..0df9209e4f 100644
--- a/dpdk/drivers/event/dsw/dsw_event.c
+++ b/dpdk/drivers/event/dsw/dsw_event.c
@@ -658,6 +658,9 @@ dsw_port_consider_migration(struct dsw_evdev *dsw,
 	if (dsw->num_ports == 1)
 		return;
 
+	if (seen_events_len < DSW_MAX_EVENTS_RECORDED)
+		return;
+
 	DSW_LOG_DP_PORT(DEBUG, source_port->id, "Considering migration.\n");
 
 	/* Randomize interval to avoid having all threads considering
@@ -930,11 +933,6 @@ dsw_port_ctl_process(struct dsw_evdev *dsw, struct dsw_port *port)
 {
 	struct dsw_ctl_msg msg;
 
-	/* So any table loads happens before the ring dequeue, in the
-	 * case of a 'paus' message.
-	 */
-	rte_smp_rmb();
-
 	if (dsw_port_ctl_dequeue(port, &msg) == 0) {
 		switch (msg.type) {
 		case DSW_CTL_PAUS_REQ:
@@ -1018,12 +1016,12 @@ dsw_event_enqueue(void *port, const struct rte_event *ev)
 }
 
 static __rte_always_inline uint16_t
-dsw_event_enqueue_burst_generic(void *port, const struct rte_event events[],
+dsw_event_enqueue_burst_generic(struct dsw_port *source_port,
+				const struct rte_event events[],
 				uint16_t events_len, bool op_types_known,
 				uint16_t num_new, uint16_t num_release,
 				uint16_t num_non_release)
 {
-	struct dsw_port *source_port = port;
 	struct dsw_evdev *dsw = source_port->dsw;
 	bool enough_credits;
 	uint16_t i;
@@ -1047,12 +1045,10 @@ dsw_event_enqueue_burst_generic(void *port, const struct rte_event events[],
 	 */
 	if (unlikely(events_len == 0)) {
 		dsw_port_note_op(source_port, DSW_MAX_PORT_OPS_PER_BG_TASK);
+		dsw_port_flush_out_buffers(dsw, source_port);
 		return 0;
 	}
 
-	if (unlikely(events_len > source_port->enqueue_depth))
-		events_len = source_port->enqueue_depth;
-
 	dsw_port_note_op(source_port, events_len);
 
 	if (!op_types_known)
@@ -1101,31 +1097,48 @@ dsw_event_enqueue_burst_generic(void *port, const struct rte_event events[],
 	DSW_LOG_DP_PORT(DEBUG, source_port->id, "%d non-release events "
 			"accepted.\n", num_non_release);
 
-	return num_non_release;
+	return (num_non_release + num_release);
 }
 
 uint16_t
 dsw_event_enqueue_burst(void *port, const struct rte_event events[],
 			uint16_t events_len)
 {
-	return dsw_event_enqueue_burst_generic(port, events, events_len, false,
-					       0, 0, 0);
+	struct dsw_port *source_port = port;
+
+	if (unlikely(events_len > source_port->enqueue_depth))
+		events_len = source_port->enqueue_depth;
+
+	return dsw_event_enqueue_burst_generic(source_port, events,
+					       events_len, false, 0, 0, 0);
 }
 
 uint16_t
 dsw_event_enqueue_new_burst(void *port, const struct rte_event events[],
 			    uint16_t events_len)
 {
-	return dsw_event_enqueue_burst_generic(port, events, events_len, true,
-					       events_len, 0, events_len);
+	struct dsw_port *source_port = port;
+
+	if (unlikely(events_len > source_port->enqueue_depth))
+		events_len = source_port->enqueue_depth;
+
+	return dsw_event_enqueue_burst_generic(source_port, events,
+					       events_len, true, events_len,
+					       0, events_len);
 }
 
 uint16_t
 dsw_event_enqueue_forward_burst(void *port, const struct rte_event events[],
 				uint16_t events_len)
 {
-	return dsw_event_enqueue_burst_generic(port, events, events_len, true,
-					       0, 0, events_len);
+	struct dsw_port *source_port = port;
+
+	if (unlikely(events_len > source_port->enqueue_depth))
+		events_len = source_port->enqueue_depth;
+
+	return dsw_event_enqueue_burst_generic(source_port, events,
+					       events_len, true, 0, 0,
+					       events_len);
 }
 
 uint16_t
@@ -1179,11 +1192,6 @@ static uint16_t
 dsw_port_dequeue_burst(struct dsw_port *port, struct rte_event *events,
 		       uint16_t num)
 {
-	struct dsw_port *source_port = port;
-	struct dsw_evdev *dsw = source_port->dsw;
-
-	dsw_port_ctl_process(dsw, source_port);
-
 	if (unlikely(port->in_buffer_len > 0)) {
 		uint16_t dequeued = RTE_MIN(num, port->in_buffer_len);
 
diff --git a/dpdk/drivers/event/octeontx2/otx2_evdev.c b/dpdk/drivers/event/octeontx2/otx2_evdev.c
index 2daeba42c7..5bdf23c362 100644
--- a/dpdk/drivers/event/octeontx2/otx2_evdev.c
+++ b/dpdk/drivers/event/octeontx2/otx2_evdev.c
@@ -648,7 +648,36 @@ sso_lf_cfg(struct otx2_sso_evdev *dev, struct otx2_mbox *mbox,
 static void
 otx2_sso_port_release(void *port)
 {
-	rte_free(port);
+	struct otx2_ssogws_cookie *gws_cookie = ssogws_get_cookie(port);
+	struct otx2_sso_evdev *dev;
+	int i;
+
+	if (!gws_cookie->configured)
+		goto free;
+
+	dev = sso_pmd_priv(gws_cookie->event_dev);
+	if (dev->dual_ws) {
+		struct otx2_ssogws_dual *ws = port;
+
+		for (i = 0; i < dev->nb_event_queues; i++) {
+			sso_port_link_modify((struct otx2_ssogws *)
+					     &ws->ws_state[0], i, false);
+			sso_port_link_modify((struct otx2_ssogws *)
+					     &ws->ws_state[1], i, false);
+		}
+		memset(ws, 0, sizeof(*ws));
+	} else {
+		struct otx2_ssogws *ws = port;
+
+		for (i = 0; i < dev->nb_event_queues; i++)
+			sso_port_link_modify(ws, i, false);
+		memset(ws, 0, sizeof(*ws));
+	}
+
+	memset(gws_cookie, 0, sizeof(*gws_cookie));
+
+free:
+	rte_free(gws_cookie);
 }
 
 static void
@@ -659,28 +688,41 @@ otx2_sso_queue_release(struct rte_eventdev *event_dev, uint8_t queue_id)
 }
 
 static void
-sso_clr_links(const struct rte_eventdev *event_dev)
+sso_restore_links(const struct rte_eventdev *event_dev)
 {
 	struct otx2_sso_evdev *dev = sso_pmd_priv(event_dev);
+	uint16_t *links_map;
 	int i, j;
 
 	for (i = 0; i < dev->nb_event_ports; i++) {
+		links_map = event_dev->data->links_map;
+		/* Point links_map to this port specific area */
+		links_map += (i * RTE_EVENT_MAX_QUEUES_PER_DEV);
 		if (dev->dual_ws) {
 			struct otx2_ssogws_dual *ws;
 
 			ws = event_dev->data->ports[i];
 			for (j = 0; j < dev->nb_event_queues; j++) {
+				if (links_map[j] == 0xdead)
+					continue;
 				sso_port_link_modify((struct otx2_ssogws *)
-						&ws->ws_state[0], j, false);
+						&ws->ws_state[0], j, true);
 				sso_port_link_modify((struct otx2_ssogws *)
-						&ws->ws_state[1], j, false);
+						&ws->ws_state[1], j, true);
+				sso_func_trace("Restoring port %d queue %d "
+						"link", i, j);
 			}
 		} else {
 			struct otx2_ssogws *ws;
 
 			ws = event_dev->data->ports[i];
-			for (j = 0; j < dev->nb_event_queues; j++)
-				sso_port_link_modify(ws, j, false);
+			for (j = 0; j < dev->nb_event_queues; j++) {
+				if (links_map[j] == 0xdead)
+					continue;
+				sso_port_link_modify(ws, j, true);
+				sso_func_trace("Restoring port %d queue %d "
+						"link", i, j);
+			}
 		}
 	}
 }
@@ -722,25 +764,29 @@ sso_configure_dual_ports(const struct rte_eventdev *event_dev)
 	}
 
 	for (i = 0; i < dev->nb_event_ports; i++) {
+		struct otx2_ssogws_cookie *gws_cookie;
 		struct otx2_ssogws_dual *ws;
 		uintptr_t base;
 
-		/* Free memory prior to re-allocation if needed */
 		if (event_dev->data->ports[i] != NULL) {
 			ws = event_dev->data->ports[i];
-			rte_free(ws);
-			ws = NULL;
-		}
-
-		/* Allocate event port memory */
-		ws = rte_zmalloc_socket("otx2_sso_ws",
-					sizeof(struct otx2_ssogws_dual),
+		} else {
+			/* Allocate event port memory */
+			ws = rte_zmalloc_socket("otx2_sso_ws",
+					sizeof(struct otx2_ssogws_dual) +
+					RTE_CACHE_LINE_SIZE,
 					RTE_CACHE_LINE_SIZE,
 					event_dev->data->socket_id);
-		if (ws == NULL) {
-			otx2_err("Failed to alloc memory for port=%d", i);
-			rc = -ENOMEM;
-			break;
+			if (ws == NULL) {
+				otx2_err("Failed to alloc memory for port=%d",
+					 i);
+				rc = -ENOMEM;
+				break;
+			}
+
+			/* First cache line is reserved for cookie */
+			ws = (struct otx2_ssogws_dual *)
+				((uint8_t *)ws + RTE_CACHE_LINE_SIZE);
 		}
 
 		ws->port = i;
@@ -752,6 +798,10 @@ sso_configure_dual_ports(const struct rte_eventdev *event_dev)
 		sso_set_port_ops((struct otx2_ssogws *)&ws->ws_state[1], base);
 		vws++;
 
+		gws_cookie = ssogws_get_cookie(ws);
+		gws_cookie->event_dev = event_dev;
+		gws_cookie->configured = 1;
+
 		event_dev->data->ports[i] = ws;
 	}
 
@@ -788,19 +838,21 @@ sso_configure_ports(const struct rte_eventdev *event_dev)
 	}
 
 	for (i = 0; i < nb_lf; i++) {
+		struct otx2_ssogws_cookie *gws_cookie;
 		struct otx2_ssogws *ws;
 		uintptr_t base;
 
 		/* Free memory prior to re-allocation if needed */
 		if (event_dev->data->ports[i] != NULL) {
 			ws = event_dev->data->ports[i];
-			rte_free(ws);
+			rte_free(ssogws_get_cookie(ws));
 			ws = NULL;
 		}
 
 		/* Allocate event port memory */
 		ws = rte_zmalloc_socket("otx2_sso_ws",
-					sizeof(struct otx2_ssogws),
+					sizeof(struct otx2_ssogws) +
+					RTE_CACHE_LINE_SIZE,
 					RTE_CACHE_LINE_SIZE,
 					event_dev->data->socket_id);
 		if (ws == NULL) {
@@ -809,10 +861,18 @@ sso_configure_ports(const struct rte_eventdev *event_dev)
 			break;
 		}
 
+		/* First cache line is reserved for cookie */
+		ws = (struct otx2_ssogws *)
+			((uint8_t *)ws + RTE_CACHE_LINE_SIZE);
+
 		ws->port = i;
 		base = dev->bar2 + (RVU_BLOCK_ADDR_SSOW << 20 | i << 12);
 		sso_set_port_ops(ws, base);
 
+		gws_cookie = ssogws_get_cookie(ws);
+		gws_cookie->event_dev = event_dev;
+		gws_cookie->configured = 1;
+
 		event_dev->data->ports[i] = ws;
 	}
 
@@ -1057,8 +1117,8 @@ otx2_sso_configure(const struct rte_eventdev *event_dev)
 		goto teardown_hwggrp;
 	}
 
-	/* Clear any prior port-queue mapping. */
-	sso_clr_links(event_dev);
+	/* Restore any prior port-queue mapping. */
+	sso_restore_links(event_dev);
 	rc = sso_ggrp_alloc_xaq(dev);
 	if (rc < 0) {
 		otx2_err("Failed to alloc xaq to ggrp %d", rc);
diff --git a/dpdk/drivers/event/octeontx2/otx2_evdev.h b/dpdk/drivers/event/octeontx2/otx2_evdev.h
index 231a12a52b..e134ea5ea3 100644
--- a/dpdk/drivers/event/octeontx2/otx2_evdev.h
+++ b/dpdk/drivers/event/octeontx2/otx2_evdev.h
@@ -16,7 +16,7 @@
 #include "otx2_mempool.h"
 #include "otx2_tim_evdev.h"
 
-#define EVENTDEV_NAME_OCTEONTX2_PMD otx2_eventdev
+#define EVENTDEV_NAME_OCTEONTX2_PMD event_octeontx2
 
 #define sso_func_trace otx2_sso_dbg
 
@@ -212,6 +212,18 @@ sso_pmd_priv(const struct rte_eventdev *event_dev)
 	return event_dev->data->dev_private;
 }
 
+struct otx2_ssogws_cookie {
+	const struct rte_eventdev *event_dev;
+	bool configured;
+};
+
+static inline struct otx2_ssogws_cookie *
+ssogws_get_cookie(void *ws)
+{
+	return (struct otx2_ssogws_cookie *)
+		((uint8_t *)ws - RTE_CACHE_LINE_SIZE);
+}
+
 static const union mbuf_initializer mbuf_init = {
 	.fields = {
 		.data_off = RTE_PKTMBUF_HEADROOM,
diff --git a/dpdk/drivers/event/octeontx2/otx2_evdev_adptr.c b/dpdk/drivers/event/octeontx2/otx2_evdev_adptr.c
index 233cba2aa3..8bdcfa3ea5 100644
--- a/dpdk/drivers/event/octeontx2/otx2_evdev_adptr.c
+++ b/dpdk/drivers/event/octeontx2/otx2_evdev_adptr.c
@@ -133,7 +133,7 @@ sso_rxq_disable(struct otx2_eth_dev *dev, uint16_t qid)
 	aq = otx2_mbox_alloc_msg_nix_aq_enq(mbox);
 	aq->qidx = qid;
 	aq->ctype = NIX_AQ_CTYPE_CQ;
-	aq->op = NIX_AQ_INSTOP_INIT;
+	aq->op = NIX_AQ_INSTOP_WRITE;
 
 	aq->cq.ena = 1;
 	aq->cq.caching = 1;
@@ -144,7 +144,7 @@ sso_rxq_disable(struct otx2_eth_dev *dev, uint16_t qid)
 
 	rc = otx2_mbox_process(mbox);
 	if (rc < 0) {
-		otx2_err("Failed to init cq context");
+		otx2_err("Failed to enable cq context");
 		goto fail;
 	}
 
diff --git a/dpdk/drivers/event/octeontx2/otx2_evdev_stats.h b/dpdk/drivers/event/octeontx2/otx2_evdev_stats.h
index 9d7c694ee6..74fcec8a07 100644
--- a/dpdk/drivers/event/octeontx2/otx2_evdev_stats.h
+++ b/dpdk/drivers/event/octeontx2/otx2_evdev_stats.h
@@ -67,7 +67,7 @@ otx2_sso_xstats_get(const struct rte_eventdev *event_dev,
 
 	switch (mode) {
 	case RTE_EVENT_DEV_XSTATS_DEVICE:
-		break;
+		return 0;
 	case RTE_EVENT_DEV_XSTATS_PORT:
 		if (queue_port_id >= (signed int)dev->nb_event_ports)
 			goto invalid_value;
diff --git a/dpdk/drivers/event/octeontx2/otx2_worker_dual.h b/dpdk/drivers/event/octeontx2/otx2_worker_dual.h
index 5134e3d525..fb6a8cd0d5 100644
--- a/dpdk/drivers/event/octeontx2/otx2_worker_dual.h
+++ b/dpdk/drivers/event/octeontx2/otx2_worker_dual.h
@@ -69,8 +69,11 @@ otx2_ssogws_dual_get_work(struct otx2_ssogws_state *ws,
 
 	if (event.sched_type != SSO_TT_EMPTY &&
 	    event.event_type == RTE_EVENT_TYPE_ETHDEV) {
-		otx2_wqe_to_mbuf(get_work1, mbuf, event.sub_event_type,
-				 (uint32_t) event.get_work0, flags, lookup_mem);
+		uint8_t port = event.sub_event_type;
+
+		event.sub_event_type = 0;
+		otx2_wqe_to_mbuf(get_work1, mbuf, port,
+				 event.flow_id, flags, lookup_mem);
 		/* Extracting tstamp, if PTP enabled. CGX will prepend the
 		 * timestamp at starting of packet data and it can be derieved
 		 * from WQE 9 dword which corresponds to SG iova.
diff --git a/dpdk/drivers/mempool/dpaa2/meson.build b/dpdk/drivers/mempool/dpaa2/meson.build
index d79fc31644..a4fe684fc4 100644
--- a/dpdk/drivers/mempool/dpaa2/meson.build
+++ b/dpdk/drivers/mempool/dpaa2/meson.build
@@ -9,5 +9,7 @@ endif
 deps += ['bus_fslmc']
 sources = files('dpaa2_hw_mempool.c')
 
+install_headers('rte_dpaa2_mempool.h')
+
 # depends on fslmc bus which uses experimental API
 allow_experimental_apis = true
diff --git a/dpdk/drivers/mempool/octeontx/octeontx_fpavf.c b/dpdk/drivers/mempool/octeontx/octeontx_fpavf.c
index c97267db3c..e37b844842 100644
--- a/dpdk/drivers/mempool/octeontx/octeontx_fpavf.c
+++ b/dpdk/drivers/mempool/octeontx/octeontx_fpavf.c
@@ -267,7 +267,7 @@ octeontx_fpapf_pool_setup(unsigned int gpool, unsigned int buf_size,
 		POOL_LTYPE(0x2) | POOL_STYPE(0) | POOL_SET_NAT_ALIGN |
 		POOL_ENA;
 
-	cfg.aid = FPA_AURA_IDX(gpool);
+	cfg.aid = 0;
 	cfg.pool_cfg = reg;
 	cfg.pool_stack_base = phys_addr;
 	cfg.pool_stack_end = phys_addr + memsz;
@@ -305,10 +305,8 @@ octeontx_fpapf_pool_destroy(unsigned int gpool_index)
 	int ret = -1;
 
 	fpa = octeontx_get_fpavf(gpool_index);
-	if (fpa == NULL) {
-		ret = -EINVAL;
-		goto err;
-	}
+	if (fpa == NULL)
+		return -EINVAL;
 
 	hdr.coproc = FPA_COPROC;
 	hdr.msg = FPA_CONFIGSET;
@@ -355,7 +353,7 @@ octeontx_fpapf_aura_attach(unsigned int gpool_index)
 	hdr.vfid = gpool_index;
 	hdr.res_code = 0;
 	memset(&cfg, 0x0, sizeof(struct octeontx_mbox_fpa_cfg));
-	cfg.aid = FPA_AURA_IDX(gpool_index);
+	cfg.aid = 0;
 
 	ret = octeontx_mbox_send(&hdr, &cfg,
 					sizeof(struct octeontx_mbox_fpa_cfg),
@@ -384,7 +382,7 @@ octeontx_fpapf_aura_detach(unsigned int gpool_index)
 		goto err;
 	}
 
-	cfg.aid = FPA_AURA_IDX(gpool_index);
+	cfg.aid = 0;
 	hdr.coproc = FPA_COPROC;
 	hdr.msg = FPA_DETACHAURA;
 	hdr.vfid = gpool_index;
diff --git a/dpdk/drivers/mempool/octeontx2/otx2_mempool_ops.c b/dpdk/drivers/mempool/octeontx2/otx2_mempool_ops.c
index ea4b1c45d2..18bdb0b4c4 100644
--- a/dpdk/drivers/mempool/octeontx2/otx2_mempool_ops.c
+++ b/dpdk/drivers/mempool/octeontx2/otx2_mempool_ops.c
@@ -637,10 +637,10 @@ static int
 otx2_npa_alloc(struct rte_mempool *mp)
 {
 	uint32_t block_size, block_count;
+	uint64_t aura_handle = 0;
 	struct otx2_npa_lf *lf;
 	struct npa_aura_s aura;
 	struct npa_pool_s pool;
-	uint64_t aura_handle;
 	int rc;
 
 	lf = otx2_npa_lf_obj_get();
diff --git a/dpdk/drivers/meson.build b/dpdk/drivers/meson.build
index 72eec46088..696079680b 100644
--- a/dpdk/drivers/meson.build
+++ b/dpdk/drivers/meson.build
@@ -9,8 +9,8 @@ endif
 dpdk_driver_classes = ['common',
 	       'bus',
 	       'mempool', # depends on common and bus.
-	       'raw',     # depends on common and bus.
-	       'net',     # depends on common, bus, mempool and raw.
+	       'net',     # depends on common, bus, mempool
+	       'raw',     # depends on common, bus and net.
 	       'crypto',  # depends on common, bus and mempool (net in future).
 	       'compress', # depends on common, bus, mempool.
 	       'event',   # depends on common, bus, mempool and net.
@@ -151,7 +151,7 @@ foreach class:dpdk_driver_classes
 			version_map = '@0@/@1@/@2@_version.map'.format(
 					meson.current_source_dir(),
 					drv_path, lib_name)
-			implib = dir_name + '.dll.a'
+			implib = 'lib' + lib_name + '.dll.a'
 
 			def_file = custom_target(lib_name + '_def',
 				command: [map_to_def_cmd, '@INPUT@', '@OUTPUT@'],
@@ -159,8 +159,14 @@ foreach class:dpdk_driver_classes
 				output: '@0@_exports.def'.format(lib_name))
 			lk_deps = [version_map, def_file]
 			if is_windows
-				lk_args = ['-Wl,/def:' + def_file.full_path(),
-					'-Wl,/implib:lib\\' + implib]
+				if is_ms_linker
+					lk_args = ['-Wl,/def:' + def_file.full_path()]
+					if meson.version().version_compare('<0.54.0')
+						lk_args += ['-Wl,/implib:drivers\\' + implib]
+					endif
+				else
+					lk_args = []
+				endif
 			else
 				lk_args = ['-Wl,--version-script=' + version_map]
 				# on unix systems check the output of the
@@ -192,7 +198,7 @@ foreach class:dpdk_driver_classes
 			shared_dep = declare_dependency(link_with: shared_lib,
 					include_directories: includes,
 					dependencies: shared_deps)
-			static_dep = declare_dependency(link_with: static_lib,
+			static_dep = declare_dependency(
 					include_directories: includes,
 					dependencies: static_deps)
 
diff --git a/dpdk/drivers/net/af_packet/rte_eth_af_packet.c b/dpdk/drivers/net/af_packet/rte_eth_af_packet.c
index f5806bf42c..00387ed0ac 100644
--- a/dpdk/drivers/net/af_packet/rte_eth_af_packet.c
+++ b/dpdk/drivers/net/af_packet/rte_eth_af_packet.c
@@ -604,6 +604,8 @@ rte_pmd_init_internals(struct rte_vdev_device *dev,
 	for (q = 0; q < nb_queues; q++) {
 		(*internals)->rx_queue[q].map = MAP_FAILED;
 		(*internals)->tx_queue[q].map = MAP_FAILED;
+		(*internals)->rx_queue[q].sockfd = -1;
+		(*internals)->tx_queue[q].sockfd = -1;
 	}
 
 	req = &((*internals)->req);
@@ -621,20 +623,20 @@ rte_pmd_init_internals(struct rte_vdev_device *dev,
 		PMD_LOG(ERR,
 			"%s: I/F name too long (%s)",
 			name, pair->value);
-		return -1;
+		goto free_internals;
 	}
 	if (ioctl(sockfd, SIOCGIFINDEX, &ifr) == -1) {
 		PMD_LOG_ERRNO(ERR, "%s: ioctl failed (SIOCGIFINDEX)", name);
-		return -1;
+		goto free_internals;
 	}
 	(*internals)->if_name = strdup(pair->value);
 	if ((*internals)->if_name == NULL)
-		return -1;
+		goto free_internals;
 	(*internals)->if_index = ifr.ifr_ifindex;
 
 	if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1) {
 		PMD_LOG_ERRNO(ERR, "%s: ioctl failed (SIOCGIFHWADDR)", name);
-		return -1;
+		goto free_internals;
 	}
 	memcpy(&(*internals)->eth_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
 
@@ -658,7 +660,7 @@ rte_pmd_init_internals(struct rte_vdev_device *dev,
 			PMD_LOG_ERRNO(ERR,
 				"%s: could not open AF_PACKET socket",
 				name);
-			return -1;
+			goto error;
 		}
 
 		tpver = TPACKET_V2;
@@ -802,15 +804,19 @@ rte_pmd_init_internals(struct rte_vdev_device *dev,
 	if (qsockfd != -1)
 		close(qsockfd);
 	for (q = 0; q < nb_queues; q++) {
-		munmap((*internals)->rx_queue[q].map,
-		       2 * req->tp_block_size * req->tp_block_nr);
+		if ((*internals)->rx_queue[q].map != MAP_FAILED)
+			munmap((*internals)->rx_queue[q].map,
+			       2 * req->tp_block_size * req->tp_block_nr);
 
 		rte_free((*internals)->rx_queue[q].rd);
 		rte_free((*internals)->tx_queue[q].rd);
-		if (((*internals)->rx_queue[q].sockfd != 0) &&
+		if (((*internals)->rx_queue[q].sockfd >= 0) &&
 			((*internals)->rx_queue[q].sockfd != qsockfd))
 			close((*internals)->rx_queue[q].sockfd);
 	}
+free_internals:
+	rte_free((*internals)->rx_queue);
+	rte_free((*internals)->tx_queue);
 	free((*internals)->if_name);
 	rte_free(*internals);
 	return -1;
diff --git a/dpdk/drivers/net/af_xdp/meson.build b/dpdk/drivers/net/af_xdp/meson.build
index 307aa0e388..a9007439fe 100644
--- a/dpdk/drivers/net/af_xdp/meson.build
+++ b/dpdk/drivers/net/af_xdp/meson.build
@@ -3,7 +3,7 @@
 
 sources = files('rte_eth_af_xdp.c')
 
-bpf_dep = dependency('libbpf', required: false)
+bpf_dep = dependency('libbpf', required: false, method: 'pkg-config')
 if not bpf_dep.found()
 	bpf_dep = cc.find_library('bpf', required: false)
 endif
diff --git a/dpdk/drivers/net/af_xdp/rte_eth_af_xdp.c b/dpdk/drivers/net/af_xdp/rte_eth_af_xdp.c
index 2b1245ee4f..ac253b1d81 100644
--- a/dpdk/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/dpdk/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -34,6 +34,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_mempool.h>
 #include <rte_mbuf.h>
 #include <rte_malloc.h>
 #include <rte_ring.h>
@@ -58,13 +59,6 @@ static int af_xdp_logtype;
 
 #define ETH_AF_XDP_FRAME_SIZE		2048
 #define ETH_AF_XDP_NUM_BUFFERS		4096
-#ifdef XDP_UMEM_UNALIGNED_CHUNK_FLAG
-#define ETH_AF_XDP_MBUF_OVERHEAD	128 /* sizeof(struct rte_mbuf) */
-#define ETH_AF_XDP_DATA_HEADROOM \
-	(ETH_AF_XDP_MBUF_OVERHEAD + RTE_PKTMBUF_HEADROOM)
-#else
-#define ETH_AF_XDP_DATA_HEADROOM	0
-#endif
 #define ETH_AF_XDP_DFLT_NUM_DESCS	XSK_RING_CONS__DEFAULT_NUM_DESCS
 #define ETH_AF_XDP_DFLT_START_QUEUE_IDX	0
 #define ETH_AF_XDP_DFLT_QUEUE_COUNT	1
@@ -171,7 +165,8 @@ reserve_fill_queue_zc(struct xsk_umem_info *umem, uint16_t reserve_size,
 		uint64_t addr;
 
 		fq_addr = xsk_ring_prod__fill_addr(fq, idx++);
-		addr = (uint64_t)bufs[i] - (uint64_t)umem->buffer;
+		addr = (uint64_t)bufs[i] - (uint64_t)umem->buffer -
+				umem->mb_pool->header_size;
 		*fq_addr = addr;
 	}
 
@@ -242,7 +237,7 @@ af_xdp_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	if (rte_pktmbuf_alloc_bulk(umem->mb_pool, fq_bufs, nb_pkts)) {
 		AF_XDP_LOG(DEBUG,
 			"Failed to get enough buffers for fq.\n");
-		return -1;
+		return 0;
 	}
 
 	rcvd = xsk_ring_cons__peek(rx, nb_pkts, &idx_rx);
@@ -270,8 +265,11 @@ af_xdp_rx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		addr = xsk_umem__extract_addr(addr);
 
 		bufs[i] = (struct rte_mbuf *)
-				xsk_umem__get_data(umem->buffer, addr);
-		bufs[i]->data_off = offset - sizeof(struct rte_mbuf);
+				xsk_umem__get_data(umem->buffer, addr +
+					umem->mb_pool->header_size);
+		bufs[i]->data_off = offset - sizeof(struct rte_mbuf) -
+			rte_pktmbuf_priv_size(umem->mb_pool) -
+			umem->mb_pool->header_size;
 
 		rte_pktmbuf_pkt_len(bufs[i]) = len;
 		rte_pktmbuf_data_len(bufs[i]) = len;
@@ -307,6 +305,10 @@ af_xdp_rx_cp(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	uint32_t free_thresh = fq->size >> 1;
 	struct rte_mbuf *mbufs[ETH_AF_XDP_RX_BATCH_SIZE];
 
+	if (xsk_prod_nb_free(fq, free_thresh) >= free_thresh)
+		(void)reserve_fill_queue(umem, ETH_AF_XDP_RX_BATCH_SIZE, NULL);
+
+
 	if (unlikely(rte_pktmbuf_alloc_bulk(rxq->mb_pool, mbufs, nb_pkts) != 0))
 		return 0;
 
@@ -320,9 +322,6 @@ af_xdp_rx_cp(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		goto out;
 	}
 
-	if (xsk_prod_nb_free(fq, free_thresh) >= free_thresh)
-		(void)reserve_fill_queue(umem, ETH_AF_XDP_RX_BATCH_SIZE, NULL);
-
 	for (i = 0; i < rcvd; i++) {
 		const struct xdp_desc *desc;
 		uint64_t addr;
@@ -384,7 +383,8 @@ pull_umem_cq(struct xsk_umem_info *umem, int size)
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
 		addr = xsk_umem__extract_addr(addr);
 		rte_pktmbuf_free((struct rte_mbuf *)
-					xsk_umem__get_data(umem->buffer, addr));
+					xsk_umem__get_data(umem->buffer,
+					addr + umem->mb_pool->header_size));
 #else
 		rte_ring_enqueue(umem->buf_ring, (void *)addr);
 #endif
@@ -442,9 +442,11 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 			}
 			desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
 			desc->len = mbuf->pkt_len;
-			addr = (uint64_t)mbuf - (uint64_t)umem->buffer;
+			addr = (uint64_t)mbuf - (uint64_t)umem->buffer -
+					umem->mb_pool->header_size;
 			offset = rte_pktmbuf_mtod(mbuf, uint64_t) -
-					(uint64_t)mbuf;
+					(uint64_t)mbuf +
+					umem->mb_pool->header_size;
 			offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
 			desc->addr = addr | offset;
 			count++;
@@ -465,9 +467,11 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 			desc = xsk_ring_prod__tx_desc(&txq->tx, idx_tx);
 			desc->len = mbuf->pkt_len;
 
-			addr = (uint64_t)local_mbuf - (uint64_t)umem->buffer;
+			addr = (uint64_t)local_mbuf - (uint64_t)umem->buffer -
+					umem->mb_pool->header_size;
 			offset = rte_pktmbuf_mtod(local_mbuf, uint64_t) -
-					(uint64_t)local_mbuf;
+					(uint64_t)local_mbuf +
+					umem->mb_pool->header_size;
 			pkt = xsk_umem__get_data(umem->buffer, addr + offset);
 			offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT;
 			desc->addr = addr | offset;
@@ -480,10 +484,7 @@ af_xdp_tx_zc(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		tx_bytes += mbuf->pkt_len;
 	}
 
-#if defined(XDP_USE_NEED_WAKEUP)
-	if (xsk_ring_prod__needs_wakeup(&txq->tx))
-#endif
-		kick_tx(txq);
+	kick_tx(txq);
 
 out:
 	xsk_ring_prod__submit(&txq->tx, count);
@@ -595,7 +596,14 @@ eth_dev_info(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	dev_info->max_tx_queues = internals->queue_cnt;
 
 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
-	dev_info->max_mtu = ETH_AF_XDP_FRAME_SIZE - ETH_AF_XDP_DATA_HEADROOM;
+#if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
+	dev_info->max_mtu = getpagesize() -
+				sizeof(struct rte_mempool_objhdr) -
+				sizeof(struct rte_mbuf) -
+				RTE_PKTMBUF_HEADROOM - XDP_PACKET_HEADROOM;
+#else
+	dev_info->max_mtu = ETH_AF_XDP_FRAME_SIZE - XDP_PACKET_HEADROOM;
+#endif
 
 	dev_info->default_rxportconf.nb_queues = 1;
 	dev_info->default_txportconf.nb_queues = 1;
@@ -678,7 +686,6 @@ static void
 xdp_umem_destroy(struct xsk_umem_info *umem)
 {
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
-	rte_mempool_free(umem->mb_pool);
 	umem->mb_pool = NULL;
 #else
 	rte_memzone_free(umem->mz);
@@ -689,7 +696,6 @@ xdp_umem_destroy(struct xsk_umem_info *umem)
 #endif
 
 	rte_free(umem);
-	umem = NULL;
 }
 
 static void
@@ -737,12 +743,17 @@ eth_link_update(struct rte_eth_dev *dev __rte_unused,
 }
 
 #if defined(XDP_UMEM_UNALIGNED_CHUNK_FLAG)
-static inline uint64_t get_base_addr(struct rte_mempool *mp)
+static inline uintptr_t get_base_addr(struct rte_mempool *mp, uint64_t *align)
 {
 	struct rte_mempool_memhdr *memhdr;
+	uintptr_t memhdr_addr, aligned_addr;
 
 	memhdr = STAILQ_FIRST(&mp->mem_list);
-	return (uint64_t)memhdr->addr & ~(getpagesize() - 1);
+	memhdr_addr = (uintptr_t)memhdr->addr;
+	aligned_addr = memhdr_addr & ~(getpagesize() - 1);
+	*align = memhdr_addr - aligned_addr;
+
+	return aligned_addr;
 }
 
 static struct
@@ -757,12 +768,15 @@ xsk_umem_info *xdp_umem_configure(struct pmd_internals *internals __rte_unused,
 		.flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG};
 	void *base_addr = NULL;
 	struct rte_mempool *mb_pool = rxq->mb_pool;
+	uint64_t umem_size, align = 0;
 
-	usr_config.frame_size = rte_pktmbuf_data_room_size(mb_pool) +
-					ETH_AF_XDP_MBUF_OVERHEAD +
-					mb_pool->private_data_size;
-	usr_config.frame_headroom = ETH_AF_XDP_DATA_HEADROOM +
-					mb_pool->private_data_size;
+	usr_config.frame_size = rte_mempool_calc_obj_size(mb_pool->elt_size,
+								mb_pool->flags,
+								NULL);
+	usr_config.frame_headroom = mb_pool->header_size +
+					sizeof(struct rte_mbuf) +
+					rte_pktmbuf_priv_size(mb_pool) +
+					RTE_PKTMBUF_HEADROOM;
 
 	umem = rte_zmalloc_socket("umem", sizeof(*umem), 0, rte_socket_id());
 	if (umem == NULL) {
@@ -771,12 +785,11 @@ xsk_umem_info *xdp_umem_configure(struct pmd_internals *internals __rte_unused,
 	}
 
 	umem->mb_pool = mb_pool;
-	base_addr = (void *)get_base_addr(mb_pool);
+	base_addr = (void *)get_base_addr(mb_pool, &align);
+	umem_size = mb_pool->populated_size * usr_config.frame_size + align;
 
-	ret = xsk_umem__create(&umem->umem, base_addr,
-			       mb_pool->populated_size * usr_config.frame_size,
-			       &umem->fq, &umem->cq,
-			       &usr_config);
+	ret = xsk_umem__create(&umem->umem, base_addr, umem_size,
+			       &umem->fq, &umem->cq, &usr_config);
 
 	if (ret) {
 		AF_XDP_LOG(ERR, "Failed to create umem");
@@ -795,7 +808,7 @@ xsk_umem_info *xdp_umem_configure(struct pmd_internals *internals,
 		.fill_size = ETH_AF_XDP_DFLT_NUM_DESCS,
 		.comp_size = ETH_AF_XDP_DFLT_NUM_DESCS,
 		.frame_size = ETH_AF_XDP_FRAME_SIZE,
-		.frame_headroom = ETH_AF_XDP_DATA_HEADROOM };
+		.frame_headroom = 0 };
 	char ring_name[RTE_RING_NAMESIZE];
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	int ret;
@@ -820,8 +833,7 @@ xsk_umem_info *xdp_umem_configure(struct pmd_internals *internals,
 
 	for (i = 0; i < ETH_AF_XDP_NUM_BUFFERS; i++)
 		rte_ring_enqueue(umem->buf_ring,
-				 (void *)(i * ETH_AF_XDP_FRAME_SIZE +
-					  ETH_AF_XDP_DATA_HEADROOM));
+				 (void *)(i * ETH_AF_XDP_FRAME_SIZE));
 
 	snprintf(mz_name, sizeof(mz_name), "af_xdp_umem_%s_%u",
 		       internals->if_name, rxq->xsk_queue_idx);
@@ -930,7 +942,7 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 	/* Now get the space available for data in the mbuf */
 	buf_size = rte_pktmbuf_data_room_size(mb_pool) -
 		RTE_PKTMBUF_HEADROOM;
-	data_size = ETH_AF_XDP_FRAME_SIZE - ETH_AF_XDP_DATA_HEADROOM;
+	data_size = ETH_AF_XDP_FRAME_SIZE;
 
 	if (data_size > buf_size) {
 		AF_XDP_LOG(ERR, "%s: %d bytes will not fit in mbuf (%d bytes)\n",
@@ -1103,7 +1115,7 @@ xdp_get_channels_info(const char *if_name, int *max_queues,
 
 	channels.cmd = ETHTOOL_GCHANNELS;
 	ifr.ifr_data = (void *)&channels;
-	strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
+	strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
 	ret = ioctl(fd, SIOCETHTOOL, &ifr);
 	if (ret) {
 		if (errno == EOPNOTSUPP) {
diff --git a/dpdk/drivers/net/atlantic/rte_pmd_atlantic.h b/dpdk/drivers/net/atlantic/rte_pmd_atlantic.h
index c0208569b6..0100fc16e5 100644
--- a/dpdk/drivers/net/atlantic/rte_pmd_atlantic.h
+++ b/dpdk/drivers/net/atlantic/rte_pmd_atlantic.h
@@ -11,7 +11,7 @@
 #ifndef _PMD_ATLANTIC_H_
 #define _PMD_ATLANTIC_H_
 
-#include <rte_ethdev_driver.h>
+#include <rte_compat.h>
 
 /**
  * @warning
diff --git a/dpdk/drivers/net/avp/avp_ethdev.c b/dpdk/drivers/net/avp/avp_ethdev.c
index cd747b6beb..8de05ec16f 100644
--- a/dpdk/drivers/net/avp/avp_ethdev.c
+++ b/dpdk/drivers/net/avp/avp_ethdev.c
@@ -269,7 +269,7 @@ avp_dev_process_request(struct avp_dev *avp, struct rte_avp_request *request)
 			break;
 		}
 
-		if ((count < 1) && (retry == 0)) {
+		if (retry == 0) {
 			PMD_DRV_LOG(ERR, "Timeout while waiting for a response for %u\n",
 				    request->req_id);
 			ret = -ETIME;
@@ -1694,7 +1694,7 @@ avp_xmit_scattered_pkts(void *tx_queue,
 			uint16_t nb_pkts)
 {
 	struct rte_avp_desc *avp_bufs[(AVP_MAX_TX_BURST *
-				       RTE_AVP_MAX_MBUF_SEGMENTS)];
+				       RTE_AVP_MAX_MBUF_SEGMENTS)] = {};
 	struct avp_queue *txq = (struct avp_queue *)tx_queue;
 	struct rte_avp_desc *tx_bufs[AVP_MAX_TX_BURST];
 	struct avp_dev *avp = txq->avp;
diff --git a/dpdk/drivers/net/bnx2x/bnx2x.c b/dpdk/drivers/net/bnx2x/bnx2x.c
index ed31335ac5..0b4030e2b9 100644
--- a/dpdk/drivers/net/bnx2x/bnx2x.c
+++ b/dpdk/drivers/net/bnx2x/bnx2x.c
@@ -1167,6 +1167,10 @@ static int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
 	if (unlikely((rx_cq_cons_sb & MAX_RCQ_ENTRIES(rxq)) ==
 		     MAX_RCQ_ENTRIES(rxq)))
 		rx_cq_cons_sb++;
+
+	PMD_RX_LOG(DEBUG, "hw CQ cons = %d, sw CQ cons = %d",
+		   rx_cq_cons_sb, rxq->rx_cq_head);
+
 	return rxq->rx_cq_head != rx_cq_cons_sb;
 }
 
@@ -1249,9 +1253,12 @@ static uint8_t bnx2x_rxeof(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp)
 	uint16_t bd_cons, bd_prod, bd_prod_fw, comp_ring_cons;
 	uint16_t hw_cq_cons, sw_cq_cons, sw_cq_prod;
 
+	rte_spinlock_lock(&(fp)->rx_mtx);
+
 	rxq = sc->rx_queues[fp->index];
 	if (!rxq) {
 		PMD_RX_LOG(ERR, "RX queue %d is NULL", fp->index);
+		rte_spinlock_unlock(&(fp)->rx_mtx);
 		return 0;
 	}
 
@@ -1321,9 +1328,14 @@ static uint8_t bnx2x_rxeof(struct bnx2x_softc *sc, struct bnx2x_fastpath *fp)
 	rxq->rx_cq_head = sw_cq_cons;
 	rxq->rx_cq_tail = sw_cq_prod;
 
+	PMD_RX_LOG(DEBUG, "BD prod = %d, sw CQ prod = %d",
+		   bd_prod_fw, sw_cq_prod);
+
 	/* Update producers */
 	bnx2x_update_rx_prod(sc, fp, bd_prod_fw, sw_cq_prod);
 
+	rte_spinlock_unlock(&(fp)->rx_mtx);
+
 	return sw_cq_cons != hw_cq_cons;
 }
 
@@ -4577,10 +4589,10 @@ static void bnx2x_handle_fp_tq(struct bnx2x_fastpath *fp)
 			bnx2x_handle_fp_tq(fp);
 			return;
 		}
+		/* We have completed slow path completion, clear the flag */
+		rte_atomic32_set(&sc->scan_fp, 0);
 	}
 
-	/* Assuming we have completed slow path completion, clear the flag */
-	rte_atomic32_set(&sc->scan_fp, 0);
 	bnx2x_ack_sb(sc, fp->igu_sb_id, USTORM_ID,
 		   le16toh(fp->fp_hc_idx), IGU_INT_ENABLE, 1);
 }
diff --git a/dpdk/drivers/net/bnx2x/bnx2x.h b/dpdk/drivers/net/bnx2x/bnx2x.h
index 3383c76759..1dbc98197d 100644
--- a/dpdk/drivers/net/bnx2x/bnx2x.h
+++ b/dpdk/drivers/net/bnx2x/bnx2x.h
@@ -360,6 +360,9 @@ struct bnx2x_fastpath {
 	/* pointer back to parent structure */
 	struct bnx2x_softc *sc;
 
+	/* Used to synchronize fastpath Rx access */
+	rte_spinlock_t rx_mtx;
+
 	/* status block */
 	struct bnx2x_dma                 sb_dma;
 	union bnx2x_host_hc_status_block status_block;
diff --git a/dpdk/drivers/net/bnx2x/bnx2x_ethdev.c b/dpdk/drivers/net/bnx2x/bnx2x_ethdev.c
index 20b045ff87..8a1a3fc7f9 100644
--- a/dpdk/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/dpdk/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -20,6 +20,7 @@ int bnx2x_logtype_driver;
  * The set of PCI devices this driver supports
  */
 #define BROADCOM_PCI_VENDOR_ID 0x14E4
+#define QLOGIC_PCI_VENDOR_ID 0x1077
 static const struct rte_pci_id pci_id_bnx2x_map[] = {
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57800) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57711) },
@@ -27,11 +28,13 @@ static const struct rte_pci_id pci_id_bnx2x_map[] = {
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57811) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_OBS) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_4_10) },
+	{ RTE_PCI_DEVICE(QLOGIC_PCI_VENDOR_ID, CHIP_NUM_57840_4_10) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_2_20) },
 #ifdef RTE_LIBRTE_BNX2X_MF_SUPPORT
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57810_MF) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57811_MF) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_MF) },
+	{ RTE_PCI_DEVICE(QLOGIC_PCI_VENDOR_ID, CHIP_NUM_57840_MF) },
 #endif
 	{ .vendor_id = 0, }
 };
@@ -41,6 +44,7 @@ static const struct rte_pci_id pci_id_bnx2xvf_map[] = {
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57810_VF) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57811_VF) },
 	{ RTE_PCI_DEVICE(BROADCOM_PCI_VENDOR_ID, CHIP_NUM_57840_VF) },
+	{ RTE_PCI_DEVICE(QLOGIC_PCI_VENDOR_ID, CHIP_NUM_57840_VF) },
 	{ .vendor_id = 0, }
 };
 
@@ -598,6 +602,11 @@ bnx2x_common_dev_init(struct rte_eth_dev *eth_dev, int is_vf)
 
 	eth_dev->dev_ops = is_vf ? &bnx2xvf_eth_dev_ops : &bnx2x_eth_dev_ops;
 
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		PMD_DRV_LOG(ERR, sc, "Skipping device init from secondary process");
+		return 0;
+	}
+
 	rte_eth_copy_pci_info(eth_dev, pci_dev);
 
 	sc->pcie_bus    = pci_dev->addr.bus;
diff --git a/dpdk/drivers/net/bnx2x/bnx2x_rxtx.c b/dpdk/drivers/net/bnx2x/bnx2x_rxtx.c
index ae97dfee36..e201b68db8 100644
--- a/dpdk/drivers/net/bnx2x/bnx2x_rxtx.c
+++ b/dpdk/drivers/net/bnx2x/bnx2x_rxtx.c
@@ -346,6 +346,8 @@ bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 	uint16_t len, pad;
 	struct rte_mbuf *rx_mb = NULL;
 
+	rte_spinlock_lock(&(fp)->rx_mtx);
+
 	hw_cq_cons = le16toh(*fp->rx_cq_cons_sb);
 	if ((hw_cq_cons & USABLE_RCQ_ENTRIES_PER_PAGE) ==
 			USABLE_RCQ_ENTRIES_PER_PAGE) {
@@ -357,8 +359,10 @@ bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 	sw_cq_cons = rxq->rx_cq_head;
 	sw_cq_prod = rxq->rx_cq_tail;
 
-	if (sw_cq_cons == hw_cq_cons)
+	if (sw_cq_cons == hw_cq_cons) {
+		rte_spinlock_unlock(&(fp)->rx_mtx);
 		return 0;
+	}
 
 	while (nb_rx < nb_pkts && sw_cq_cons != hw_cq_cons) {
 
@@ -414,7 +418,7 @@ bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		 */
 		if (cqe_fp->pars_flags.flags & PARSING_FLAGS_VLAN) {
 			rx_mb->vlan_tci = cqe_fp->vlan_tag;
-			rx_mb->ol_flags |= PKT_RX_VLAN;
+			rx_mb->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
 		}
 
 		rx_pkts[nb_rx] = rx_mb;
@@ -439,6 +443,8 @@ bnx2x_recv_pkts(void *p_rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 	bnx2x_upd_rx_prod_fast(sc, fp, bd_prod, sw_cq_prod);
 
+	rte_spinlock_unlock(&(fp)->rx_mtx);
+
 	return nb_rx;
 }
 
diff --git a/dpdk/drivers/net/bnx2x/meson.build b/dpdk/drivers/net/bnx2x/meson.build
index 678708905e..f9749d3132 100644
--- a/dpdk/drivers/net/bnx2x/meson.build
+++ b/dpdk/drivers/net/bnx2x/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2018 Intel Corporation
 
-dep = dependency('zlib', required: false)
+dep = dependency('zlib', required: false, method: 'pkg-config')
 build = dep.found()
 reason = 'missing dependency, "zlib"'
 ext_deps += dep
diff --git a/dpdk/drivers/net/bnxt/bnxt.h b/dpdk/drivers/net/bnxt/bnxt.h
index e259c8239d..0a0ecaafa8 100644
--- a/dpdk/drivers/net/bnxt/bnxt.h
+++ b/dpdk/drivers/net/bnxt/bnxt.h
@@ -117,6 +117,14 @@
 #define BNXT_NUM_ASYNC_CPR(bp) 1
 #endif
 
+/* In FreeBSD OS, nic_uio driver does not support interrupts */
+#ifdef RTE_EXEC_ENV_FREEBSD
+#ifdef BNXT_NUM_ASYNC_CPR
+#undef BNXT_NUM_ASYNC_CPR
+#endif
+#define BNXT_NUM_ASYNC_CPR(bp)	0
+#endif
+
 #define BNXT_MISC_VEC_ID               RTE_INTR_VEC_ZERO_OFFSET
 #define BNXT_RX_VEC_START              RTE_INTR_VEC_RXTX_OFFSET
 
@@ -170,13 +178,6 @@ struct bnxt_led_cfg {
 #define BNXT_LED_DFLT_ENABLES(x)                        \
 	rte_cpu_to_le_32(BNXT_LED_DFLT_ENA << (BNXT_LED_DFLT_ENA_SHIFT * (x)))
 
-enum bnxt_hw_context {
-	HW_CONTEXT_NONE     = 0,
-	HW_CONTEXT_IS_RSS   = 1,
-	HW_CONTEXT_IS_COS   = 2,
-	HW_CONTEXT_IS_LB    = 3,
-};
-
 struct bnxt_vlan_table_entry {
 	uint16_t		tpid;
 	uint16_t		vid;
@@ -231,9 +232,10 @@ struct bnxt_pf_info {
 	uint8_t			evb_mode;
 };
 
-/* Max wait time is 10 * 100ms = 1s */
-#define BNXT_LINK_WAIT_CNT	10
-#define BNXT_LINK_WAIT_INTERVAL	100
+/* Max wait time for link up is 10s and link down is 500ms */
+#define BNXT_MAX_LINK_WAIT_CNT	200
+#define BNXT_MIN_LINK_WAIT_CNT	10
+#define BNXT_LINK_WAIT_INTERVAL	50
 struct bnxt_link_info {
 	uint32_t		phy_flags;
 	uint8_t			mac_type;
@@ -342,7 +344,7 @@ struct bnxt_coal {
 #define DBR_TYPE_NQ				(0xaULL << 60)
 #define DBR_TYPE_NQ_ARM				(0xbULL << 60)
 
-#define BNXT_RSS_TBL_SIZE_THOR		512
+#define BNXT_RSS_TBL_SIZE_THOR		512U
 #define BNXT_RSS_ENTRIES_PER_CTX_THOR	64
 #define BNXT_MAX_RSS_CTXTS_THOR \
 	(BNXT_RSS_TBL_SIZE_THOR / BNXT_RSS_ENTRIES_PER_CTX_THOR)
@@ -461,6 +463,11 @@ struct bnxt_error_recovery_info {
 	uint32_t        last_reset_counter;
 };
 
+/* Frequency for the FUNC_DRV_IF_CHANGE retry in milliseconds */
+#define BNXT_IF_CHANGE_RETRY_INTERVAL	50
+/* Maximum retry count for FUNC_DRV_IF_CHANGE */
+#define BNXT_IF_CHANGE_RETRY_COUNT	40
+
 /* address space location of register */
 #define BNXT_FW_STATUS_REG_TYPE_MASK	3
 /* register is located in PCIe config space */
@@ -485,7 +492,6 @@ struct bnxt {
 	void				*bar0;
 
 	struct rte_eth_dev		*eth_dev;
-	struct rte_eth_rss_conf		rss_conf;
 	struct rte_pci_device		*pdev;
 	void				*doorbell_base;
 
@@ -507,19 +513,17 @@ struct bnxt {
 #define BNXT_FLAG_STINGRAY		BIT(14)
 #define BNXT_FLAG_FW_RESET		BIT(15)
 #define BNXT_FLAG_FATAL_ERROR		BIT(16)
-#define BNXT_FLAG_FW_CAP_IF_CHANGE		BIT(17)
-#define BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE	BIT(18)
-#define BNXT_FLAG_FW_CAP_ERROR_RECOVERY		BIT(19)
-#define BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED	BIT(20)
-#define BNXT_FLAG_FW_CAP_ERR_RECOVER_RELOAD	BIT(21)
-#define BNXT_FLAG_EXT_STATS_SUPPORTED		BIT(22)
-#define BNXT_FLAG_NEW_RM			BIT(23)
-#define BNXT_FLAG_INIT_DONE			BIT(24)
-#define BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS		BIT(25)
-#define BNXT_FLAG_ADV_FLOW_MGMT			BIT(26)
+#define BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE	BIT(17)
+#define BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED	BIT(18)
+#define BNXT_FLAG_EXT_STATS_SUPPORTED		BIT(19)
+#define BNXT_FLAG_NEW_RM			BIT(20)
+#define BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS		BIT(22)
+#define BNXT_FLAG_ADV_FLOW_MGMT			BIT(23)
+#define BNXT_FLAG_NPAR_PF                      BIT(24)
+#define BNXT_FLAG_DFLT_MAC_SET			BIT(26)
 #define BNXT_PF(bp)		(!((bp)->flags & BNXT_FLAG_VF))
 #define BNXT_VF(bp)		((bp)->flags & BNXT_FLAG_VF)
-#define BNXT_NPAR(bp)		((bp)->port_partition_type)
+#define BNXT_NPAR(bp)		((bp)->flags & BNXT_FLAG_NPAR_PF)
 #define BNXT_MH(bp)             ((bp)->flags & BNXT_FLAG_MULTI_HOST)
 #define BNXT_SINGLE_PF(bp)      (BNXT_PF(bp) && !BNXT_NPAR(bp) && !BNXT_MH(bp))
 #define BNXT_USE_CHIMP_MB	0 //For non-CFA commands, everything uses Chimp.
@@ -529,9 +533,14 @@ struct bnxt {
 #define BNXT_STINGRAY(bp)	((bp)->flags & BNXT_FLAG_STINGRAY)
 #define BNXT_HAS_NQ(bp)		BNXT_CHIP_THOR(bp)
 #define BNXT_HAS_RING_GRPS(bp)	(!BNXT_CHIP_THOR(bp))
+#define BNXT_HAS_DFLT_MAC_SET(bp)      ((bp)->flags & BNXT_FLAG_DFLT_MAC_SET)
+
+	uint32_t		fw_cap;
+#define BNXT_FW_CAP_HOT_RESET		BIT(0)
+#define BNXT_FW_CAP_IF_CHANGE		BIT(1)
+#define BNXT_FW_CAP_ERROR_RECOVERY	BIT(2)
+#define BNXT_FW_CAP_ERR_RECOVER_RELOAD	BIT(3)
 
-	uint32_t		flow_flags;
-#define BNXT_FLOW_FLAG_L2_HDR_SRC_FILTER_EN	BIT(0)
 	pthread_mutex_t         flow_lock;
 
 	uint32_t		vnic_cap_flags;
@@ -584,12 +593,15 @@ struct bnxt {
 	rte_iova_t			hwrm_short_cmd_req_dma_addr;
 	rte_spinlock_t			hwrm_lock;
 	pthread_mutex_t			def_cp_lock;
+	pthread_mutex_t			health_check_lock;
 	uint16_t			max_req_len;
 	uint16_t			max_resp_len;
 	uint16_t                        hwrm_max_ext_req_len;
 
-	 /* default command timeout value of 50ms */
-#define HWRM_CMD_TIMEOUT		50000
+	 /* default command timeout value of 500ms */
+#define DFLT_HWRM_CMD_TIMEOUT		500000
+	 /* short command timeout value of 50ms */
+#define SHORT_HWRM_CMD_TIMEOUT		50000
 	/* default HWRM request timeout value */
 	uint32_t			hwrm_cmd_timeout;
 
@@ -603,18 +615,11 @@ struct bnxt {
 	uint8_t                 max_q;
 
 	uint16_t		fw_fid;
-	uint8_t			dflt_mac_addr[RTE_ETHER_ADDR_LEN];
 	uint16_t		max_rsscos_ctx;
 	uint16_t		max_cp_rings;
 	uint16_t		max_tx_rings;
 	uint16_t		max_rx_rings;
 #define MAX_STINGRAY_RINGS		128U
-#define BNXT_MAX_RINGS(bp) \
-	(BNXT_STINGRAY(bp) ? RTE_MIN(RTE_MIN(bp->max_rx_rings, \
-					     MAX_STINGRAY_RINGS), \
-				     bp->max_stat_ctx) : \
-				RTE_MIN(bp->max_rx_rings, bp->max_stat_ctx))
-
 	uint16_t		max_nq_rings;
 	uint16_t		max_l2_ctx;
 	uint16_t		max_rx_em_flows;
@@ -628,8 +633,6 @@ struct bnxt {
 #define BNXT_OUTER_TPID_BD_SHFT	16
 	uint32_t		outer_tpid_bd;
 	struct bnxt_pf_info	pf;
-	uint8_t			port_partition_type;
-	uint8_t			dev_stopped;
 	uint8_t			vxlan_port_cnt;
 	uint8_t			geneve_port_cnt;
 	uint16_t		vxlan_port;
@@ -652,8 +655,37 @@ struct bnxt {
 	struct bnxt_error_recovery_info *recovery_info;
 };
 
+static
+inline uint16_t bnxt_max_rings(struct bnxt *bp)
+{
+	uint16_t max_tx_rings = bp->max_tx_rings;
+	uint16_t max_rx_rings = bp->max_rx_rings;
+	uint16_t max_cp_rings = bp->max_cp_rings;
+	uint16_t max_rings;
+
+	/* For the sake of symmetry:
+	 * max Tx rings == max Rx rings, one stat ctx for each.
+	 */
+	if (BNXT_STINGRAY(bp)) {
+		max_rx_rings = RTE_MIN(RTE_MIN(max_rx_rings / 2U,
+					       MAX_STINGRAY_RINGS),
+				       bp->max_stat_ctx / 2U);
+	} else {
+		max_rx_rings = RTE_MIN(max_rx_rings / 2U,
+				       bp->max_stat_ctx / 2U);
+	}
+
+	max_tx_rings = RTE_MIN(max_tx_rings, max_rx_rings);
+	if (max_cp_rings > BNXT_NUM_ASYNC_CPR(bp))
+		max_cp_rings -= BNXT_NUM_ASYNC_CPR(bp);
+	max_rings = RTE_MIN(max_cp_rings / 2U, max_tx_rings);
+
+	return max_rings;
+}
+
 int bnxt_mtu_set_op(struct rte_eth_dev *eth_dev, uint16_t new_mtu);
-int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete);
+int bnxt_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete,
+		     bool exp_link_status);
 int bnxt_rcv_msg_from_vf(struct bnxt *bp, uint16_t vf_id, void *msg);
 int is_bnxt_in_error(struct bnxt *bp);
 uint16_t bnxt_rss_ctxts(const struct bnxt *bp);
@@ -664,6 +696,13 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp);
 
 bool is_bnxt_supported(struct rte_eth_dev *dev);
 bool bnxt_stratus_device(struct bnxt *bp);
+int bnxt_link_update_op(struct rte_eth_dev *eth_dev,
+			int wait_to_complete);
+uint16_t bnxt_dummy_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts);
+uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
+			      uint16_t nb_pkts);
+
 extern const struct rte_flow_ops bnxt_flow_ops;
 #define bnxt_acquire_flow_lock(bp) \
 	pthread_mutex_lock(&(bp)->flow_lock)
@@ -671,11 +710,23 @@ extern const struct rte_flow_ops bnxt_flow_ops;
 #define bnxt_release_flow_lock(bp) \
 	pthread_mutex_unlock(&(bp)->flow_lock)
 
+#define BNXT_VALID_VNIC_OR_RET(bp, vnic_id) do { \
+	if ((vnic_id) >= (bp)->max_vnics) { \
+		rte_flow_error_set(error, \
+				EINVAL, \
+				RTE_FLOW_ERROR_TYPE_ATTR_GROUP, \
+				NULL, \
+				"Group id is invalid!"); \
+		rc = -rte_errno; \
+		goto ret; \
+	} \
+} while (0)
+
 extern int bnxt_logtype_driver;
 #define PMD_DRV_LOG_RAW(level, fmt, args...) \
 	rte_log(RTE_LOG_ ## level, bnxt_logtype_driver, "%s(): " fmt, \
 		__func__, ## args)
 
 #define PMD_DRV_LOG(level, fmt, args...) \
-	PMD_DRV_LOG_RAW(level, fmt, ## args)
+	  PMD_DRV_LOG_RAW(level, fmt, ## args)
 #endif
diff --git a/dpdk/drivers/net/bnxt/bnxt_cpr.c b/dpdk/drivers/net/bnxt/bnxt_cpr.c
index e6f30fecbf..26c7dae88f 100644
--- a/dpdk/drivers/net/bnxt/bnxt_cpr.c
+++ b/dpdk/drivers/net/bnxt/bnxt_cpr.c
@@ -21,7 +21,7 @@ void bnxt_wait_for_device_shutdown(struct bnxt *bp)
 	 * the SHUTDOWN bit in health register
 	 */
 	if (!(bp->recovery_info &&
-	      (bp->flags & BNXT_FLAG_FW_CAP_ERR_RECOVER_RELOAD)))
+	      (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD)))
 		return;
 
 	/* Driver has to wait for fw_reset_max_msecs or shutdown bit which comes
@@ -76,6 +76,18 @@ void bnxt_handle_async_event(struct bnxt *bp,
 		PMD_DRV_LOG(INFO, "Port conn async event\n");
 		break;
 	case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY:
+		/*
+		 * Avoid any rx/tx packet processing during firmware reset
+		 * operation.
+		 */
+		bnxt_stop_rxtx(bp);
+
+		/* Ignore reset notify async events when stopping the port */
+		if (!bp->eth_dev->data->dev_started) {
+			bp->flags |= BNXT_FLAG_FATAL_ERROR;
+			return;
+		}
+
 		event_data = rte_le_to_cpu_32(async_cmp->event_data1);
 		/* timestamp_lo/hi values are in units of 100ms */
 		bp->fw_reset_max_msecs = async_cmp->timestamp_hi ?
@@ -276,3 +288,9 @@ bool bnxt_is_recovery_enabled(struct bnxt *bp)
 
 	return false;
 }
+
+void bnxt_stop_rxtx(struct bnxt *bp)
+{
+	bp->eth_dev->rx_pkt_burst = &bnxt_dummy_recv_pkts;
+	bp->eth_dev->tx_pkt_burst = &bnxt_dummy_xmit_pkts;
+}
diff --git a/dpdk/drivers/net/bnxt/bnxt_cpr.h b/dpdk/drivers/net/bnxt/bnxt_cpr.h
index c2880783f6..ff9697f4c8 100644
--- a/dpdk/drivers/net/bnxt/bnxt_cpr.h
+++ b/dpdk/drivers/net/bnxt/bnxt_cpr.h
@@ -64,9 +64,9 @@ struct bnxt_db_info;
 				(cons));				\
 } while (0)
 #define B_CP_DIS_DB(cpr, raw_cons)					\
-	rte_write32((DB_CP_FLAGS |					\
-		    RING_CMP(((cpr)->cp_ring_struct), raw_cons)),	\
-		    ((cpr)->cp_db.doorbell))
+	rte_write32_relaxed((DB_CP_FLAGS |				\
+			    RING_CMP(((cpr)->cp_ring_struct), raw_cons)), \
+			    ((cpr)->cp_db.doorbell))
 
 #define B_CP_DB(cpr, raw_cons, ring_mask)				\
 	rte_write32((DB_CP_FLAGS |					\
@@ -126,4 +126,5 @@ void bnxt_wait_for_device_shutdown(struct bnxt *bp);
 bool bnxt_is_recovery_enabled(struct bnxt *bp);
 bool bnxt_is_master_func(struct bnxt *bp);
 
+void bnxt_stop_rxtx(struct bnxt *bp);
 #endif
diff --git a/dpdk/drivers/net/bnxt/bnxt_ethdev.c b/dpdk/drivers/net/bnxt/bnxt_ethdev.c
index 41848f36f8..06843d8ddb 100644
--- a/dpdk/drivers/net/bnxt/bnxt_ethdev.c
+++ b/dpdk/drivers/net/bnxt/bnxt_ethdev.c
@@ -119,6 +119,7 @@ static const struct rte_pci_id bnxt_pci_id_map[] = {
 				     DEV_RX_OFFLOAD_UDP_CKSUM | \
 				     DEV_RX_OFFLOAD_TCP_CKSUM | \
 				     DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | \
+				     DEV_RX_OFFLOAD_OUTER_UDP_CKSUM | \
 				     DEV_RX_OFFLOAD_JUMBO_FRAME | \
 				     DEV_RX_OFFLOAD_KEEP_CRC | \
 				     DEV_RX_OFFLOAD_VLAN_EXTEND | \
@@ -132,6 +133,8 @@ static int bnxt_dev_uninit(struct rte_eth_dev *eth_dev);
 static int bnxt_init_resources(struct bnxt *bp, bool reconfig_dev);
 static int bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev);
 static void bnxt_cancel_fw_health_check(struct bnxt *bp);
+static int bnxt_restore_vlan_filters(struct bnxt *bp);
+static void bnxt_dev_recover(void *arg);
 
 int is_bnxt_in_error(struct bnxt *bp)
 {
@@ -151,12 +154,15 @@ int is_bnxt_in_error(struct bnxt *bp)
 
 uint16_t bnxt_rss_ctxts(const struct bnxt *bp)
 {
+	unsigned int num_rss_rings = RTE_MIN(bp->rx_nr_rings,
+					     BNXT_RSS_TBL_SIZE_THOR);
+
 	if (!BNXT_CHIP_THOR(bp))
 		return 1;
 
-	return RTE_ALIGN_MUL_CEIL(bp->rx_nr_rings,
+	return RTE_ALIGN_MUL_CEIL(num_rss_rings,
 				  BNXT_RSS_ENTRIES_PER_CTX_THOR) /
-				    BNXT_RSS_ENTRIES_PER_CTX_THOR;
+				  BNXT_RSS_ENTRIES_PER_CTX_THOR;
 }
 
 static uint16_t  bnxt_rss_hash_tbl_size(const struct bnxt *bp)
@@ -228,14 +234,109 @@ static int bnxt_alloc_mem(struct bnxt *bp, bool reconfig)
 	return rc;
 }
 
-static int bnxt_init_chip(struct bnxt *bp)
+static int bnxt_setup_one_vnic(struct bnxt *bp, uint16_t vnic_id)
 {
+	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+	struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+	uint64_t rx_offloads = dev_conf->rxmode.offloads;
 	struct bnxt_rx_queue *rxq;
+	unsigned int j;
+	int rc;
+
+	rc = bnxt_vnic_grp_alloc(bp, vnic);
+	if (rc)
+		goto err_out;
+
+	PMD_DRV_LOG(DEBUG, "vnic[%d] = %p vnic->fw_grp_ids = %p\n",
+		    vnic_id, vnic, vnic->fw_grp_ids);
+
+	rc = bnxt_hwrm_vnic_alloc(bp, vnic);
+	if (rc)
+		goto err_out;
+
+	/* Alloc RSS context only if RSS mode is enabled */
+	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) {
+		int j, nr_ctxs = bnxt_rss_ctxts(bp);
+
+		if (bp->rx_nr_rings > BNXT_RSS_TBL_SIZE_THOR) {
+			PMD_DRV_LOG(ERR, "RxQ cnt %d > reta_size %d\n",
+				    bp->rx_nr_rings, BNXT_RSS_TBL_SIZE_THOR);
+			PMD_DRV_LOG(ERR,
+				    "Only queues 0-%d will be in RSS table\n",
+				    BNXT_RSS_TBL_SIZE_THOR - 1);
+		}
+
+		rc = 0;
+		for (j = 0; j < nr_ctxs; j++) {
+			rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, j);
+			if (rc)
+				break;
+		}
+		if (rc) {
+			PMD_DRV_LOG(ERR,
+				    "HWRM vnic %d ctx %d alloc failure rc: %x\n",
+				    vnic_id, j, rc);
+			goto err_out;
+		}
+		vnic->num_lb_ctxts = nr_ctxs;
+	}
+
+	/*
+	 * Firmware sets pf pair in default vnic cfg. If the VLAN strip
+	 * setting is not available at this time, it will not be
+	 * configured correctly in the CFA.
+	 */
+	if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
+		vnic->vlan_strip = true;
+	else
+		vnic->vlan_strip = false;
+
+	rc = bnxt_hwrm_vnic_cfg(bp, vnic);
+	if (rc)
+		goto err_out;
+
+	rc = bnxt_set_hwrm_vnic_filters(bp, vnic);
+	if (rc)
+		goto err_out;
+
+	for (j = 0; j < bp->rx_num_qs_per_vnic; j++) {
+		rxq = bp->eth_dev->data->rx_queues[j];
+
+		PMD_DRV_LOG(DEBUG,
+			    "rxq[%d]->vnic=%p vnic->fw_grp_ids=%p\n",
+			    j, rxq->vnic, rxq->vnic->fw_grp_ids);
+
+		if (BNXT_HAS_RING_GRPS(bp) && rxq->rx_deferred_start)
+			rxq->vnic->fw_grp_ids[j] = INVALID_HW_RING_ID;
+		else
+			vnic->rx_queue_cnt++;
+	}
+
+	PMD_DRV_LOG(DEBUG, "vnic->rx_queue_cnt = %d\n", vnic->rx_queue_cnt);
+
+	rc = bnxt_vnic_rss_configure(bp, vnic);
+	if (rc)
+		goto err_out;
+
+	bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
+
+	if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO)
+		bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 1);
+	else
+		bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 0);
+
+	return 0;
+err_out:
+	PMD_DRV_LOG(ERR, "HWRM vnic %d cfg failure rc: %x\n",
+		    vnic_id, rc);
+	return rc;
+}
+
+static int bnxt_init_chip(struct bnxt *bp)
+{
 	struct rte_eth_link new;
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
-	struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
-	uint64_t rx_offloads = dev_conf->rxmode.offloads;
 	uint32_t intr_vector = 0;
 	uint32_t queue_id, base = BNXT_MISC_VEC_ID;
 	uint32_t vec = BNXT_MISC_VEC_ID;
@@ -303,93 +404,11 @@ static int bnxt_init_chip(struct bnxt *bp)
 
 	/* VNIC configuration */
 	for (i = 0; i < bp->nr_vnics; i++) {
-		struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
-		struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-
-		rc = bnxt_vnic_grp_alloc(bp, vnic);
+		rc = bnxt_setup_one_vnic(bp, i);
 		if (rc)
 			goto err_out;
-
-		PMD_DRV_LOG(DEBUG, "vnic[%d] = %p vnic->fw_grp_ids = %p\n",
-			    i, vnic, vnic->fw_grp_ids);
-
-		rc = bnxt_hwrm_vnic_alloc(bp, vnic);
-		if (rc) {
-			PMD_DRV_LOG(ERR, "HWRM vnic %d alloc failure rc: %x\n",
-				i, rc);
-			goto err_out;
-		}
-
-		/* Alloc RSS context only if RSS mode is enabled */
-		if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS) {
-			int j, nr_ctxs = bnxt_rss_ctxts(bp);
-
-			rc = 0;
-			for (j = 0; j < nr_ctxs; j++) {
-				rc = bnxt_hwrm_vnic_ctx_alloc(bp, vnic, j);
-				if (rc)
-					break;
-			}
-			if (rc) {
-				PMD_DRV_LOG(ERR,
-				  "HWRM vnic %d ctx %d alloc failure rc: %x\n",
-				  i, j, rc);
-				goto err_out;
-			}
-			vnic->num_lb_ctxts = nr_ctxs;
-		}
-
-		/*
-		 * Firmware sets pf pair in default vnic cfg. If the VLAN strip
-		 * setting is not available at this time, it will not be
-		 * configured correctly in the CFA.
-		 */
-		if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-			vnic->vlan_strip = true;
-		else
-			vnic->vlan_strip = false;
-
-		rc = bnxt_hwrm_vnic_cfg(bp, vnic);
-		if (rc) {
-			PMD_DRV_LOG(ERR, "HWRM vnic %d cfg failure rc: %x\n",
-				i, rc);
-			goto err_out;
-		}
-
-		rc = bnxt_set_hwrm_vnic_filters(bp, vnic);
-		if (rc) {
-			PMD_DRV_LOG(ERR,
-				"HWRM vnic %d filter failure rc: %x\n",
-				i, rc);
-			goto err_out;
-		}
-
-		for (j = 0; j < bp->rx_num_qs_per_vnic; j++) {
-			rxq = bp->eth_dev->data->rx_queues[j];
-
-			PMD_DRV_LOG(DEBUG,
-				    "rxq[%d]->vnic=%p vnic->fw_grp_ids=%p\n",
-				    j, rxq->vnic, rxq->vnic->fw_grp_ids);
-
-			if (BNXT_HAS_RING_GRPS(bp) && rxq->rx_deferred_start)
-				rxq->vnic->fw_grp_ids[j] = INVALID_HW_RING_ID;
-		}
-
-		rc = bnxt_vnic_rss_configure(bp, vnic);
-		if (rc) {
-			PMD_DRV_LOG(ERR,
-				    "HWRM vnic set RSS failure rc: %x\n", rc);
-			goto err_out;
-		}
-
-		bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
-
-		if (bp->eth_dev->data->dev_conf.rxmode.offloads &
-		    DEV_RX_OFFLOAD_TCP_LRO)
-			bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 1);
-		else
-			bnxt_hwrm_vnic_tpa_cfg(bp, vnic, 0);
 	}
+
 	rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, &bp->vnic_info[0], 0, NULL);
 	if (rc) {
 		PMD_DRV_LOG(ERR,
@@ -439,8 +458,11 @@ static int bnxt_init_chip(struct bnxt *bp)
 
 	/* enable uio/vfio intr/eventfd mapping */
 	rc = rte_intr_enable(intr_handle);
+#ifndef RTE_EXEC_ENV_FREEBSD
+	/* In FreeBSD OS, nic_uio driver does not support interrupts */
 	if (rc)
 		goto err_free;
+#endif
 
 	rc = bnxt_get_hwrm_link_config(bp, &new);
 	if (rc) {
@@ -505,7 +527,7 @@ static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
 	if (BNXT_PF(bp))
 		dev_info->max_vfs = pdev->max_vfs;
 
-	max_rx_rings = BNXT_MAX_RINGS(bp);
+	max_rx_rings = bnxt_max_rings(bp);
 	/* For the sake of symmetry, max_rx_queues = max_tx_queues */
 	dev_info->max_rx_queues = max_rx_rings;
 	dev_info->max_tx_queues = max_rx_rings;
@@ -535,8 +557,7 @@ static int bnxt_dev_info_get_op(struct rte_eth_dev *eth_dev,
 			.wthresh = 0,
 		},
 		.rx_free_thresh = 32,
-		/* If no descriptors available, pkts are dropped by default */
-		.rx_drop_en = 1,
+		.rx_drop_en = BNXT_DEFAULT_RX_DROP_EN,
 	};
 
 	dev_info->default_txconf = (struct rte_eth_txconf) {
@@ -758,6 +779,7 @@ bnxt_receive_function(__rte_unused struct rte_eth_dev *eth_dev)
 		DEV_RX_OFFLOAD_UDP_CKSUM |
 		DEV_RX_OFFLOAD_TCP_CKSUM |
 		DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM |
+		DEV_RX_OFFLOAD_OUTER_UDP_CKSUM |
 		DEV_RX_OFFLOAD_RSS_HASH |
 		DEV_RX_OFFLOAD_VLAN_FILTER))) {
 		PMD_DRV_LOG(INFO, "Using vector mode receive for port %d\n",
@@ -827,7 +849,7 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 	struct bnxt *bp = eth_dev->data->dev_private;
 	uint64_t rx_offloads = eth_dev->data->dev_conf.rxmode.offloads;
 	int vlan_mask = 0;
-	int rc;
+	int rc, retry_cnt = BNXT_IF_CHANGE_RETRY_COUNT;
 
 	if (!eth_dev->data->nb_tx_queues || !eth_dev->data->nb_rx_queues) {
 		PMD_DRV_LOG(ERR, "Queues are not configured yet!\n");
@@ -840,14 +862,23 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 			bp->rx_cp_nr_rings, RTE_ETHDEV_QUEUE_STAT_CNTRS);
 	}
 
-	rc = bnxt_hwrm_if_change(bp, 1);
-	if (!rc) {
-		if (bp->flags & BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE) {
-			rc = bnxt_handle_if_change_status(bp);
-			if (rc)
-				return rc;
-		}
+	do {
+		rc = bnxt_hwrm_if_change(bp, true);
+		if (rc == 0 || rc != -EAGAIN)
+			break;
+
+		rte_delay_ms(BNXT_IF_CHANGE_RETRY_INTERVAL);
+	} while (retry_cnt--);
+
+	if (rc)
+		return rc;
+
+	if (bp->flags & BNXT_FLAG_IF_CHANGE_HOT_FW_RESET_DONE) {
+		rc = bnxt_handle_if_change_status(bp);
+		if (rc)
+			return rc;
 	}
+
 	bnxt_enable_int(bp);
 
 	rc = bnxt_init_chip(bp);
@@ -855,6 +886,7 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 		goto error;
 
 	eth_dev->data->scattered_rx = bnxt_scattered_rx(eth_dev);
+	eth_dev->data->dev_started = 1;
 
 	bnxt_link_update_op(eth_dev, 1);
 
@@ -869,19 +901,16 @@ static int bnxt_dev_start_op(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = bnxt_receive_function(eth_dev);
 	eth_dev->tx_pkt_burst = bnxt_transmit_function(eth_dev);
 
-	bp->flags |= BNXT_FLAG_INIT_DONE;
-	eth_dev->data->dev_started = 1;
-	bp->dev_stopped = 0;
-	pthread_mutex_lock(&bp->def_cp_lock);
 	bnxt_schedule_fw_health_check(bp);
-	pthread_mutex_unlock(&bp->def_cp_lock);
+
 	return 0;
 
 error:
-	bnxt_hwrm_if_change(bp, 0);
 	bnxt_shutdown_nic(bp);
 	bnxt_free_tx_mbufs(bp);
 	bnxt_free_rx_mbufs(bp);
+	bnxt_hwrm_if_change(bp, false);
+	eth_dev->data->dev_started = 0;
 	return rc;
 }
 
@@ -916,6 +945,7 @@ static void bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 	struct bnxt *bp = eth_dev->data->dev_private;
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct rte_eth_link link;
 
 	eth_dev->data->dev_started = 0;
 	/* Prevent crashes when queues are still in use */
@@ -929,18 +959,16 @@ static void bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 
 	bnxt_cancel_fw_health_check(bp);
 
-	bp->flags &= ~BNXT_FLAG_INIT_DONE;
-	if (bp->eth_dev->data->dev_started) {
-		/* TBD: STOP HW queues DMA */
-		eth_dev->data->dev_link.link_status = 0;
+	/* Do not bring link down during reset recovery */
+	if (!is_bnxt_in_error(bp)) {
+		bnxt_dev_set_link_down_op(eth_dev);
+		/* Wait for link to be reset */
+		if (BNXT_SINGLE_PF(bp))
+			rte_delay_ms(500);
+		/* clear the recorded link status */
+		memset(&link, 0, sizeof(link));
+		rte_eth_linkstatus_set(eth_dev, &link);
 	}
-	bnxt_dev_set_link_down_op(eth_dev);
-
-	/* Wait for link to be reset and the async notification to process.
-	 * During reset recovery, there is no need to wait
-	 */
-	if (!is_bnxt_in_error(bp))
-		rte_delay_ms(BNXT_LINK_WAIT_INTERVAL * 2);
 
 	/* Clean queue intr-vector mapping */
 	rte_intr_efd_disable(intr_handle);
@@ -955,8 +983,7 @@ static void bnxt_dev_stop_op(struct rte_eth_dev *eth_dev)
 	/* Process any remaining notifications in default completion queue */
 	bnxt_int_handler(eth_dev);
 	bnxt_shutdown_nic(bp);
-	bnxt_hwrm_if_change(bp, 0);
-	bp->dev_stopped = 1;
+	bnxt_hwrm_if_change(bp, false);
 	bp->rx_cosq_cnt = 0;
 }
 
@@ -964,7 +991,11 @@ static void bnxt_dev_close_op(struct rte_eth_dev *eth_dev)
 {
 	struct bnxt *bp = eth_dev->data->dev_private;
 
-	if (bp->dev_stopped == 0)
+	/* cancel the recovery handler before remove dev */
+	rte_eal_alarm_cancel(bnxt_dev_reset_and_resume, (void *)bp);
+	rte_eal_alarm_cancel(bnxt_dev_recover, (void *)bp);
+
+	if (eth_dev->data->dev_started)
 		bnxt_dev_stop_op(eth_dev);
 
 	if (eth_dev->data->mac_addrs != NULL) {
@@ -1074,7 +1105,7 @@ static int bnxt_mac_addr_add_op(struct rte_eth_dev *eth_dev,
 	if (rc)
 		return rc;
 
-	if (BNXT_VF(bp) & !BNXT_VF_IS_TRUSTED(bp)) {
+	if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
 		PMD_DRV_LOG(ERR, "Cannot add MAC address to a VF interface\n");
 		return -ENOTSUP;
 	}
@@ -1084,6 +1115,10 @@ static int bnxt_mac_addr_add_op(struct rte_eth_dev *eth_dev,
 		return -EINVAL;
 	}
 
+	/* Filter settings will get applied when port is started */
+	if (!eth_dev->data->dev_started)
+		return 0;
+
 	rc = bnxt_add_mac_filter(bp, vnic, mac_addr, index, pool);
 
 	return rc;
@@ -1094,7 +1129,8 @@ int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete)
 	int rc = 0;
 	struct bnxt *bp = eth_dev->data->dev_private;
 	struct rte_eth_link new;
-	unsigned int cnt = BNXT_LINK_WAIT_CNT;
+	int cnt = wait_to_complete ? BNXT_MAX_LINK_WAIT_CNT :
+			BNXT_MIN_LINK_WAIT_CNT;
 
 	rc = is_bnxt_in_error(bp);
 	if (rc)
@@ -1118,6 +1154,12 @@ int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete)
 		rte_delay_ms(BNXT_LINK_WAIT_INTERVAL);
 	} while (cnt--);
 
+	/* Only single function PF can bring phy down.
+	 * When port is stopped, report link down for VF/MH/NPAR functions.
+	 */
+	if (!BNXT_SINGLE_PF(bp) && !eth_dev->data->dev_started)
+		memset(&new, 0, sizeof(new));
+
 out:
 	/* Timed out or success */
 	if (new.link_status != eth_dev->data->dev_link.link_status ||
@@ -1145,6 +1187,10 @@ static int bnxt_promiscuous_enable_op(struct rte_eth_dev *eth_dev)
 	if (rc)
 		return rc;
 
+	/* Filter settings will get applied when port is started */
+	if (!eth_dev->data->dev_started)
+		return 0;
+
 	if (bp->vnic_info == NULL)
 		return 0;
 
@@ -1170,6 +1216,10 @@ static int bnxt_promiscuous_disable_op(struct rte_eth_dev *eth_dev)
 	if (rc)
 		return rc;
 
+	/* Filter settings will get applied when port is started */
+	if (!eth_dev->data->dev_started)
+		return 0;
+
 	if (bp->vnic_info == NULL)
 		return 0;
 
@@ -1195,6 +1245,10 @@ static int bnxt_allmulticast_enable_op(struct rte_eth_dev *eth_dev)
 	if (rc)
 		return rc;
 
+	/* Filter settings will get applied when port is started */
+	if (!eth_dev->data->dev_started)
+		return 0;
+
 	if (bp->vnic_info == NULL)
 		return 0;
 
@@ -1220,6 +1274,10 @@ static int bnxt_allmulticast_disable_op(struct rte_eth_dev *eth_dev)
 	if (rc)
 		return rc;
 
+	/* Filter settings will get applied when port is started */
+	if (!eth_dev->data->dev_started)
+		return 0;
+
 	if (bp->vnic_info == NULL)
 		return 0;
 
@@ -1319,8 +1377,8 @@ static int bnxt_reta_update_op(struct rte_eth_dev *eth_dev,
 		}
 	}
 
-	bnxt_hwrm_vnic_rss_cfg(bp, vnic);
-	return 0;
+	rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
+	return rc;
 }
 
 static int bnxt_reta_query_op(struct rte_eth_dev *eth_dev,
@@ -1399,7 +1457,9 @@ static int bnxt_rss_hash_update_op(struct rte_eth_dev *eth_dev,
 	}
 
 	bp->flags |= BNXT_FLAG_UPDATE_HASH;
-	memcpy(&bp->rss_conf, rss_conf, sizeof(*rss_conf));
+	memcpy(&eth_dev->data->dev_conf.rx_adv_conf.rss_conf,
+	       rss_conf,
+	       sizeof(*rss_conf));
 
 	/* Update the default RSS VNIC(s) */
 	vnic = &bp->vnic_info[0];
@@ -1420,8 +1480,8 @@ static int bnxt_rss_hash_update_op(struct rte_eth_dev *eth_dev,
 	memcpy(vnic->rss_hash_key, rss_conf->rss_key, rss_conf->rss_key_len);
 
 rss_config:
-	bnxt_hwrm_vnic_rss_cfg(bp, vnic);
-	return 0;
+	rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
+	return rc;
 }
 
 static int bnxt_rss_hash_conf_get_op(struct rte_eth_dev *eth_dev,
@@ -1476,7 +1536,7 @@ static int bnxt_rss_hash_conf_get_op(struct rte_eth_dev *eth_dev,
 		}
 		if (hash_types) {
 			PMD_DRV_LOG(ERR,
-				"Unknwon RSS config from firmware (%08x), RSS disabled",
+				"Unknown RSS config from firmware (%08x), RSS disabled",
 				vnic->hash_type);
 			return -ENOTSUP;
 		}
@@ -1808,6 +1868,11 @@ static int bnxt_vlan_filter_set_op(struct rte_eth_dev *eth_dev,
 	if (rc)
 		return rc;
 
+	if (!eth_dev->data->dev_started) {
+		PMD_DRV_LOG(ERR, "port must be started before setting vlan\n");
+		return -EINVAL;
+	}
+
 	/* These operations apply to ALL existing MAC/VLAN filters */
 	if (on)
 		return bnxt_add_vlan_filter(bp, vlan_id);
@@ -1841,18 +1906,12 @@ static int bnxt_del_dflt_mac_filter(struct bnxt *bp,
 }
 
 static int
-bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
+bnxt_config_vlan_hw_filter(struct bnxt *bp, uint64_t rx_offloads)
 {
-	struct bnxt *bp = dev->data->dev_private;
-	uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
 	struct bnxt_vnic_info *vnic;
 	unsigned int i;
 	int rc;
 
-	rc = is_bnxt_in_error(bp);
-	if (rc)
-		return rc;
-
 	vnic = BNXT_GET_DEFAULT_VNIC(bp);
 	if (!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) {
 		/* Remove any VLAN filters programmed */
@@ -1876,18 +1935,102 @@ bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
 	PMD_DRV_LOG(DEBUG, "VLAN Filtering: %d\n",
 		    !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER));
 
+	return 0;
+}
+
+static int bnxt_free_one_vnic(struct bnxt *bp, uint16_t vnic_id)
+{
+	struct bnxt_vnic_info *vnic = &bp->vnic_info[vnic_id];
+	unsigned int i;
+	int rc;
+
+	/* Destroy vnic filters and vnic */
+	if (bp->eth_dev->data->dev_conf.rxmode.offloads &
+	    DEV_RX_OFFLOAD_VLAN_FILTER) {
+		for (i = 0; i < RTE_ETHER_MAX_VLAN_ID; i++)
+			bnxt_del_vlan_filter(bp, i);
+	}
+	bnxt_del_dflt_mac_filter(bp, vnic);
+
+	rc = bnxt_hwrm_vnic_free(bp, vnic);
+	if (rc)
+		return rc;
+
+	rte_free(vnic->fw_grp_ids);
+	vnic->fw_grp_ids = NULL;
+
+	vnic->rx_queue_cnt = 0;
+
+	return 0;
+}
+
+static int
+bnxt_config_vlan_hw_stripping(struct bnxt *bp, uint64_t rx_offloads)
+{
+	struct bnxt_vnic_info *vnic = BNXT_GET_DEFAULT_VNIC(bp);
+	int rc;
+
+	/* Destroy, recreate and reconfigure the default vnic */
+	rc = bnxt_free_one_vnic(bp, 0);
+	if (rc)
+		return rc;
+
+	/* default vnic 0 */
+	rc = bnxt_setup_one_vnic(bp, 0);
+	if (rc)
+		return rc;
+
+	if (bp->eth_dev->data->dev_conf.rxmode.offloads &
+	    DEV_RX_OFFLOAD_VLAN_FILTER) {
+		rc = bnxt_add_vlan_filter(bp, 0);
+		if (rc)
+			return rc;
+		rc = bnxt_restore_vlan_filters(bp);
+		if (rc)
+			return rc;
+	} else {
+		rc = bnxt_add_mac_filter(bp, vnic, NULL, 0, 0);
+		if (rc)
+			return rc;
+	}
+
+	rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, vnic, 0, NULL);
+	if (rc)
+		return rc;
+
+	PMD_DRV_LOG(DEBUG, "VLAN Strip Offload: %d\n",
+		    !!(rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP));
+
+	return rc;
+}
+
+static int
+bnxt_vlan_offload_set_op(struct rte_eth_dev *dev, int mask)
+{
+	uint64_t rx_offloads = dev->data->dev_conf.rxmode.offloads;
+	struct bnxt *bp = dev->data->dev_private;
+	int rc;
+
+	rc = is_bnxt_in_error(bp);
+	if (rc)
+		return rc;
+
+	/* Filter settings will get applied when port is started */
+	if (!dev->data->dev_started)
+		return 0;
+
+	if (mask & ETH_VLAN_FILTER_MASK) {
+		/* Enable or disable VLAN filtering */
+		rc = bnxt_config_vlan_hw_filter(bp, rx_offloads);
+		if (rc)
+			return rc;
+	}
+
 	if (mask & ETH_VLAN_STRIP_MASK) {
 		/* Enable or disable VLAN stripping */
-		for (i = 0; i < bp->nr_vnics; i++) {
-			struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
-			if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-				vnic->vlan_strip = true;
-			else
-				vnic->vlan_strip = false;
-			bnxt_hwrm_vnic_cfg(bp, vnic);
-		}
-		PMD_DRV_LOG(DEBUG, "VLAN Strip Offload: %d\n",
-			!!(rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP));
+		rc = bnxt_config_vlan_hw_stripping(bp, rx_offloads);
+		if (rc)
+			return rc;
 	}
 
 	if (mask & ETH_VLAN_EXTEND_MASK) {
@@ -1965,7 +2108,6 @@ bnxt_set_default_mac_addr_op(struct rte_eth_dev *dev,
 	struct bnxt *bp = dev->data->dev_private;
 	/* Default Filter is tied to VNIC 0 */
 	struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
-	struct bnxt_filter_info *filter;
 	int rc;
 
 	rc = is_bnxt_in_error(bp);
@@ -1978,32 +2120,27 @@ bnxt_set_default_mac_addr_op(struct rte_eth_dev *dev,
 	if (rte_is_zero_ether_addr(addr))
 		return -EINVAL;
 
-	STAILQ_FOREACH(filter, &vnic->filter, next) {
-		/* Default Filter is at Index 0 */
-		if (filter->mac_index != 0)
-			continue;
+	/* Filter settings will get applied when port is started */
+	if (!dev->data->dev_started)
+		return 0;
 
-		memcpy(filter->l2_addr, addr, RTE_ETHER_ADDR_LEN);
-		memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
-		filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX |
-			HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_OUTERMOST;
-		filter->enables |=
-			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
-			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK;
+	/* Check if the requested MAC is already added */
+	if (memcmp(addr, bp->mac_addr, RTE_ETHER_ADDR_LEN) == 0)
+		return 0;
 
-		rc = bnxt_hwrm_set_l2_filter(bp, vnic->fw_vnic_id, filter);
-		if (rc) {
-			memcpy(filter->l2_addr, bp->mac_addr,
-			       RTE_ETHER_ADDR_LEN);
-			return rc;
-		}
+	/* Destroy filter and re-create it */
+	bnxt_del_dflt_mac_filter(bp, vnic);
 
-		memcpy(bp->mac_addr, addr, RTE_ETHER_ADDR_LEN);
-		PMD_DRV_LOG(DEBUG, "Set MAC addr\n");
-		return 0;
+	memcpy(bp->mac_addr, addr, RTE_ETHER_ADDR_LEN);
+	if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
+		/* This filter will allow only untagged packets */
+		rc = bnxt_add_vlan_filter(bp, 0);
+	} else {
+		rc = bnxt_add_mac_filter(bp, vnic, addr, 0, 0);
 	}
 
-	return 0;
+	PMD_DRV_LOG(DEBUG, "Set MAC addr\n");
+	return rc;
 }
 
 static int
@@ -2053,10 +2190,11 @@ bnxt_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
 	uint8_t fw_major = (bp->fw_ver >> 24) & 0xff;
 	uint8_t fw_minor = (bp->fw_ver >> 16) & 0xff;
 	uint8_t fw_updt = (bp->fw_ver >> 8) & 0xff;
+	uint8_t fw_rsvd = bp->fw_ver & 0xff;
 	int ret;
 
-	ret = snprintf(fw_version, fw_size, "%d.%d.%d",
-			fw_major, fw_minor, fw_updt);
+	ret = snprintf(fw_version, fw_size, "%d.%d.%d.%d",
+			fw_major, fw_minor, fw_updt, fw_rsvd);
 
 	ret += 1; /* add the size of '\0' */
 	if (fw_size < (uint32_t)ret)
@@ -2082,8 +2220,9 @@ bnxt_rxq_info_get_op(struct rte_eth_dev *dev, uint16_t queue_id,
 	qinfo->nb_desc = rxq->nb_rx_desc;
 
 	qinfo->conf.rx_free_thresh = rxq->rx_free_thresh;
-	qinfo->conf.rx_drop_en = 0;
+	qinfo->conf.rx_drop_en = rxq->drop_en;
 	qinfo->conf.rx_deferred_start = rxq->rx_deferred_start;
+	qinfo->conf.offloads = dev->data->dev_conf.rxmode.offloads;
 }
 
 static void
@@ -2107,6 +2246,7 @@ bnxt_txq_info_get_op(struct rte_eth_dev *dev, uint16_t queue_id,
 	qinfo->conf.tx_free_thresh = txq->tx_free_thresh;
 	qinfo->conf.tx_rs_thresh = 0;
 	qinfo->conf.tx_deferred_start = txq->tx_deferred_start;
+	qinfo->conf.offloads = dev->data->dev_conf.txmode.offloads;
 }
 
 int bnxt_mtu_set_op(struct rte_eth_dev *eth_dev, uint16_t new_mtu)
@@ -3500,9 +3640,9 @@ bnxt_get_eeprom_length_op(struct rte_eth_dev *dev)
 	if (rc)
 		return rc;
 
-	PMD_DRV_LOG(INFO, "%04x:%02x:%02x:%02x\n",
-		bp->pdev->addr.domain, bp->pdev->addr.bus,
-		bp->pdev->addr.devid, bp->pdev->addr.function);
+	PMD_DRV_LOG(INFO, PCI_PRI_FMT "\n",
+		    bp->pdev->addr.domain, bp->pdev->addr.bus,
+		    bp->pdev->addr.devid, bp->pdev->addr.function);
 
 	rc = bnxt_hwrm_nvm_get_dir_info(bp, &dir_entries, &entry_length);
 	if (rc != 0)
@@ -3524,10 +3664,10 @@ bnxt_get_eeprom_op(struct rte_eth_dev *dev,
 	if (rc)
 		return rc;
 
-	PMD_DRV_LOG(INFO, "%04x:%02x:%02x:%02x in_eeprom->offset = %d "
-		"len = %d\n", bp->pdev->addr.domain,
-		bp->pdev->addr.bus, bp->pdev->addr.devid,
-		bp->pdev->addr.function, in_eeprom->offset, in_eeprom->length);
+	PMD_DRV_LOG(INFO, PCI_PRI_FMT " in_eeprom->offset = %d len = %d\n",
+		    bp->pdev->addr.domain, bp->pdev->addr.bus,
+		    bp->pdev->addr.devid, bp->pdev->addr.function,
+		    in_eeprom->offset, in_eeprom->length);
 
 	if (in_eeprom->offset == 0) /* special offset value to get directory */
 		return bnxt_get_nvram_directory(bp, in_eeprom->length,
@@ -3600,10 +3740,10 @@ bnxt_set_eeprom_op(struct rte_eth_dev *dev,
 	if (rc)
 		return rc;
 
-	PMD_DRV_LOG(INFO, "%04x:%02x:%02x:%02x in_eeprom->offset = %d "
-		"len = %d\n", bp->pdev->addr.domain,
-		bp->pdev->addr.bus, bp->pdev->addr.devid,
-		bp->pdev->addr.function, in_eeprom->offset, in_eeprom->length);
+	PMD_DRV_LOG(INFO, PCI_PRI_FMT " in_eeprom->offset = %d len = %d\n",
+		    bp->pdev->addr.domain, bp->pdev->addr.bus,
+		    bp->pdev->addr.devid, bp->pdev->addr.function,
+		    in_eeprom->offset, in_eeprom->length);
 
 	if (!BNXT_PF(bp)) {
 		PMD_DRV_LOG(ERR, "NVM write not supported from a VF\n");
@@ -3688,8 +3828,6 @@ static const struct eth_dev_ops bnxt_dev_ops = {
 	.txq_info_get = bnxt_txq_info_get_op,
 	.dev_led_on = bnxt_dev_led_on_op,
 	.dev_led_off = bnxt_dev_led_off_op,
-	.xstats_get_by_id = bnxt_dev_xstats_get_by_id_op,
-	.xstats_get_names_by_id = bnxt_dev_xstats_get_names_by_id_op,
 	.rx_queue_count = bnxt_rx_queue_count_op,
 	.rx_descriptor_status = bnxt_rx_descriptor_status_op,
 	.tx_descriptor_status = bnxt_tx_descriptor_status_op,
@@ -3788,24 +3926,100 @@ static void bnxt_write_fw_reset_reg(struct bnxt *bp, uint32_t index)
 
 static void bnxt_dev_cleanup(struct bnxt *bp)
 {
-	bnxt_set_hwrm_link_config(bp, false);
+	bp->eth_dev->data->dev_link.link_status = 0;
 	bp->link_info.link_up = 0;
-	if (bp->dev_stopped == 0)
+	if (bp->eth_dev->data->dev_started)
 		bnxt_dev_stop_op(bp->eth_dev);
 
 	bnxt_uninit_resources(bp, true);
 }
 
+static int bnxt_restore_vlan_filters(struct bnxt *bp)
+{
+	struct rte_eth_dev *dev = bp->eth_dev;
+	struct rte_vlan_filter_conf *vfc;
+	int vidx, vbit, rc;
+	uint16_t vlan_id;
+
+	for (vlan_id = 1; vlan_id <= RTE_ETHER_MAX_VLAN_ID; vlan_id++) {
+		vfc = &dev->data->vlan_filter_conf;
+		vidx = vlan_id / 64;
+		vbit = vlan_id % 64;
+
+		/* Each bit corresponds to a VLAN id */
+		if (vfc->ids[vidx] & (UINT64_C(1) << vbit)) {
+			rc = bnxt_add_vlan_filter(bp, vlan_id);
+			if (rc)
+				return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int bnxt_restore_mac_filters(struct bnxt *bp)
+{
+	struct rte_eth_dev *dev = bp->eth_dev;
+	struct rte_eth_dev_info dev_info;
+	struct rte_ether_addr *addr;
+	uint64_t pool_mask;
+	uint32_t pool = 0;
+	uint16_t i;
+	int rc;
+
+	if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp))
+		return 0;
+
+	rc = bnxt_dev_info_get_op(dev, &dev_info);
+	if (rc)
+		return rc;
+
+	/* replay MAC address configuration */
+	for (i = 1; i < dev_info.max_mac_addrs; i++) {
+		addr = &dev->data->mac_addrs[i];
+
+		/* skip zero address */
+		if (rte_is_zero_ether_addr(addr))
+			continue;
+
+		pool = 0;
+		pool_mask = dev->data->mac_pool_sel[i];
+
+		do {
+			if (pool_mask & 1ULL) {
+				rc = bnxt_mac_addr_add_op(dev, addr, i, pool);
+				if (rc)
+					return rc;
+			}
+			pool_mask >>= 1;
+			pool++;
+		} while (pool_mask);
+	}
+
+	return 0;
+}
+
 static int bnxt_restore_filters(struct bnxt *bp)
 {
 	struct rte_eth_dev *dev = bp->eth_dev;
 	int ret = 0;
 
-	if (dev->data->all_multicast)
+	if (dev->data->all_multicast) {
 		ret = bnxt_allmulticast_enable_op(dev);
-	if (dev->data->promiscuous)
+		if (ret)
+			return ret;
+	}
+	if (dev->data->promiscuous) {
 		ret = bnxt_promiscuous_enable_op(dev);
+		if (ret)
+			return ret;
+	}
 
+	ret = bnxt_restore_mac_filters(bp);
+	if (ret)
+		return ret;
+
+	ret = bnxt_restore_vlan_filters(bp);
 	/* TODO restore other filters as well */
 	return ret;
 }
@@ -3820,7 +4034,7 @@ static void bnxt_dev_recover(void *arg)
 	bp->flags &= ~BNXT_FLAG_FATAL_ERROR;
 
 	do {
-		rc = bnxt_hwrm_ver_get(bp);
+		rc = bnxt_hwrm_ver_get(bp, SHORT_HWRM_CMD_TIMEOUT);
 		if (rc == 0)
 			break;
 		rte_delay_ms(BNXT_FW_READY_WAIT_INTERVAL);
@@ -3844,15 +4058,17 @@ static void bnxt_dev_recover(void *arg)
 	rc = bnxt_dev_start_op(bp->eth_dev);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Failed to start port after reset\n");
-		goto err;
+		goto err_start;
 	}
 
 	rc = bnxt_restore_filters(bp);
 	if (rc)
-		goto err;
+		goto err_start;
 
 	PMD_DRV_LOG(INFO, "Recovered from FW reset\n");
 	return;
+err_start:
+	bnxt_dev_stop_op(bp->eth_dev);
 err:
 	bp->flags |= BNXT_FLAG_FATAL_ERROR;
 	bnxt_uninit_resources(bp, false);
@@ -4006,17 +4222,22 @@ void bnxt_schedule_fw_health_check(struct bnxt *bp)
 {
 	uint32_t polling_freq;
 
+	pthread_mutex_lock(&bp->health_check_lock);
+
 	if (!bnxt_is_recovery_enabled(bp))
-		return;
+		goto done;
 
 	if (bp->flags & BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED)
-		return;
+		goto done;
 
 	polling_freq = bp->recovery_info->driver_polling_freq;
 
 	rte_eal_alarm_set(US_PER_MS * polling_freq,
 			  bnxt_check_fw_health, (void *)bp);
 	bp->flags |= BNXT_FLAG_FW_HEALTH_CHECK_SCHEDULED;
+
+done:
+	pthread_mutex_unlock(&bp->health_check_lock);
 }
 
 static void bnxt_cancel_fw_health_check(struct bnxt *bp)
@@ -4138,18 +4359,6 @@ static int bnxt_alloc_ctx_mem_blk(__rte_unused struct bnxt *bp,
 
 		memset(mz->addr, 0, mz->len);
 		mz_phys_addr = mz->iova;
-		if ((unsigned long)mz->addr == mz_phys_addr) {
-			PMD_DRV_LOG(DEBUG,
-				    "physical address same as virtual\n");
-			PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
-			mz_phys_addr = rte_mem_virt2iova(mz->addr);
-			if (mz_phys_addr == RTE_BAD_IOVA) {
-				PMD_DRV_LOG(ERR,
-					"unable to map addr to phys memory\n");
-				return -ENOMEM;
-			}
-		}
-		rte_mem_lock_page(((char *)mz->addr));
 
 		rmem->pg_tbl = mz->addr;
 		rmem->pg_tbl_map = mz_phys_addr;
@@ -4173,22 +4382,8 @@ static int bnxt_alloc_ctx_mem_blk(__rte_unused struct bnxt *bp,
 
 	memset(mz->addr, 0, mz->len);
 	mz_phys_addr = mz->iova;
-	if ((unsigned long)mz->addr == mz_phys_addr) {
-		PMD_DRV_LOG(DEBUG,
-			    "Memzone physical address same as virtual.\n");
-		PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
-		for (sz = 0; sz < mem_size; sz += BNXT_PAGE_SIZE)
-			rte_mem_lock_page(((char *)mz->addr) + sz);
-		mz_phys_addr = rte_mem_virt2iova(mz->addr);
-		if (mz_phys_addr == RTE_BAD_IOVA) {
-			PMD_DRV_LOG(ERR,
-				    "unable to map addr to phys memory\n");
-			return -ENOMEM;
-		}
-	}
 
 	for (sz = 0, i = 0; sz < mem_size; sz += BNXT_PAGE_SIZE, i++) {
-		rte_mem_lock_page(((char *)mz->addr) + sz);
 		rmem->pg_arr[i] = ((char *)mz->addr) + sz;
 		rmem->dma_arr[i] = mz_phys_addr + sz;
 
@@ -4365,18 +4560,6 @@ static int bnxt_alloc_stats_mem(struct bnxt *bp)
 	}
 	memset(mz->addr, 0, mz->len);
 	mz_phys_addr = mz->iova;
-	if ((unsigned long)mz->addr == mz_phys_addr) {
-		PMD_DRV_LOG(DEBUG,
-			    "Memzone physical address same as virtual.\n");
-		PMD_DRV_LOG(DEBUG,
-			    "Using rte_mem_virt2iova()\n");
-		mz_phys_addr = rte_mem_virt2iova(mz->addr);
-		if (mz_phys_addr == RTE_BAD_IOVA) {
-			PMD_DRV_LOG(ERR,
-				    "Can't map address to physical memory\n");
-			return -ENOMEM;
-		}
-	}
 
 	bp->rx_mem_zone = (const void *)mz;
 	bp->hw_rx_port_stats = mz->addr;
@@ -4403,17 +4586,6 @@ static int bnxt_alloc_stats_mem(struct bnxt *bp)
 	}
 	memset(mz->addr, 0, mz->len);
 	mz_phys_addr = mz->iova;
-	if ((unsigned long)mz->addr == mz_phys_addr) {
-		PMD_DRV_LOG(DEBUG,
-			    "Memzone physical address same as virtual\n");
-		PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
-		mz_phys_addr = rte_mem_virt2iova(mz->addr);
-		if (mz_phys_addr == RTE_BAD_IOVA) {
-			PMD_DRV_LOG(ERR,
-				    "Can't map address to physical memory\n");
-			return -ENOMEM;
-		}
-	}
 
 	bp->tx_mem_zone = (const void *)mz;
 	bp->hw_tx_port_stats = mz->addr;
@@ -4461,7 +4633,7 @@ static int bnxt_setup_mac_addr(struct rte_eth_dev *eth_dev)
 		return -ENOMEM;
 	}
 
-	if (bnxt_check_zero_bytes(bp->dflt_mac_addr, RTE_ETHER_ADDR_LEN)) {
+	if (!BNXT_HAS_DFLT_MAC_SET(bp)) {
 		if (BNXT_PF(bp))
 			return -EINVAL;
 
@@ -4474,14 +4646,11 @@ static int bnxt_setup_mac_addr(struct rte_eth_dev *eth_dev)
 			    bp->mac_addr[3], bp->mac_addr[4], bp->mac_addr[5]);
 
 		rc = bnxt_hwrm_set_mac(bp);
-		if (!rc)
-			memcpy(&bp->eth_dev->data->mac_addrs[0], bp->mac_addr,
-			       RTE_ETHER_ADDR_LEN);
-		return rc;
+		if (rc)
+			return rc;
 	}
 
 	/* Copy the permanent MAC from the FUNC_QCAPS response */
-	memcpy(bp->mac_addr, bp->dflt_mac_addr, RTE_ETHER_ADDR_LEN);
 	memcpy(&eth_dev->data->mac_addrs[0], bp->mac_addr, RTE_ETHER_ADDR_LEN);
 
 	return rc;
@@ -4492,7 +4661,7 @@ static int bnxt_restore_dflt_mac(struct bnxt *bp)
 	int rc = 0;
 
 	/* MAC is already configured in FW */
-	if (!bnxt_check_zero_bytes(bp->dflt_mac_addr, RTE_ETHER_ADDR_LEN))
+	if (BNXT_HAS_DFLT_MAC_SET(bp))
 		return 0;
 
 	/* Restore the old MAC configured */
@@ -4546,7 +4715,9 @@ static int bnxt_init_fw(struct bnxt *bp)
 	uint16_t mtu;
 	int rc = 0;
 
-	rc = bnxt_hwrm_ver_get(bp);
+	bp->fw_cap = 0;
+
+	rc = bnxt_hwrm_ver_get(bp, DFLT_HWRM_CMD_TIMEOUT);
 	if (rc)
 		return rc;
 
@@ -4574,14 +4745,10 @@ static int bnxt_init_fw(struct bnxt *bp)
 	if (rc)
 		return rc;
 
-	rc = bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(bp);
-	if (rc)
-		return rc;
-
 	/* Get the adapter error recovery support info */
 	rc = bnxt_hwrm_error_recovery_qcfg(bp);
 	if (rc)
-		bp->flags &= ~BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+		bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
 
 	bnxt_hwrm_port_led_qcaps(bp);
 
@@ -4600,8 +4767,14 @@ bnxt_init_locks(struct bnxt *bp)
 	}
 
 	err = pthread_mutex_init(&bp->def_cp_lock, NULL);
-	if (err)
+	if (err) {
 		PMD_DRV_LOG(ERR, "Unable to initialize def_cp_lock\n");
+		return err;
+	}
+
+	err = pthread_mutex_init(&bp->health_check_lock, NULL);
+	if (err)
+		PMD_DRV_LOG(ERR, "Unable to initialize health_check_lock\n");
 	return err;
 }
 
@@ -4693,8 +4866,6 @@ bnxt_dev_init(struct rte_eth_dev *eth_dev)
 
 	bp = eth_dev->data->dev_private;
 
-	bp->dev_stopped = 1;
-
 	if (bnxt_vf_pciid(pci_dev->id.device_id))
 		bp->flags |= BNXT_FLAG_VF;
 
@@ -4745,6 +4916,7 @@ bnxt_uninit_locks(struct bnxt *bp)
 {
 	pthread_mutex_destroy(&bp->flow_lock);
 	pthread_mutex_destroy(&bp->def_cp_lock);
+	pthread_mutex_destroy(&bp->health_check_lock);
 }
 
 static int
@@ -4796,10 +4968,9 @@ bnxt_dev_uninit(struct rte_eth_dev *eth_dev)
 		bp->rx_mem_zone = NULL;
 	}
 
-	if (bp->dev_stopped == 0)
+	if (eth_dev->data->dev_started)
 		bnxt_dev_close_op(eth_dev);
-	if (bp->pf.vf_info)
-		rte_free(bp->pf.vf_info);
+	bnxt_hwrm_free_vf_info(bp);
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
diff --git a/dpdk/drivers/net/bnxt/bnxt_filter.c b/dpdk/drivers/net/bnxt/bnxt_filter.c
index da1a6c24a9..f4b18d5b84 100644
--- a/dpdk/drivers/net/bnxt/bnxt_filter.c
+++ b/dpdk/drivers/net/bnxt/bnxt_filter.c
@@ -26,22 +26,20 @@ struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp)
 {
 	struct bnxt_filter_info *filter;
 
-	/* Find the 1st unused filter from the free_filter_list pool*/
-	filter = STAILQ_FIRST(&bp->free_filter_list);
+	filter = bnxt_get_unused_filter(bp);
 	if (!filter) {
 		PMD_DRV_LOG(ERR, "No more free filter resources\n");
 		return NULL;
 	}
-	STAILQ_REMOVE_HEAD(&bp->free_filter_list, next);
 
 	filter->mac_index = INVALID_MAC_INDEX;
 	/* Default to L2 MAC Addr filter */
 	filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX;
 	filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR |
 			HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK;
-	memcpy(filter->l2_addr, bp->eth_dev->data->mac_addrs->addr_bytes,
-	       RTE_ETHER_ADDR_LEN);
+	memcpy(filter->l2_addr, bp->mac_addr, RTE_ETHER_ADDR_LEN);
 	memset(filter->l2_addr_mask, 0xff, RTE_ETHER_ADDR_LEN);
+
 	return filter;
 }
 
@@ -83,6 +81,15 @@ void bnxt_free_all_filters(struct bnxt *bp)
 	struct bnxt_filter_info *filter, *temp_filter;
 	unsigned int i;
 
+	for (i = 0; i < bp->pf.max_vfs; i++) {
+		STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) {
+			bnxt_hwrm_clear_l2_filter(bp, filter);
+		}
+	}
+
+	if (bp->vnic_info == NULL)
+		return;
+
 	for (i = 0; i < bp->nr_vnics; i++) {
 		vnic = &bp->vnic_info[i];
 		filter = STAILQ_FIRST(&vnic->filter);
@@ -96,12 +103,6 @@ void bnxt_free_all_filters(struct bnxt *bp)
 		}
 		STAILQ_INIT(&vnic->filter);
 	}
-
-	for (i = 0; i < bp->pf.max_vfs; i++) {
-		STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) {
-			bnxt_hwrm_clear_l2_filter(bp, filter);
-		}
-	}
 }
 
 void bnxt_free_filter_mem(struct bnxt *bp)
diff --git a/dpdk/drivers/net/bnxt/bnxt_filter.h b/dpdk/drivers/net/bnxt/bnxt_filter.h
index 9db3e74877..fc40f112ba 100644
--- a/dpdk/drivers/net/bnxt/bnxt_filter.h
+++ b/dpdk/drivers/net/bnxt/bnxt_filter.h
@@ -77,6 +77,10 @@ struct bnxt_filter_info {
 	uint16_t                ip_addr_type;
 	uint16_t                ethertype;
 	uint32_t		priority;
+	/* Backptr to vnic. As of now, used only by an L2 filter
+	 * to remember which vnic it was created on
+	 */
+	struct			bnxt_vnic_info *vnic;
 };
 
 struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp);
diff --git a/dpdk/drivers/net/bnxt/bnxt_flow.c b/dpdk/drivers/net/bnxt/bnxt_flow.c
index 76e9584da7..f069e5f56a 100644
--- a/dpdk/drivers/net/bnxt/bnxt_flow.c
+++ b/dpdk/drivers/net/bnxt/bnxt_flow.c
@@ -746,10 +746,9 @@ bnxt_find_matching_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf)
 {
 	struct bnxt_filter_info *mf, *f0;
 	struct bnxt_vnic_info *vnic0;
-	struct rte_flow *flow;
 	int i;
 
-	vnic0 = &bp->vnic_info[0];
+	vnic0 = BNXT_GET_DEFAULT_VNIC(bp);
 	f0 = STAILQ_FIRST(&vnic0->filter);
 
 	/* This flow has same DST MAC as the port/l2 filter. */
@@ -762,8 +761,7 @@ bnxt_find_matching_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf)
 		if (vnic->fw_vnic_id == INVALID_VNIC_ID)
 			continue;
 
-		STAILQ_FOREACH(flow, &vnic->flow_list, next) {
-			mf = flow->filter;
+		STAILQ_FOREACH(mf, &vnic->filter, next) {
 
 			if (mf->matching_l2_fltr_ptr)
 				continue;
@@ -798,6 +796,8 @@ bnxt_create_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf,
 	if (filter1 == NULL)
 		return NULL;
 
+	memcpy(filter1, nf, sizeof(*filter1));
+
 	filter1->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_XDP_DISABLE;
 	filter1->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX;
 	if (nf->valid_flags & BNXT_FLOW_L2_SRC_VALID_FLAG ||
@@ -867,7 +867,6 @@ bnxt_create_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf,
 		bnxt_free_filter(bp, filter1);
 		return NULL;
 	}
-	filter1->l2_ref_cnt++;
 	return filter1;
 }
 
@@ -880,11 +879,14 @@ bnxt_get_l2_filter(struct bnxt *bp, struct bnxt_filter_info *nf,
 	l2_filter = bnxt_find_matching_l2_filter(bp, nf);
 	if (l2_filter) {
 		l2_filter->l2_ref_cnt++;
-		nf->matching_l2_fltr_ptr = l2_filter;
 	} else {
 		l2_filter = bnxt_create_l2_filter(bp, nf, vnic);
-		nf->matching_l2_fltr_ptr = NULL;
+		if (l2_filter) {
+			STAILQ_INSERT_TAIL(&vnic->filter, l2_filter, next);
+			l2_filter->vnic = vnic;
+		}
 	}
+	nf->matching_l2_fltr_ptr = l2_filter;
 
 	return l2_filter;
 }
@@ -1054,16 +1056,9 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
 			vnic_id = act_q->index;
 		}
 
+		BNXT_VALID_VNIC_OR_RET(bp, vnic_id);
+
 		vnic = &bp->vnic_info[vnic_id];
-		if (vnic == NULL) {
-			rte_flow_error_set(error,
-					   EINVAL,
-					   RTE_FLOW_ERROR_TYPE_ACTION,
-					   act,
-					   "No matching VNIC found.");
-			rc = -rte_errno;
-			goto ret;
-		}
 		if (vnic->rx_queue_cnt) {
 			if (vnic->start_grp_id != act_q->index) {
 				PMD_DRV_LOG(ERR,
@@ -1126,7 +1121,16 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
 		PMD_DRV_LOG(DEBUG,
 			    "Setting vnic ff_idx %d\n", vnic->ff_pool_idx);
 		filter->dst_id = vnic->fw_vnic_id;
-		filter1 = bnxt_get_l2_filter(bp, filter, vnic);
+
+		/* For ntuple filter, create the L2 filter with default VNIC.
+		 * The user specified redirect queue will be set while creating
+		 * the ntuple filter in hardware.
+		 */
+		vnic0 = BNXT_GET_DEFAULT_VNIC(bp);
+		if (use_ntuple)
+			filter1 = bnxt_get_l2_filter(bp, filter, vnic0);
+		else
+			filter1 = bnxt_get_l2_filter(bp, filter, vnic);
 		if (filter1 == NULL) {
 			rte_flow_error_set(error,
 					   ENOSPC,
@@ -1252,28 +1256,10 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
 		rss = (const struct rte_flow_action_rss *)act->conf;
 
 		vnic_id = attr->group;
-		if (!vnic_id) {
-			PMD_DRV_LOG(ERR, "Group id cannot be 0\n");
-			rte_flow_error_set(error,
-					   EINVAL,
-					   RTE_FLOW_ERROR_TYPE_ATTR,
-					   NULL,
-					   "Group id cannot be 0");
-			rc = -rte_errno;
-			goto ret;
-		}
+
+		BNXT_VALID_VNIC_OR_RET(bp, vnic_id);
 
 		vnic = &bp->vnic_info[vnic_id];
-		if (vnic == NULL) {
-			rte_flow_error_set(error,
-					   EINVAL,
-					   RTE_FLOW_ERROR_TYPE_ACTION,
-					   act,
-					   "No matching VNIC for RSS group.");
-			rc = -rte_errno;
-			goto ret;
-		}
-		PMD_DRV_LOG(DEBUG, "VNIC found\n");
 
 		/* Check if requested RSS config matches RSS config of VNIC
 		 * only if it is not a fresh VNIC configuration.
@@ -1420,11 +1406,6 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
 		goto ret;
 	}
 
-	if (filter1 && !filter->matching_l2_fltr_ptr) {
-		bnxt_free_filter(bp, filter1);
-		filter1->fw_l2_filter_id = -1;
-	}
-
 done:
 	act = bnxt_flow_non_void_action(++act);
 	if (act->type != RTE_FLOW_ACTION_TYPE_END) {
@@ -1448,7 +1429,7 @@ bnxt_validate_and_parse_flow(struct rte_eth_dev *dev,
 		if (rxq && !vnic->rx_queue_cnt)
 			rxq->vnic = &bp->vnic_info[0];
 	}
-	return rc;
+	return -rte_errno;
 }
 
 static
@@ -1537,10 +1518,13 @@ bnxt_update_filter(struct bnxt *bp, struct bnxt_filter_info *old_filter,
 	 * filter which points to the new destination queue and so we clear
 	 * the previous L2 filter. For ntuple filters, we are going to reuse
 	 * the old L2 filter and create new NTUPLE filter with this new
-	 * destination queue subsequently during bnxt_flow_create.
+	 * destination queue subsequently during bnxt_flow_create. So we
+	 * decrement the ref cnt of the L2 filter that would've been bumped
+	 * up previously in bnxt_validate_and_parse_flow as the old n-tuple
+	 * filter that was referencing it will be deleted now.
 	 */
+	bnxt_hwrm_clear_l2_filter(bp, old_filter);
 	if (new_filter->filter_type == HWRM_CFA_L2_FILTER) {
-		bnxt_hwrm_clear_l2_filter(bp, old_filter);
 		bnxt_hwrm_set_l2_filter(bp, new_filter->dst_id, new_filter);
 	} else {
 		if (new_filter->filter_type == HWRM_CFA_EM_FILTER)
@@ -1663,7 +1647,9 @@ bnxt_flow_create(struct rte_eth_dev *dev,
 
 	filter = bnxt_get_unused_filter(bp);
 	if (filter == NULL) {
-		PMD_DRV_LOG(ERR, "Not enough resources for a new flow.\n");
+		rte_flow_error_set(error, ENOSPC,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Not enough resources for a new flow");
 		goto free_flow;
 	}
 
@@ -1729,12 +1715,24 @@ bnxt_flow_create(struct rte_eth_dev *dev,
 		filter->enables |=
 			HWRM_CFA_EM_FLOW_ALLOC_INPUT_ENABLES_L2_FILTER_ID;
 		ret = bnxt_hwrm_set_em_filter(bp, filter->dst_id, filter);
+		if (ret != 0) {
+			rte_flow_error_set(error, -ret,
+					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+					   "Failed to create EM filter");
+			goto free_filter;
+		}
 	}
 
 	if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER) {
 		filter->enables |=
 			HWRM_CFA_NTUPLE_FILTER_ALLOC_INPUT_ENABLES_L2_FILTER_ID;
 		ret = bnxt_hwrm_set_ntuple_filter(bp, filter->dst_id, filter);
+		if (ret != 0) {
+			rte_flow_error_set(error, -ret,
+					   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+					   "Failed to create ntuple filter");
+			goto free_filter;
+		}
 	}
 
 	vnic = find_matching_vnic(bp, filter);
@@ -1748,9 +1746,9 @@ bnxt_flow_create(struct rte_eth_dev *dev,
 		}
 
 		STAILQ_INSERT_TAIL(&vnic->filter, filter, next);
-		PMD_DRV_LOG(DEBUG, "Successfully created flow.\n");
 		STAILQ_INSERT_TAIL(&vnic->flow_list, flow, next);
 		bnxt_release_flow_lock(bp);
+		PMD_DRV_LOG(DEBUG, "Successfully created flow.\n");
 		return flow;
 	}
 
@@ -1765,7 +1763,7 @@ bnxt_flow_create(struct rte_eth_dev *dev,
 		rte_flow_error_set(error, 0,
 				   RTE_FLOW_ERROR_TYPE_NONE, NULL,
 				   "Flow with pattern exists, updating destination queue");
-	else
+	else if (!rte_errno)
 		rte_flow_error_set(error, -ret,
 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 				   "Failed to create flow.");
@@ -1817,57 +1815,31 @@ static int bnxt_handle_tunnel_redirect_destroy(struct bnxt *bp,
 }
 
 static int
-bnxt_flow_destroy(struct rte_eth_dev *dev,
-		  struct rte_flow *flow,
-		  struct rte_flow_error *error)
+_bnxt_flow_destroy(struct bnxt *bp,
+		   struct rte_flow *flow,
+		    struct rte_flow_error *error)
 {
-	struct bnxt *bp = dev->data->dev_private;
 	struct bnxt_filter_info *filter;
 	struct bnxt_vnic_info *vnic;
 	int ret = 0;
 
-	bnxt_acquire_flow_lock(bp);
-	if (!flow) {
-		rte_flow_error_set(error, EINVAL,
-				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
-				   "Invalid flow: failed to destroy flow.");
-		bnxt_release_flow_lock(bp);
-		return -EINVAL;
-	}
-
 	filter = flow->filter;
 	vnic = flow->vnic;
 
-	if (!filter) {
-		rte_flow_error_set(error, EINVAL,
-				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
-				   "Invalid flow: failed to destroy flow.");
-		bnxt_release_flow_lock(bp);
-		return -EINVAL;
-	}
-
 	if (filter->filter_type == HWRM_CFA_TUNNEL_REDIRECT_FILTER &&
 	    filter->enables == filter->tunnel_type) {
-		ret = bnxt_handle_tunnel_redirect_destroy(bp,
-							  filter,
-							  error);
-		if (!ret) {
+		ret = bnxt_handle_tunnel_redirect_destroy(bp, filter, error);
+		if (!ret)
 			goto done;
-		} else {
-			bnxt_release_flow_lock(bp);
+		else
 			return ret;
-		}
 	}
 
 	ret = bnxt_match_filter(bp, filter);
 	if (ret == 0)
 		PMD_DRV_LOG(ERR, "Could not find matching flow\n");
 
-	if (filter->filter_type == HWRM_CFA_EM_FILTER)
-		ret = bnxt_hwrm_clear_em_filter(bp, filter);
-	if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
-		ret = bnxt_hwrm_clear_ntuple_filter(bp, filter);
-	ret = bnxt_hwrm_clear_l2_filter(bp, filter);
+	ret = bnxt_clear_one_vnic_filter(bp, filter);
 
 done:
 	if (!ret) {
@@ -1903,7 +1875,36 @@ bnxt_flow_destroy(struct rte_eth_dev *dev,
 				   "Failed to destroy flow.");
 	}
 
+	return ret;
+}
+
+static int
+bnxt_flow_destroy(struct rte_eth_dev *dev,
+		  struct rte_flow *flow,
+		  struct rte_flow_error *error)
+{
+	struct bnxt *bp = dev->data->dev_private;
+	int ret = 0;
+
+	bnxt_acquire_flow_lock(bp);
+	if (!flow) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Invalid flow: failed to destroy flow.");
+		bnxt_release_flow_lock(bp);
+		return -EINVAL;
+	}
+
+	if (!flow->filter) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Invalid flow: failed to destroy flow.");
+		bnxt_release_flow_lock(bp);
+		return -EINVAL;
+	}
+	ret = _bnxt_flow_destroy(bp, flow, error);
 	bnxt_release_flow_lock(bp);
+
 	return ret;
 }
 
@@ -1911,7 +1912,6 @@ static int
 bnxt_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
 {
 	struct bnxt *bp = dev->data->dev_private;
-	struct bnxt_filter_info *filter = NULL;
 	struct bnxt_vnic_info *vnic;
 	struct rte_flow *flow;
 	unsigned int i;
@@ -1925,66 +1925,17 @@ bnxt_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
 
 		while (!STAILQ_EMPTY(&vnic->flow_list)) {
 			flow = STAILQ_FIRST(&vnic->flow_list);
-			filter = flow->filter;
-
-			if (filter->filter_type ==
-			    HWRM_CFA_TUNNEL_REDIRECT_FILTER &&
-			    filter->enables == filter->tunnel_type) {
-				ret =
-				bnxt_handle_tunnel_redirect_destroy(bp,
-								    filter,
-								    error);
-				if (!ret) {
-					goto done;
-				} else {
-					bnxt_release_flow_lock(bp);
-					return ret;
-				}
-			}
-
-			if (filter->filter_type == HWRM_CFA_EM_FILTER)
-				ret = bnxt_hwrm_clear_em_filter(bp, filter);
-			if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
-				ret = bnxt_hwrm_clear_ntuple_filter(bp, filter);
-			else if (i)
-				ret = bnxt_hwrm_clear_l2_filter(bp, filter);
 
-			if (ret) {
-				rte_flow_error_set
-					(error,
-					 -ret,
-					 RTE_FLOW_ERROR_TYPE_HANDLE,
-					 NULL,
-					 "Failed to flush flow in HW.");
-				bnxt_release_flow_lock(bp);
-				return -rte_errno;
-			}
-done:
-			STAILQ_REMOVE(&vnic->flow_list, flow,
-				      rte_flow, next);
-
-			STAILQ_REMOVE(&vnic->filter,
-				      filter,
-				      bnxt_filter_info,
-				      next);
-			bnxt_free_filter(bp, filter);
-
-			rte_free(flow);
+			if (!flow->filter)
+				continue;
 
-			/* If this was the last flow associated with this vnic,
-			 * switch the queue back to RSS pool.
-			 */
-			if (STAILQ_EMPTY(&vnic->flow_list)) {
-				rte_free(vnic->fw_grp_ids);
-				if (vnic->rx_queue_cnt > 1)
-					bnxt_hwrm_vnic_ctx_free(bp, vnic);
-				bnxt_hwrm_vnic_free(bp, vnic);
-				vnic->rx_queue_cnt = 0;
-			}
+			ret = _bnxt_flow_destroy(bp, flow, error);
+			if (ret)
+				break;
 		}
 	}
-
 	bnxt_release_flow_lock(bp);
+
 	return ret;
 }
 
diff --git a/dpdk/drivers/net/bnxt/bnxt_hwrm.c b/dpdk/drivers/net/bnxt/bnxt_hwrm.c
index 41730089b1..8025d5ad78 100644
--- a/dpdk/drivers/net/bnxt/bnxt_hwrm.c
+++ b/dpdk/drivers/net/bnxt/bnxt_hwrm.c
@@ -52,7 +52,7 @@ static int page_getenum(size_t size)
 	if (size <= 1 << 30)
 		return 30;
 	PMD_DRV_LOG(ERR, "Page size %zu out of range\n", size);
-	return sizeof(void *) * 8 - 1;
+	return sizeof(int) * 8 - 1;
 }
 
 static int page_roundup(size_t size)
@@ -100,11 +100,7 @@ static int bnxt_hwrm_send_message(struct bnxt *bp, void *msg,
 	if (bp->flags & BNXT_FLAG_FATAL_ERROR)
 		return 0;
 
-	/* For VER_GET command, set timeout as 50ms */
-	if (rte_cpu_to_le_16(req->req_type) == HWRM_VER_GET)
-		timeout = HWRM_CMD_TIMEOUT;
-	else
-		timeout = bp->hwrm_cmd_timeout;
+	timeout = bp->hwrm_cmd_timeout;
 
 	if (bp->flags & BNXT_FLAG_SHORT_CMD ||
 	    msg_len > bp->max_req_len) {
@@ -168,8 +164,9 @@ static int bnxt_hwrm_send_message(struct bnxt *bp, void *msg,
 		    rte_cpu_to_le_16(req->req_type) == HWRM_VER_GET)
 			return -ETIMEDOUT;
 
-		PMD_DRV_LOG(ERR, "Error(timeout) sending msg 0x%04x\n",
-			    req->req_type);
+		PMD_DRV_LOG(ERR,
+			    "Error(timeout) sending msg 0x%04x, seq_id %d\n",
+			    req->req_type, req->seq_id);
 		return -ETIMEDOUT;
 	}
 	return 0;
@@ -188,6 +185,10 @@ static int bnxt_hwrm_send_message(struct bnxt *bp, void *msg,
  */
 #define HWRM_PREP(req, type, kong) do { \
 	rte_spinlock_lock(&bp->hwrm_lock); \
+	if (bp->hwrm_cmd_resp_addr == NULL) { \
+		rte_spinlock_unlock(&bp->hwrm_lock); \
+		return -EACCES; \
+	} \
 	memset(bp->hwrm_cmd_resp_addr, 0, bp->max_resp_len); \
 	req.req_type = rte_cpu_to_le_16(HWRM_##type); \
 	req.cmpl_ring = rte_cpu_to_le_16(-1); \
@@ -221,6 +222,8 @@ static int bnxt_hwrm_send_message(struct bnxt *bp, void *msg,
 			rc = -EINVAL; \
 		else if (rc == HWRM_ERR_CODE_CMD_NOT_SUPPORTED) \
 			rc = -ENOTSUP; \
+		else if (rc == HWRM_ERR_CODE_HOT_RESET_PROGRESS) \
+			rc = -EAGAIN; \
 		else if (rc > 0) \
 			rc = -EIO; \
 		return rc; \
@@ -249,6 +252,8 @@ static int bnxt_hwrm_send_message(struct bnxt *bp, void *msg,
 			rc = -EINVAL; \
 		else if (rc == HWRM_ERR_CODE_CMD_NOT_SUPPORTED) \
 			rc = -ENOTSUP; \
+		else if (rc == HWRM_ERR_CODE_HOT_RESET_PROGRESS) \
+			rc = -EAGAIN; \
 		else if (rc > 0) \
 			rc = -EIO; \
 		return rc; \
@@ -309,8 +314,8 @@ int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp,
 	if (vlan_table) {
 		if (!(mask & HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN))
 			mask |= HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY;
-		req.vlan_tag_tbl_addr = rte_cpu_to_le_64(
-			 rte_mem_virt2iova(vlan_table));
+		req.vlan_tag_tbl_addr =
+			rte_cpu_to_le_64(rte_malloc_virt2iova(vlan_table));
 		req.num_vlan_tags = rte_cpu_to_le_32((uint32_t)vlan_count);
 	}
 	req.mask = rte_cpu_to_le_32(mask);
@@ -351,7 +356,7 @@ int bnxt_hwrm_cfa_vlan_antispoof_cfg(struct bnxt *bp, uint16_t fid,
 	req.fid = rte_cpu_to_le_16(fid);
 
 	req.vlan_tag_mask_tbl_addr =
-		rte_cpu_to_le_64(rte_mem_virt2iova(vlan_table));
+		rte_cpu_to_le_64(rte_malloc_virt2iova(vlan_table));
 	req.num_vlan_entries = rte_cpu_to_le_32((uint32_t)vlan_count);
 
 	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
@@ -363,10 +368,11 @@ int bnxt_hwrm_cfa_vlan_antispoof_cfg(struct bnxt *bp, uint16_t fid,
 }
 
 int bnxt_hwrm_clear_l2_filter(struct bnxt *bp,
-			   struct bnxt_filter_info *filter)
+			     struct bnxt_filter_info *filter)
 {
 	int rc = 0;
 	struct bnxt_filter_info *l2_filter = filter;
+	struct bnxt_vnic_info *vnic = NULL;
 	struct hwrm_cfa_l2_filter_free_input req = {.req_type = 0 };
 	struct hwrm_cfa_l2_filter_free_output *resp = bp->hwrm_cmd_resp_addr;
 
@@ -379,6 +385,9 @@ int bnxt_hwrm_clear_l2_filter(struct bnxt *bp,
 	PMD_DRV_LOG(DEBUG, "filter: %p l2_filter: %p ref_cnt: %d\n",
 		    filter, l2_filter, l2_filter->l2_ref_cnt);
 
+	if (l2_filter->l2_ref_cnt == 0)
+		return 0;
+
 	if (l2_filter->l2_ref_cnt > 0)
 		l2_filter->l2_ref_cnt--;
 
@@ -395,6 +404,14 @@ int bnxt_hwrm_clear_l2_filter(struct bnxt *bp,
 	HWRM_UNLOCK();
 
 	filter->fw_l2_filter_id = UINT64_MAX;
+	if (l2_filter->l2_ref_cnt == 0) {
+		vnic = l2_filter->vnic;
+		if (vnic) {
+			STAILQ_REMOVE(&vnic->filter, l2_filter,
+				      bnxt_filter_info, next);
+			bnxt_free_filter(bp, l2_filter);
+		}
+	}
 
 	return 0;
 }
@@ -430,6 +447,9 @@ int bnxt_hwrm_set_l2_filter(struct bnxt *bp,
 
 	HWRM_PREP(req, CFA_L2_FILTER_ALLOC, BNXT_USE_CHIMP_MB);
 
+	/* PMD does not support XDP and RoCE */
+	filter->flags |= HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_XDP_DISABLE |
+			HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_TRAFFIC_L2;
 	req.flags = rte_cpu_to_le_32(filter->flags);
 
 	enables = filter->enables |
@@ -475,6 +495,8 @@ int bnxt_hwrm_set_l2_filter(struct bnxt *bp,
 	filter->fw_l2_filter_id = rte_le_to_cpu_64(resp->l2_filter_id);
 	HWRM_UNLOCK();
 
+	filter->l2_ref_cnt++;
+
 	return rc;
 }
 
@@ -567,6 +589,20 @@ static int bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
 	return 0;
 }
 
+void bnxt_hwrm_free_vf_info(struct bnxt *bp)
+{
+	uint16_t i;
+
+	for (i = 0; i < bp->pf.max_vfs; i++) {
+		rte_free(bp->pf.vf_info[i].vlan_table);
+		bp->pf.vf_info[i].vlan_table = NULL;
+		rte_free(bp->pf.vf_info[i].vlan_as_table);
+		bp->pf.vf_info[i].vlan_as_table = NULL;
+	}
+	rte_free(bp->pf.vf_info);
+	bp->pf.vf_info = NULL;
+}
+
 static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
 {
 	int rc = 0;
@@ -593,9 +629,14 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
 		new_max_vfs = bp->pdev->max_vfs;
 		if (new_max_vfs != bp->pf.max_vfs) {
 			if (bp->pf.vf_info)
-				rte_free(bp->pf.vf_info);
-			bp->pf.vf_info = rte_malloc("bnxt_vf_info",
+				bnxt_hwrm_free_vf_info(bp);
+			bp->pf.vf_info = rte_zmalloc("bnxt_vf_info",
 			    sizeof(bp->pf.vf_info[0]) * new_max_vfs, 0);
+			if (bp->pf.vf_info == NULL) {
+				PMD_DRV_LOG(ERR, "Alloc vf info fail\n");
+				HWRM_UNLOCK();
+				return -ENOMEM;
+			}
 			bp->pf.max_vfs = new_max_vfs;
 			for (i = 0; i < new_max_vfs; i++) {
 				bp->pf.vf_info[i].fid = bp->pf.first_vf_id + i;
@@ -627,7 +668,12 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
 	}
 
 	bp->fw_fid = rte_le_to_cpu_32(resp->fid);
-	memcpy(bp->dflt_mac_addr, &resp->mac_address, RTE_ETHER_ADDR_LEN);
+	if (!bnxt_check_zero_bytes(resp->mac_address, RTE_ETHER_ADDR_LEN)) {
+		bp->flags |= BNXT_FLAG_DFLT_MAC_SET;
+		memcpy(bp->mac_addr, &resp->mac_address, RTE_ETHER_ADDR_LEN);
+	} else {
+		bp->flags &= ~BNXT_FLAG_DFLT_MAC_SET;
+	}
 	bp->max_rsscos_ctx = rte_le_to_cpu_16(resp->max_rsscos_ctx);
 	bp->max_cp_rings = rte_le_to_cpu_16(resp->max_cmpl_rings);
 	bp->max_tx_rings = rte_le_to_cpu_16(resp->max_tx_rings);
@@ -661,16 +707,15 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
 		bp->flags |= BNXT_FLAG_EXT_STATS_SUPPORTED;
 
 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERROR_RECOVERY_CAPABLE) {
-		bp->flags |= BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
+		bp->fw_cap |= BNXT_FW_CAP_ERROR_RECOVERY;
 		PMD_DRV_LOG(DEBUG, "Adapter Error recovery SUPPORTED\n");
-	} else {
-		bp->flags &= ~BNXT_FLAG_FW_CAP_ERROR_RECOVERY;
 	}
 
 	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_ERR_RECOVER_RELOAD)
-		bp->flags |= BNXT_FLAG_FW_CAP_ERR_RECOVER_RELOAD;
-	else
-		bp->flags &= ~BNXT_FLAG_FW_CAP_ERR_RECOVER_RELOAD;
+		bp->fw_cap |= BNXT_FW_CAP_ERR_RECOVER_RELOAD;
+
+	if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_HOT_RESET_CAPABLE)
+		bp->fw_cap |= BNXT_FW_CAP_HOT_RESET;
 
 	HWRM_UNLOCK();
 
@@ -756,8 +801,9 @@ int bnxt_hwrm_func_driver_register(struct bnxt *bp)
 	if (bp->flags & BNXT_FLAG_REGISTERED)
 		return 0;
 
-	flags = HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_HOT_RESET_SUPPORT;
-	if (bp->flags & BNXT_FLAG_FW_CAP_ERROR_RECOVERY)
+	if (bp->fw_cap & BNXT_FW_CAP_HOT_RESET)
+		flags = HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_HOT_RESET_SUPPORT;
+	if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
 		flags |= HWRM_FUNC_DRV_RGTR_INPUT_FLAGS_ERROR_RECOVERY_SUPPORT;
 
 	/* PFs and trusted VFs should indicate the support of the
@@ -797,7 +843,7 @@ int bnxt_hwrm_func_driver_register(struct bnxt *bp)
 				 ASYNC_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE |
 				 ASYNC_CMPL_EVENT_ID_LINK_SPEED_CHANGE |
 				 ASYNC_CMPL_EVENT_ID_RESET_NOTIFY);
-	if (bp->flags & BNXT_FLAG_FW_CAP_ERROR_RECOVERY)
+	if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
 		req.async_event_fwd[0] |=
 			rte_cpu_to_le_32(ASYNC_CMPL_EVENT_ID_ERROR_RECOVERY);
 	req.async_event_fwd[1] |=
@@ -810,7 +856,7 @@ int bnxt_hwrm_func_driver_register(struct bnxt *bp)
 
 	flags = rte_le_to_cpu_32(resp->flags);
 	if (flags & HWRM_FUNC_DRV_RGTR_OUTPUT_FLAGS_IF_CHANGE_SUPPORTED)
-		bp->flags |= BNXT_FLAG_FW_CAP_IF_CHANGE;
+		bp->fw_cap |= BNXT_FW_CAP_IF_CHANGE;
 
 	HWRM_UNLOCK();
 
@@ -934,7 +980,7 @@ int bnxt_hwrm_func_resc_qcaps(struct bnxt *bp)
 	return rc;
 }
 
-int bnxt_hwrm_ver_get(struct bnxt *bp)
+int bnxt_hwrm_ver_get(struct bnxt *bp, uint32_t timeout)
 {
 	int rc = 0;
 	struct hwrm_ver_get_input req = {.req_type = 0 };
@@ -945,6 +991,7 @@ int bnxt_hwrm_ver_get(struct bnxt *bp)
 	uint32_t dev_caps_cfg;
 
 	bp->max_req_len = HWRM_MAX_REQ_LEN;
+	bp->hwrm_cmd_timeout = timeout;
 	HWRM_PREP(req, VER_GET, BNXT_USE_CHIMP_MB);
 
 	req.hwrm_intf_maj = HWRM_VERSION_MAJOR;
@@ -958,10 +1005,11 @@ int bnxt_hwrm_ver_get(struct bnxt *bp)
 	else
 		HWRM_CHECK_RESULT();
 
-	PMD_DRV_LOG(INFO, "%d.%d.%d:%d.%d.%d\n",
+	PMD_DRV_LOG(INFO, "%d.%d.%d:%d.%d.%d.%d\n",
 		resp->hwrm_intf_maj_8b, resp->hwrm_intf_min_8b,
 		resp->hwrm_intf_upd_8b, resp->hwrm_fw_maj_8b,
-		resp->hwrm_fw_min_8b, resp->hwrm_fw_bld_8b);
+		resp->hwrm_fw_min_8b, resp->hwrm_fw_bld_8b,
+		resp->hwrm_fw_rsvd_8b);
 	bp->fw_ver = (resp->hwrm_fw_maj_8b << 24) |
 		     (resp->hwrm_fw_min_8b << 16) |
 		     (resp->hwrm_fw_bld_8b << 8) |
@@ -979,7 +1027,7 @@ int bnxt_hwrm_ver_get(struct bnxt *bp)
 	/* convert timeout to usec */
 	bp->hwrm_cmd_timeout *= 1000;
 	if (!bp->hwrm_cmd_timeout)
-		bp->hwrm_cmd_timeout = HWRM_CMD_TIMEOUT;
+		bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT;
 
 	if (resp->hwrm_intf_maj_8b != HWRM_VERSION_MAJOR) {
 		PMD_DRV_LOG(ERR, "Unsupported firmware API version\n");
@@ -1011,9 +1059,8 @@ int bnxt_hwrm_ver_get(struct bnxt *bp)
 			rc = -ENOMEM;
 			goto error;
 		}
-		rte_mem_lock_page(bp->hwrm_cmd_resp_addr);
 		bp->hwrm_cmd_resp_dma_addr =
-			rte_mem_virt2iova(bp->hwrm_cmd_resp_addr);
+			rte_malloc_virt2iova(bp->hwrm_cmd_resp_addr);
 		if (bp->hwrm_cmd_resp_dma_addr == RTE_BAD_IOVA) {
 			PMD_DRV_LOG(ERR,
 			"Unable to map response buffer to physical memory.\n");
@@ -1048,9 +1095,8 @@ int bnxt_hwrm_ver_get(struct bnxt *bp)
 			rc = -ENOMEM;
 			goto error;
 		}
-		rte_mem_lock_page(bp->hwrm_short_cmd_req_addr);
 		bp->hwrm_short_cmd_req_dma_addr =
-			rte_mem_virt2iova(bp->hwrm_short_cmd_req_addr);
+			rte_malloc_virt2iova(bp->hwrm_short_cmd_req_addr);
 		if (bp->hwrm_short_cmd_req_dma_addr == RTE_BAD_IOVA) {
 			rte_free(bp->hwrm_short_cmd_req_addr);
 			PMD_DRV_LOG(ERR,
@@ -1210,6 +1256,35 @@ static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp,
 	return rc;
 }
 
+static bool bnxt_find_lossy_profile(struct bnxt *bp)
+{
+	int i = 0;
+
+	for (i = BNXT_COS_QUEUE_COUNT - 1; i >= 0; i--) {
+		if (bp->tx_cos_queue[i].profile ==
+		    HWRM_QUEUE_SERVICE_PROFILE_LOSSY) {
+			bp->tx_cosq_id[0] = bp->tx_cos_queue[i].id;
+			return true;
+		}
+	}
+	return false;
+}
+
+static void bnxt_find_first_valid_profile(struct bnxt *bp)
+{
+	int i = 0;
+
+	for (i = BNXT_COS_QUEUE_COUNT - 1; i >= 0; i--) {
+		if (bp->tx_cos_queue[i].profile !=
+		    HWRM_QUEUE_SERVICE_PROFILE_UNKNOWN &&
+		    bp->tx_cos_queue[i].id !=
+		    HWRM_QUEUE_SERVICE_PROFILE_UNKNOWN) {
+			bp->tx_cosq_id[0] = bp->tx_cos_queue[i].id;
+			break;
+		}
+	}
+}
+
 int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
 {
 	int rc = 0;
@@ -1269,14 +1344,13 @@ int bnxt_hwrm_queue_qportcfg(struct bnxt *bp)
 						bp->tx_cos_queue[i].id;
 			}
 		} else {
-			for (i = BNXT_COS_QUEUE_COUNT - 1; i >= 0; i--) {
-				if (bp->tx_cos_queue[i].profile ==
-					HWRM_QUEUE_SERVICE_PROFILE_LOSSY) {
-					bp->tx_cosq_id[0] =
-						bp->tx_cos_queue[i].id;
-					break;
-				}
-			}
+			/* When CoS classification is disabled, for normal NIC
+			 * operations, ideally we should look to use LOSSY.
+			 * If not found, fallback to the first valid profile
+			 */
+			if (!bnxt_find_lossy_profile(bp))
+				bnxt_find_first_valid_profile(bp);
+
 		}
 	}
 
@@ -2072,8 +2146,8 @@ int bnxt_hwrm_vnic_tpa_cfg(struct bnxt *bp,
 				HWRM_VNIC_TPA_CFG_INPUT_FLAGS_GRO |
 				HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_ECN |
 			HWRM_VNIC_TPA_CFG_INPUT_FLAGS_AGG_WITH_SAME_GRE_SEQ);
-		req.max_agg_segs = rte_cpu_to_le_16(BNXT_TPA_MAX_AGGS(bp));
-		req.max_aggs = rte_cpu_to_le_16(BNXT_TPA_MAX_SEGS(bp));
+		req.max_aggs = rte_cpu_to_le_16(BNXT_TPA_MAX_AGGS(bp));
+		req.max_agg_segs = rte_cpu_to_le_16(BNXT_TPA_MAX_SEGS(bp));
 		req.min_agg_len = rte_cpu_to_le_32(512);
 	}
 	req.vnic_id = rte_cpu_to_le_16(vnic->fw_vnic_id);
@@ -2325,13 +2399,6 @@ void bnxt_free_hwrm_rx_ring(struct bnxt *bp, int queue_index)
 		if (BNXT_HAS_RING_GRPS(bp))
 			bp->grp_info[queue_index].rx_fw_ring_id =
 							INVALID_HW_RING_ID;
-		memset(rxr->rx_desc_ring, 0,
-		       rxr->rx_ring_struct->ring_size *
-		       sizeof(*rxr->rx_desc_ring));
-		memset(rxr->rx_buf_ring, 0,
-		       rxr->rx_ring_struct->ring_size *
-		       sizeof(*rxr->rx_buf_ring));
-		rxr->rx_prod = 0;
 	}
 	ring = rxr->ag_ring_struct;
 	if (ring->fw_ring_id != INVALID_HW_RING_ID) {
@@ -2339,11 +2406,6 @@ void bnxt_free_hwrm_rx_ring(struct bnxt *bp, int queue_index)
 				    BNXT_CHIP_THOR(bp) ?
 				    HWRM_RING_FREE_INPUT_RING_TYPE_RX_AGG :
 				    HWRM_RING_FREE_INPUT_RING_TYPE_RX);
-		ring->fw_ring_id = INVALID_HW_RING_ID;
-		memset(rxr->ag_buf_ring, 0,
-		       rxr->ag_ring_struct->ring_size *
-		       sizeof(*rxr->ag_buf_ring));
-		rxr->ag_prod = 0;
 		if (BNXT_HAS_RING_GRPS(bp))
 			bp->grp_info[queue_index].ag_fw_ring_id =
 							INVALID_HW_RING_ID;
@@ -2430,11 +2492,10 @@ int bnxt_alloc_hwrm_resources(struct bnxt *bp)
 		pdev->addr.bus, pdev->addr.devid, pdev->addr.function);
 	bp->max_resp_len = HWRM_MAX_RESP_LEN;
 	bp->hwrm_cmd_resp_addr = rte_malloc(type, bp->max_resp_len, 0);
-	rte_mem_lock_page(bp->hwrm_cmd_resp_addr);
 	if (bp->hwrm_cmd_resp_addr == NULL)
 		return -ENOMEM;
 	bp->hwrm_cmd_resp_dma_addr =
-		rte_mem_virt2iova(bp->hwrm_cmd_resp_addr);
+		rte_malloc_virt2iova(bp->hwrm_cmd_resp_addr);
 	if (bp->hwrm_cmd_resp_dma_addr == RTE_BAD_IOVA) {
 		PMD_DRV_LOG(ERR,
 			"unable to map response address to physical memory\n");
@@ -2445,18 +2506,32 @@ int bnxt_alloc_hwrm_resources(struct bnxt *bp)
 	return 0;
 }
 
+int
+bnxt_clear_one_vnic_filter(struct bnxt *bp, struct bnxt_filter_info *filter)
+{
+	int rc = 0;
+
+	if (filter->filter_type == HWRM_CFA_EM_FILTER) {
+		rc = bnxt_hwrm_clear_em_filter(bp, filter);
+		if (rc)
+			return rc;
+	} else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER) {
+		rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
+		if (rc)
+			return rc;
+	}
+
+	rc = bnxt_hwrm_clear_l2_filter(bp, filter);
+	return rc;
+}
+
 int bnxt_clear_hwrm_vnic_filters(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 {
 	struct bnxt_filter_info *filter;
 	int rc = 0;
 
 	STAILQ_FOREACH(filter, &vnic->filter, next) {
-		if (filter->filter_type == HWRM_CFA_EM_FILTER)
-			rc = bnxt_hwrm_clear_em_filter(bp, filter);
-		else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
-			rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
-		else
-			rc = bnxt_hwrm_clear_l2_filter(bp, filter);
+		rc = bnxt_clear_one_vnic_filter(bp, filter);
 		STAILQ_REMOVE(&vnic->filter, filter, bnxt_filter_info, next);
 		bnxt_free_filter(bp, filter);
 	}
@@ -2474,12 +2549,7 @@ bnxt_clear_hwrm_vnic_flows(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 		flow = STAILQ_FIRST(&vnic->flow_list);
 		filter = flow->filter;
 		PMD_DRV_LOG(DEBUG, "filter type %d\n", filter->filter_type);
-		if (filter->filter_type == HWRM_CFA_EM_FILTER)
-			rc = bnxt_hwrm_clear_em_filter(bp, filter);
-		else if (filter->filter_type == HWRM_CFA_NTUPLE_FILTER)
-			rc = bnxt_hwrm_clear_ntuple_filter(bp, filter);
-		else
-			rc = bnxt_hwrm_clear_l2_filter(bp, filter);
+		rc = bnxt_clear_one_vnic_filter(bp, filter);
 
 		STAILQ_REMOVE(&vnic->flow_list, flow, rte_flow, next);
 		rte_free(flow);
@@ -2914,10 +2984,10 @@ int bnxt_hwrm_func_qcfg(struct bnxt *bp, uint16_t *mtu)
 	case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR1_5:
 	case HWRM_FUNC_QCFG_OUTPUT_PORT_PARTITION_TYPE_NPAR2_0:
 		/* FALLTHROUGH */
-		bp->port_partition_type = resp->port_partition_type;
+		bp->flags |= BNXT_FLAG_NPAR_PF;
 		break;
 	default:
-		bp->port_partition_type = 0;
+		bp->flags &= ~BNXT_FLAG_NPAR_PF;
 		break;
 	}
 
@@ -3053,9 +3123,9 @@ static void add_random_mac_if_needed(struct bnxt *bp,
 	}
 }
 
-static void reserve_resources_from_vf(struct bnxt *bp,
-				      struct hwrm_func_cfg_input *cfg_req,
-				      int vf)
+static int reserve_resources_from_vf(struct bnxt *bp,
+				     struct hwrm_func_cfg_input *cfg_req,
+				     int vf)
 {
 	struct hwrm_func_qcaps_input req = {0};
 	struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
@@ -3089,6 +3159,8 @@ static void reserve_resources_from_vf(struct bnxt *bp,
 	bp->max_ring_grps -= rte_le_to_cpu_16(resp->max_hw_ring_grps);
 
 	HWRM_UNLOCK();
+
+	return 0;
 }
 
 int bnxt_hwrm_func_qcfg_current_vf_vlan(struct bnxt *bp, int vf)
@@ -3297,17 +3369,19 @@ int bnxt_hwrm_tunnel_dst_port_alloc(struct bnxt *bp, uint16_t port,
 
 	HWRM_PREP(req, TUNNEL_DST_PORT_ALLOC, BNXT_USE_CHIMP_MB);
 	req.tunnel_type = tunnel_type;
-	req.tunnel_dst_port_val = port;
+	req.tunnel_dst_port_val = rte_cpu_to_be_16(port);
 	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
 	HWRM_CHECK_RESULT();
 
 	switch (tunnel_type) {
 	case HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN:
-		bp->vxlan_fw_dst_port_id = resp->tunnel_dst_port_id;
+		bp->vxlan_fw_dst_port_id =
+			rte_le_to_cpu_16(resp->tunnel_dst_port_id);
 		bp->vxlan_port = port;
 		break;
 	case HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_GENEVE:
-		bp->geneve_fw_dst_port_id = resp->tunnel_dst_port_id;
+		bp->geneve_fw_dst_port_id =
+			rte_le_to_cpu_16(resp->tunnel_dst_port_id);
 		bp->geneve_port = port;
 		break;
 	default:
@@ -3382,7 +3456,7 @@ int bnxt_hwrm_func_buf_rgtr(struct bnxt *bp)
 			 page_getenum(bp->pf.active_vfs * HWRM_MAX_REQ_LEN));
 	req.req_buf_len = rte_cpu_to_le_16(HWRM_MAX_REQ_LEN);
 	req.req_buf_page_addr0 =
-		rte_cpu_to_le_64(rte_mem_virt2iova(bp->pf.vf_req_buf));
+		rte_cpu_to_le_64(rte_malloc_virt2iova(bp->pf.vf_req_buf));
 	if (req.req_buf_page_addr0 == RTE_BAD_IOVA) {
 		PMD_DRV_LOG(ERR,
 			"unable to map buffer address to physical memory\n");
@@ -3812,11 +3886,11 @@ int bnxt_get_nvram_directory(struct bnxt *bp, uint32_t len, uint8_t *data)
 
 	buflen = dir_entries * entry_length;
 	buf = rte_malloc("nvm_dir", buflen, 0);
-	rte_mem_lock_page(buf);
 	if (buf == NULL)
 		return -ENOMEM;
-	dma_handle = rte_mem_virt2iova(buf);
+	dma_handle = rte_malloc_virt2iova(buf);
 	if (dma_handle == RTE_BAD_IOVA) {
+		rte_free(buf);
 		PMD_DRV_LOG(ERR,
 			"unable to map response address to physical memory\n");
 		return -ENOMEM;
@@ -3846,12 +3920,12 @@ int bnxt_hwrm_get_nvram_item(struct bnxt *bp, uint32_t index,
 	struct hwrm_nvm_read_output *resp = bp->hwrm_cmd_resp_addr;
 
 	buf = rte_malloc("nvm_item", length, 0);
-	rte_mem_lock_page(buf);
 	if (!buf)
 		return -ENOMEM;
 
-	dma_handle = rte_mem_virt2iova(buf);
+	dma_handle = rte_malloc_virt2iova(buf);
 	if (dma_handle == RTE_BAD_IOVA) {
+		rte_free(buf);
 		PMD_DRV_LOG(ERR,
 			"unable to map response address to physical memory\n");
 		return -ENOMEM;
@@ -3900,12 +3974,12 @@ int bnxt_hwrm_flash_nvram(struct bnxt *bp, uint16_t dir_type,
 	uint8_t *buf;
 
 	buf = rte_malloc("nvm_write", data_len, 0);
-	rte_mem_lock_page(buf);
 	if (!buf)
 		return -ENOMEM;
 
-	dma_handle = rte_mem_virt2iova(buf);
+	dma_handle = rte_malloc_virt2iova(buf);
 	if (dma_handle == RTE_BAD_IOVA) {
+		rte_free(buf);
 		PMD_DRV_LOG(ERR,
 			"unable to map response address to physical memory\n");
 		return -ENOMEM;
@@ -3967,7 +4041,7 @@ static int bnxt_hwrm_func_vf_vnic_query(struct bnxt *bp, uint16_t vf,
 
 	req.vf_id = rte_cpu_to_le_16(bp->pf.first_vf_id + vf);
 	req.max_vnic_id_cnt = rte_cpu_to_le_32(bp->pf.total_vnics);
-	req.vnic_id_tbl_addr = rte_cpu_to_le_64(rte_mem_virt2iova(vnic_ids));
+	req.vnic_id_tbl_addr = rte_cpu_to_le_64(rte_malloc_virt2iova(vnic_ids));
 
 	if (req.vnic_id_tbl_addr == RTE_BAD_IOVA) {
 		HWRM_UNLOCK();
@@ -4391,37 +4465,35 @@ int bnxt_vnic_rss_configure(struct bnxt *bp, struct bnxt_vnic_info *vnic)
 {
 	unsigned int rss_idx, fw_idx, i;
 
+	if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
+		return 0;
+
 	if (!(vnic->rss_table && vnic->hash_type))
 		return 0;
 
 	if (BNXT_CHIP_THOR(bp))
 		return bnxt_vnic_rss_configure_thor(bp, vnic);
 
-	if (vnic->fw_vnic_id == INVALID_HW_RING_ID)
-		return 0;
-
-	if (vnic->rss_table && vnic->hash_type) {
-		/*
-		 * Fill the RSS hash & redirection table with
-		 * ring group ids for all VNICs
-		 */
-		for (rss_idx = 0, fw_idx = 0; rss_idx < HW_HASH_INDEX_SIZE;
-			rss_idx++, fw_idx++) {
-			for (i = 0; i < bp->rx_cp_nr_rings; i++) {
-				fw_idx %= bp->rx_cp_nr_rings;
-				if (vnic->fw_grp_ids[fw_idx] !=
-				    INVALID_HW_RING_ID)
-					break;
-				fw_idx++;
-			}
-			if (i == bp->rx_cp_nr_rings)
-				return 0;
-			vnic->rss_table[rss_idx] = vnic->fw_grp_ids[fw_idx];
+	/*
+	 * Fill the RSS hash & redirection table with
+	 * ring group ids for all VNICs
+	 */
+	for (rss_idx = 0, fw_idx = 0; rss_idx < HW_HASH_INDEX_SIZE;
+	     rss_idx++, fw_idx++) {
+		for (i = 0; i < bp->rx_cp_nr_rings; i++) {
+			fw_idx %= bp->rx_cp_nr_rings;
+			if (vnic->fw_grp_ids[fw_idx] != INVALID_HW_RING_ID)
+				break;
+			fw_idx++;
 		}
-		return bnxt_hwrm_vnic_rss_cfg(bp, vnic);
+
+		if (i == bp->rx_cp_nr_rings)
+			return 0;
+
+		vnic->rss_table[rss_idx] = vnic->fw_grp_ids[fw_idx];
 	}
 
-	return 0;
+	return bnxt_hwrm_vnic_rss_cfg(bp, vnic);
 }
 
 static void bnxt_hwrm_set_coal_params(struct bnxt_coal *hw_coal,
@@ -4831,7 +4903,6 @@ int bnxt_hwrm_set_mac(struct bnxt *bp)
 
 	HWRM_CHECK_RESULT();
 
-	memcpy(bp->dflt_mac_addr, bp->mac_addr, RTE_ETHER_ADDR_LEN);
 	HWRM_UNLOCK();
 
 	return rc;
@@ -4844,7 +4915,7 @@ int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
 	uint32_t flags;
 	int rc;
 
-	if (!(bp->flags & BNXT_FLAG_FW_CAP_IF_CHANGE))
+	if (!(bp->fw_cap & BNXT_FW_CAP_IF_CHANGE))
 		return 0;
 
 	/* Do not issue FUNC_DRV_IF_CHANGE during reset recovery.
@@ -4887,7 +4958,7 @@ int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp)
 	int rc;
 
 	/* Older FW does not have error recovery support */
-	if (!(bp->flags & BNXT_FLAG_FW_CAP_ERROR_RECOVERY))
+	if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
 		return 0;
 
 	if (!info) {
@@ -5034,35 +5105,3 @@ int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path, uint64_t *timestamp)
 
 	return rc;
 }
-
-int bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(struct bnxt *bp)
-{
-	struct hwrm_cfa_adv_flow_mgnt_qcaps_output *resp =
-					bp->hwrm_cmd_resp_addr;
-	struct hwrm_cfa_adv_flow_mgnt_qcaps_input req = {0};
-	uint32_t flags = 0;
-	int rc = 0;
-
-	if (!(bp->flags & BNXT_FLAG_ADV_FLOW_MGMT))
-		return rc;
-
-	if (!(BNXT_PF(bp) || BNXT_VF_IS_TRUSTED(bp))) {
-		PMD_DRV_LOG(DEBUG,
-			    "Not a PF or trusted VF. Command not supported\n");
-		return 0;
-	}
-
-	HWRM_PREP(req, CFA_ADV_FLOW_MGNT_QCAPS, BNXT_USE_KONG(bp));
-	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_KONG(bp));
-
-	HWRM_CHECK_RESULT();
-	flags = rte_le_to_cpu_32(resp->flags);
-	HWRM_UNLOCK();
-
-	if (flags & HWRM_CFA_ADV_FLOW_MGNT_QCAPS_L2_HDR_SRC_FILTER_EN) {
-		bp->flow_flags |= BNXT_FLOW_FLAG_L2_HDR_SRC_FILTER_EN;
-		PMD_DRV_LOG(INFO, "Source L2 header filtering enabled\n");
-	}
-
-	return rc;
-}
diff --git a/dpdk/drivers/net/bnxt/bnxt_hwrm.h b/dpdk/drivers/net/bnxt/bnxt_hwrm.h
index abe5de9db6..8ceaeb59c0 100644
--- a/dpdk/drivers/net/bnxt/bnxt_hwrm.h
+++ b/dpdk/drivers/net/bnxt/bnxt_hwrm.h
@@ -35,6 +35,9 @@ struct bnxt_cp_ring_info;
 #define HWRM_QUEUE_SERVICE_PROFILE_LOSSY \
 	HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_LOSSY
 
+#define HWRM_QUEUE_SERVICE_PROFILE_UNKNOWN \
+	HWRM_QUEUE_QPORTCFG_OUTPUT_QUEUE_ID0_SERVICE_PROFILE_UNKNOWN
+
 #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESV_STRATEGY_MINIMAL_STATIC \
 	HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESERVATION_STRATEGY_MINIMAL_STATIC
 #define HWRM_FUNC_RESOURCE_QCAPS_OUTPUT_VF_RESV_STRATEGY_MAXIMAL \
@@ -86,6 +89,7 @@ int bnxt_hwrm_func_buf_rgtr(struct bnxt *bp);
 int bnxt_hwrm_func_buf_unrgtr(struct bnxt *bp);
 int bnxt_hwrm_func_driver_register(struct bnxt *bp);
 int bnxt_hwrm_func_qcaps(struct bnxt *bp);
+void bnxt_hwrm_free_vf_info(struct bnxt *bp);
 int bnxt_hwrm_func_reset(struct bnxt *bp);
 int bnxt_hwrm_func_driver_unregister(struct bnxt *bp, uint32_t flags);
 int bnxt_hwrm_func_qstats(struct bnxt *bp, uint16_t fid,
@@ -117,7 +121,7 @@ int bnxt_hwrm_stat_ctx_free(struct bnxt *bp,
 int bnxt_hwrm_ctx_qstats(struct bnxt *bp, uint32_t cid, int idx,
 			 struct rte_eth_stats *stats, uint8_t rx);
 
-int bnxt_hwrm_ver_get(struct bnxt *bp);
+int bnxt_hwrm_ver_get(struct bnxt *bp, uint32_t timeout);
 
 int bnxt_hwrm_vnic_alloc(struct bnxt *bp, struct bnxt_vnic_info *vnic);
 int bnxt_hwrm_vnic_cfg(struct bnxt *bp, struct bnxt_vnic_info *vnic);
@@ -226,5 +230,6 @@ int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp);
 int bnxt_hwrm_fw_reset(struct bnxt *bp);
 int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path,
 			    uint64_t *timestamp);
-int bnxt_hwrm_cfa_adv_flow_mgmt_qcaps(struct bnxt *bp);
+int bnxt_clear_one_vnic_filter(struct bnxt *bp,
+			       struct bnxt_filter_info *filter);
 #endif
diff --git a/dpdk/drivers/net/bnxt/bnxt_irq.c b/dpdk/drivers/net/bnxt/bnxt_irq.c
index 846325ea96..40e1b0c980 100644
--- a/dpdk/drivers/net/bnxt/bnxt_irq.c
+++ b/dpdk/drivers/net/bnxt/bnxt_irq.c
@@ -181,5 +181,13 @@ int bnxt_request_int(struct bnxt *bp)
 			irq->requested = 1;
 	}
 
+#ifdef RTE_EXEC_ENV_FREEBSD
+	/**
+	 * In FreeBSD OS, nic_uio does not support interrupts and
+	 * interrupt register callback will fail.
+	 */
+	rc = 0;
+#endif
+
 	return rc;
 }
diff --git a/dpdk/drivers/net/bnxt/bnxt_ring.c b/dpdk/drivers/net/bnxt/bnxt_ring.c
index ea46fa9bc0..bb60f8ab0f 100644
--- a/dpdk/drivers/net/bnxt/bnxt_ring.c
+++ b/dpdk/drivers/net/bnxt/bnxt_ring.c
@@ -110,9 +110,7 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 	uint64_t rx_offloads = bp->eth_dev->data->dev_conf.rxmode.offloads;
 	const struct rte_memzone *mz = NULL;
 	char mz_name[RTE_MEMZONE_NAMESIZE];
-	rte_iova_t mz_phys_addr_base;
 	rte_iova_t mz_phys_addr;
-	int sz;
 
 	int stats_len = (tx_ring_info || rx_ring_info) ?
 	    RTE_CACHE_LINE_ROUNDUP(sizeof(struct hwrm_stat_ctx_query_output) -
@@ -214,22 +212,7 @@ int bnxt_alloc_rings(struct bnxt *bp, uint16_t qidx,
 			return -ENOMEM;
 	}
 	memset(mz->addr, 0, mz->len);
-	mz_phys_addr_base = mz->iova;
 	mz_phys_addr = mz->iova;
-	if ((unsigned long)mz->addr == mz_phys_addr_base) {
-		PMD_DRV_LOG(DEBUG,
-			    "Memzone physical address same as virtual.\n");
-		PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
-		for (sz = 0; sz < total_alloc_len; sz += getpagesize())
-			rte_mem_lock_page(((char *)mz->addr) + sz);
-		mz_phys_addr_base = rte_mem_virt2iova(mz->addr);
-		mz_phys_addr = rte_mem_virt2iova(mz->addr);
-		if (mz_phys_addr == RTE_BAD_IOVA) {
-			PMD_DRV_LOG(ERR,
-			"unable to map ring address to physical memory\n");
-			return -ENOMEM;
-		}
-	}
 
 	if (tx_ring_info) {
 		txq->mz = mz;
@@ -468,6 +451,7 @@ int bnxt_alloc_rxtx_nq_ring(struct bnxt *bp)
 	ring->ring_mask = ring->ring_size - 1;
 	ring->vmem_size = 0;
 	ring->vmem = NULL;
+	ring->fw_ring_id = INVALID_HW_RING_ID;
 
 	nqr->cp_ring_struct = ring;
 	rc = bnxt_alloc_rings(bp, 0, NULL, NULL, nqr, NULL, "l2_nqr");
@@ -615,7 +599,7 @@ int bnxt_alloc_hwrm_rx_ring(struct bnxt *bp, int queue_index)
 
 	if (rxq->rx_started) {
 		if (bnxt_init_one_rx_ring(rxq)) {
-			RTE_LOG(ERR, PMD,
+			PMD_DRV_LOG(ERR,
 				"bnxt_init_one_rx_ring failed!\n");
 			bnxt_rx_queue_release_op(rxq);
 			rc = -ENOMEM;
diff --git a/dpdk/drivers/net/bnxt/bnxt_ring.h b/dpdk/drivers/net/bnxt/bnxt_ring.h
index 48a39d7884..0a4685d167 100644
--- a/dpdk/drivers/net/bnxt/bnxt_ring.h
+++ b/dpdk/drivers/net/bnxt/bnxt_ring.h
@@ -27,7 +27,7 @@
 #define DEFAULT_RX_RING_SIZE	256
 #define DEFAULT_TX_RING_SIZE	256
 
-#define AGG_RING_SIZE_FACTOR	2
+#define AGG_RING_SIZE_FACTOR	4
 #define AGG_RING_MULTIPLIER	2
 
 /* These assume 4k pages */
@@ -83,7 +83,7 @@ void bnxt_free_rxtx_nq_ring(struct bnxt *bp);
 static inline void bnxt_db_write(struct bnxt_db_info *db, uint32_t idx)
 {
 	if (db->db_64)
-		rte_write64_relaxed(db->db_key64 | idx, db->doorbell);
+		rte_write64(db->db_key64 | idx, db->doorbell);
 	else
 		rte_write32(db->db_key32 | idx, db->doorbell);
 }
@@ -94,7 +94,6 @@ static inline void bnxt_db_nq(struct bnxt_cp_ring_info *cpr)
 	if (unlikely(!cpr->cp_db.db_64))
 		return;
 
-	rte_smp_wmb();
 	rte_write64(cpr->cp_db.db_key64 | DBR_TYPE_NQ |
 		    RING_CMP(cpr->cp_ring_struct, cpr->cp_raw_cons),
 		    cpr->cp_db.doorbell);
@@ -106,7 +105,6 @@ static inline void bnxt_db_nq_arm(struct bnxt_cp_ring_info *cpr)
 	if (unlikely(!cpr->cp_db.db_64))
 		return;
 
-	rte_smp_wmb();
 	rte_write64(cpr->cp_db.db_key64 | DBR_TYPE_NQ_ARM |
 		    RING_CMP(cpr->cp_ring_struct, cpr->cp_raw_cons),
 		    cpr->cp_db.doorbell);
@@ -117,11 +115,18 @@ static inline void bnxt_db_cq(struct bnxt_cp_ring_info *cpr)
 	struct bnxt_db_info *db = &cpr->cp_db;
 	uint32_t idx = RING_CMP(cpr->cp_ring_struct, cpr->cp_raw_cons);
 
-	rte_smp_wmb();
-	if (db->db_64)
-		rte_write64(db->db_key64 | idx, db->doorbell);
-	else
-		B_CP_DIS_DB(cpr, cpr->cp_raw_cons);
+	if (db->db_64) {
+		uint64_t key_idx = db->db_key64 | idx;
+		void *doorbell = db->doorbell;
+
+		rte_compiler_barrier();
+		rte_write64_relaxed(key_idx, doorbell);
+	} else {
+		uint32_t cp_raw_cons = cpr->cp_raw_cons;
+
+		rte_compiler_barrier();
+		B_CP_DIS_DB(cpr, cp_raw_cons);
+	}
 }
 
 #endif
diff --git a/dpdk/drivers/net/bnxt/bnxt_rxq.c b/dpdk/drivers/net/bnxt/bnxt_rxq.c
index 457ebede0e..df00191c09 100644
--- a/dpdk/drivers/net/bnxt/bnxt_rxq.c
+++ b/dpdk/drivers/net/bnxt/bnxt_rxq.c
@@ -168,10 +168,8 @@ int bnxt_mq_rx_configure(struct bnxt *bp)
 	if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
 		struct rte_eth_rss_conf *rss = &dev_conf->rx_adv_conf.rss_conf;
 
-		if (bp->flags & BNXT_FLAG_UPDATE_HASH) {
-			rss = &bp->rss_conf;
+		if (bp->flags & BNXT_FLAG_UPDATE_HASH)
 			bp->flags &= ~BNXT_FLAG_UPDATE_HASH;
-		}
 
 		for (i = 0; i < bp->nr_vnics; i++) {
 			vnic = &bp->vnic_info[i];
@@ -203,11 +201,9 @@ void bnxt_rx_queue_release_mbufs(struct bnxt_rx_queue *rxq)
 	struct bnxt_tpa_info *tpa_info;
 	uint16_t i;
 
-	if (!rxq)
+	if (!rxq || !rxq->rx_ring)
 		return;
 
-	rte_spinlock_lock(&rxq->lock);
-
 	sw_ring = rxq->rx_ring->rx_buf_ring;
 	if (sw_ring) {
 		for (i = 0;
@@ -243,7 +239,6 @@ void bnxt_rx_queue_release_mbufs(struct bnxt_rx_queue *rxq)
 		}
 	}
 
-	rte_spinlock_unlock(&rxq->lock);
 }
 
 void bnxt_free_rx_mbufs(struct bnxt *bp)
@@ -268,12 +263,21 @@ void bnxt_rx_queue_release_op(void *rx_queue)
 		bnxt_rx_queue_release_mbufs(rxq);
 
 		/* Free RX ring hardware descriptors */
-		bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
-		/* Free RX Agg ring hardware descriptors */
-		bnxt_free_ring(rxq->rx_ring->ag_ring_struct);
-
+		if (rxq->rx_ring) {
+			bnxt_free_ring(rxq->rx_ring->rx_ring_struct);
+			rte_free(rxq->rx_ring->rx_ring_struct);
+			/* Free RX Agg ring hardware descriptors */
+			bnxt_free_ring(rxq->rx_ring->ag_ring_struct);
+			rte_free(rxq->rx_ring->ag_ring_struct);
+
+			rte_free(rxq->rx_ring);
+		}
 		/* Free RX completion ring hardware descriptors */
-		bnxt_free_ring(rxq->cp_ring->cp_ring_struct);
+		if (rxq->cp_ring) {
+			bnxt_free_ring(rxq->cp_ring->cp_ring_struct);
+			rte_free(rxq->cp_ring->cp_ring_struct);
+			rte_free(rxq->cp_ring);
+		}
 
 		bnxt_free_rxq_stats(rxq);
 		rte_memzone_free(rxq->mz);
@@ -300,7 +304,7 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 	if (rc)
 		return rc;
 
-	if (queue_idx >= BNXT_MAX_RINGS(bp)) {
+	if (queue_idx >= bnxt_max_rings(bp)) {
 		PMD_DRV_LOG(ERR,
 			"Cannot create Rx ring %d. Only %d rings available\n",
 			queue_idx, bp->max_rx_rings);
@@ -309,8 +313,7 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 
 	if (!nb_desc || nb_desc > MAX_RX_DESC_CNT) {
 		PMD_DRV_LOG(ERR, "nb_desc %d is invalid\n", nb_desc);
-		rc = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	if (eth_dev->data->rx_queues) {
@@ -322,19 +325,26 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 				 RTE_CACHE_LINE_SIZE, socket_id);
 	if (!rxq) {
 		PMD_DRV_LOG(ERR, "bnxt_rx_queue allocation failed!\n");
-		rc = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 	rxq->bp = bp;
 	rxq->mb_pool = mp;
 	rxq->nb_rx_desc = nb_desc;
 	rxq->rx_free_thresh = rx_conf->rx_free_thresh;
 
+	if (rx_conf->rx_drop_en != BNXT_DEFAULT_RX_DROP_EN)
+		PMD_DRV_LOG(NOTICE,
+			    "Per-queue config of drop-en is not supported.\n");
+	rxq->drop_en = BNXT_DEFAULT_RX_DROP_EN;
+
 	PMD_DRV_LOG(DEBUG, "RX Buf MTU %d\n", eth_dev->data->mtu);
 
 	rc = bnxt_init_rx_ring_struct(rxq, socket_id);
-	if (rc)
-		goto out;
+	if (rc) {
+		PMD_DRV_LOG(ERR,
+			    "init_rx_ring_struct failed!\n");
+		goto err;
+	}
 
 	PMD_DRV_LOG(DEBUG, "RX Buf size is %d\n", rxq->rx_buf_size);
 	rxq->queue_id = queue_idx;
@@ -346,13 +356,12 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 
 	eth_dev->data->rx_queues[queue_idx] = rxq;
 	/* Allocate RX ring hardware descriptors */
-	if (bnxt_alloc_rings(bp, queue_idx, NULL, rxq, rxq->cp_ring, NULL,
-			     "rxr")) {
+	rc = bnxt_alloc_rings(bp, queue_idx, NULL, rxq, rxq->cp_ring, NULL,
+			     "rxr");
+	if (rc) {
 		PMD_DRV_LOG(ERR,
-			"ring_dma_zone_reserve for rx_ring failed!\n");
-		bnxt_rx_queue_release_op(rxq);
-		rc = -ENOMEM;
-		goto out;
+			    "ring_dma_zone_reserve for rx_ring failed!\n");
+		goto err;
 	}
 	rte_atomic64_init(&rxq->rx_mbuf_alloc_fail);
 
@@ -370,13 +379,14 @@ int bnxt_rx_queue_setup_op(struct rte_eth_dev *eth_dev,
 		rxq->rx_started = true;
 	}
 	eth_dev->data->rx_queue_state[queue_idx] = queue_state;
-	rte_spinlock_init(&rxq->lock);
 
 	/* Configure mtu if it is different from what was configured before */
 	if (!queue_idx)
 		bnxt_mtu_set_op(eth_dev, eth_dev->data->mtu);
 
-out:
+	return 0;
+err:
+	bnxt_rx_queue_release_op(rxq);
 	return rc;
 }
 
@@ -540,12 +550,12 @@ int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 		rc = bnxt_vnic_rss_configure(bp, vnic);
 	}
 
-	if (BNXT_CHIP_THOR(bp)) {
-		/* Compute current number of active receive queues. */
-		for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++)
-			if (bp->rx_queues[i]->rx_started)
-				active_queue_cnt++;
+	/* Compute current number of active receive queues. */
+	for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++)
+		if (bp->rx_queues[i]->rx_started)
+			active_queue_cnt++;
 
+	if (BNXT_CHIP_THOR(bp)) {
 		/*
 		 * For Thor, we need to ensure that the VNIC default receive
 		 * ring corresponds to an active receive queue. When no queue
@@ -565,6 +575,22 @@ int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 			/* Reconfigure default receive ring. */
 			bnxt_hwrm_vnic_cfg(bp, vnic);
 		}
+	} else if (active_queue_cnt) {
+		/*
+		 * If the queue being stopped is the current default queue and
+		 * there are other active queues, pick one of them as the
+		 * default and reconfigure the vnic.
+		 */
+		if (vnic->dflt_ring_grp == bp->grp_info[rx_queue_id].fw_grp_id) {
+			for (i = vnic->start_grp_id; i < vnic->end_grp_id; i++) {
+				if (bp->rx_queues[i]->rx_started) {
+					vnic->dflt_ring_grp =
+						bp->grp_info[i].fw_grp_id;
+					bnxt_hwrm_vnic_cfg(bp, vnic);
+					break;
+				}
+			}
+		}
 	}
 
 	if (rc == 0)
diff --git a/dpdk/drivers/net/bnxt/bnxt_rxq.h b/dpdk/drivers/net/bnxt/bnxt_rxq.h
index 4f5182d9e9..ae3badb7a0 100644
--- a/dpdk/drivers/net/bnxt/bnxt_rxq.h
+++ b/dpdk/drivers/net/bnxt/bnxt_rxq.h
@@ -6,13 +6,13 @@
 #ifndef _BNXT_RQX_H_
 #define _BNXT_RQX_H_
 
+/* Drop by default when receive desc is not available. */
+#define BNXT_DEFAULT_RX_DROP_EN		1
+
 struct bnxt;
 struct bnxt_rx_ring_info;
 struct bnxt_cp_ring_info;
 struct bnxt_rx_queue {
-	rte_spinlock_t		lock;	/* Synchronize between rx_queue_stop
-					 * and fast path
-					 */
 	struct rte_mempool	*mb_pool; /* mbuf pool for RX ring */
 	struct rte_mbuf		*pkt_first_seg; /* 1st seg of pkt */
 	struct rte_mbuf		*pkt_last_seg; /* Last seg of pkt */
@@ -31,6 +31,7 @@ struct bnxt_rx_queue {
 	uint8_t			crc_len; /* 0 if CRC stripped, 4 otherwise */
 	uint8_t			rx_deferred_start; /* not in global dev start */
 	uint8_t			rx_started; /* RX queue is started */
+	uint8_t			drop_en; /* Drop when rx desc not available. */
 
 	struct bnxt		*bp;
 	int			index;
diff --git a/dpdk/drivers/net/bnxt/bnxt_rxr.c b/dpdk/drivers/net/bnxt/bnxt_rxr.c
index 3b713c2427..1cf8f3e17c 100644
--- a/dpdk/drivers/net/bnxt/bnxt_rxr.c
+++ b/dpdk/drivers/net/bnxt/bnxt_rxr.c
@@ -145,6 +145,7 @@ static void bnxt_tpa_start(struct bnxt_rx_queue *rxq,
 	tpa_info->mbuf = mbuf;
 	tpa_info->len = rte_le_to_cpu_32(tpa_start->len);
 
+	mbuf->data_off = RTE_PKTMBUF_HEADROOM;
 	mbuf->nb_segs = 1;
 	mbuf->next = NULL;
 	mbuf->pkt_len = rte_le_to_cpu_32(tpa_start->len);
@@ -261,6 +262,7 @@ static int bnxt_rx_pages(struct bnxt_rx_queue *rxq,
 		 */
 		rte_bitmap_set(rxr->ag_bitmap, ag_cons);
 	}
+	last->next = NULL;
 	bnxt_prod_ag_mbuf(rxq);
 	return 0;
 }
@@ -300,7 +302,6 @@ static inline struct rte_mbuf *bnxt_tpa_end(
 	mbuf = tpa_info->mbuf;
 	RTE_ASSERT(mbuf != NULL);
 
-	rte_prefetch0(mbuf);
 	if (agg_bufs) {
 		bnxt_rx_pages(rxq, mbuf, raw_cp_cons, agg_bufs, tpa_info);
 	}
@@ -474,8 +475,6 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 	if (mbuf == NULL)
 		return -EBUSY;
 
-	rte_prefetch0(mbuf);
-
 	mbuf->data_off = RTE_PKTMBUF_HEADROOM;
 	mbuf->nb_segs = 1;
 	mbuf->next = NULL;
@@ -606,6 +605,7 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 	struct bnxt_cp_ring_info *cpr = rxq->cp_ring;
 	struct bnxt_rx_ring_info *rxr = rxq->rx_ring;
 	uint32_t raw_cons = cpr->cp_raw_cons;
+	bool alloc_failed = false;
 	uint32_t cons;
 	int nb_rx_pkts = 0;
 	struct rx_pkt_cmpl *rxcmp;
@@ -618,14 +618,12 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		return 0;
 
 	/* If Rx Q was stopped return */
-	if (unlikely(!rxq->rx_started ||
-		     !rte_spinlock_trylock(&rxq->lock)))
+	if (unlikely(!rxq->rx_started))
 		return 0;
 
 	/* Handle RX burst request */
 	while (1) {
 		cons = RING_CMP(cpr->cp_ring_struct, raw_cons);
-		rte_prefetch0(&cpr->cp_desc_ring[cons]);
 		rxcmp = (struct rx_pkt_cmpl *)&cpr->cp_desc_ring[cons];
 
 		if (!CMP_VALID(rxcmp, raw_cons, cpr->cp_ring_struct))
@@ -637,10 +635,14 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		/* TODO: Avoid magic numbers... */
 		if ((CMP_TYPE(rxcmp) & 0x30) == 0x10) {
 			rc = bnxt_rx_pkt(&rx_pkts[nb_rx_pkts], rxq, &raw_cons);
-			if (likely(!rc) || rc == -ENOMEM)
+			if (!rc)
 				nb_rx_pkts++;
-			if (rc == -EBUSY)	/* partial completion */
+			else if (rc == -EBUSY)	/* partial completion */
 				break;
+			else if (rc == -ENOMEM) {
+				nb_rx_pkts++;
+				alloc_failed = true;
+			}
 		} else if (!BNXT_NUM_ASYNC_CPR(rxq->bp)) {
 			evt =
 			bnxt_event_hwrm_resp_handler(rxq->bp,
@@ -667,6 +669,10 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		goto done;
 	}
 
+	/* Ring the completion queue doorbell. */
+	bnxt_db_cq(cpr);
+
+	/* Ring the receive descriptor doorbell. */
 	if (prod != rxr->rx_prod)
 		bnxt_db_write(&rxr->rx_db, rxr->rx_prod);
 
@@ -674,23 +680,23 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 	if (ag_prod != rxr->ag_prod)
 		bnxt_db_write(&rxr->ag_db, rxr->ag_prod);
 
-	bnxt_db_cq(cpr);
-
 	/* Attempt to alloc Rx buf in case of a previous allocation failure. */
-	if (rc == -ENOMEM) {
-		int i;
+	if (alloc_failed) {
+		uint16_t cnt;
 
-		for (i = prod; i <= nb_rx_pkts;
-			i = RING_NEXT(rxr->rx_ring_struct, i)) {
-			struct bnxt_sw_rx_bd *rx_buf = &rxr->rx_buf_ring[i];
+		for (cnt = 0; cnt < nb_rx_pkts; cnt++) {
+			struct bnxt_sw_rx_bd *rx_buf;
+
+			prod = RING_NEXT(rxr->rx_ring_struct, prod);
+			rx_buf = &rxr->rx_buf_ring[prod];
 
 			/* Buffer already allocated for this index. */
 			if (rx_buf->mbuf != NULL)
 				continue;
 
 			/* This slot is empty. Alloc buffer for Rx */
-			if (!bnxt_alloc_rx_data(rxq, rxr, i)) {
-				rxr->rx_prod = i;
+			if (!bnxt_alloc_rx_data(rxq, rxr, prod)) {
+				rxr->rx_prod = prod;
 				bnxt_db_write(&rxr->rx_db, rxr->rx_prod);
 			} else {
 				PMD_DRV_LOG(ERR, "Alloc  mbuf failed\n");
@@ -700,8 +706,6 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 	}
 
 done:
-	rte_spinlock_unlock(&rxq->lock);
-
 	return nb_rx_pkts;
 }
 
@@ -778,6 +782,7 @@ int bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq, unsigned int socket_id)
 	ring->bd_dma = rxr->rx_desc_mapping;
 	ring->vmem_size = ring->ring_size * sizeof(struct bnxt_sw_rx_bd);
 	ring->vmem = (void **)&rxr->rx_buf_ring;
+	ring->fw_ring_id = INVALID_HW_RING_ID;
 
 	cpr = rte_zmalloc_socket("bnxt_rx_ring",
 				 sizeof(struct bnxt_cp_ring_info),
@@ -799,6 +804,7 @@ int bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq, unsigned int socket_id)
 	ring->bd_dma = cpr->cp_desc_mapping;
 	ring->vmem_size = 0;
 	ring->vmem = NULL;
+	ring->fw_ring_id = INVALID_HW_RING_ID;
 
 	/* Allocate Aggregator rings */
 	ring = rte_zmalloc_socket("bnxt_rx_ring_struct",
@@ -814,6 +820,7 @@ int bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq, unsigned int socket_id)
 	ring->bd_dma = rxr->ag_desc_mapping;
 	ring->vmem_size = ring->ring_size * sizeof(struct bnxt_sw_rx_bd);
 	ring->vmem = (void **)&rxr->ag_buf_ring;
+	ring->fw_ring_id = INVALID_HW_RING_ID;
 
 	return 0;
 }
@@ -844,7 +851,7 @@ int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq)
 	size = rte_pktmbuf_data_room_size(rxq->mb_pool) - RTE_PKTMBUF_HEADROOM;
 	size = RTE_MIN(BNXT_MAX_PKT_LEN, size);
 
-	type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT | RX_PROD_PKT_BD_FLAGS_EOP_PAD;
+	type = RX_PROD_PKT_BD_TYPE_RX_PROD_PKT;
 
 	rxr = rxq->rx_ring;
 	ring = rxr->rx_ring_struct;
@@ -852,11 +859,13 @@ int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq)
 
 	prod = rxr->rx_prod;
 	for (i = 0; i < ring->ring_size; i++) {
-		if (bnxt_alloc_rx_data(rxq, rxr, prod) != 0) {
-			PMD_DRV_LOG(WARNING,
-				"init'ed rx ring %d with %d/%d mbufs only\n",
-				rxq->queue_id, i, ring->ring_size);
-			break;
+		if (unlikely(!rxr->rx_buf_ring[i].mbuf)) {
+			if (bnxt_alloc_rx_data(rxq, rxr, prod) != 0) {
+				PMD_DRV_LOG(WARNING,
+					    "init'ed rx ring %d with %d/%d mbufs only\n",
+					    rxq->queue_id, i, ring->ring_size);
+				break;
+			}
 		}
 		rxr->rx_prod = prod;
 		prod = RING_NEXT(rxr->rx_ring_struct, prod);
@@ -868,11 +877,13 @@ int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq)
 	prod = rxr->ag_prod;
 
 	for (i = 0; i < ring->ring_size; i++) {
-		if (bnxt_alloc_ag_data(rxq, rxr, prod) != 0) {
-			PMD_DRV_LOG(WARNING,
-			"init'ed AG ring %d with %d/%d mbufs only\n",
-			rxq->queue_id, i, ring->ring_size);
-			break;
+		if (unlikely(!rxr->ag_buf_ring[i].mbuf)) {
+			if (bnxt_alloc_ag_data(rxq, rxr, prod) != 0) {
+				PMD_DRV_LOG(WARNING,
+					    "init'ed AG ring %d with %d/%d mbufs only\n",
+					    rxq->queue_id, i, ring->ring_size);
+				break;
+			}
 		}
 		rxr->ag_prod = prod;
 		prod = RING_NEXT(rxr->ag_ring_struct, prod);
@@ -883,11 +894,13 @@ int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq)
 		unsigned int max_aggs = BNXT_TPA_MAX_AGGS(rxq->bp);
 
 		for (i = 0; i < max_aggs; i++) {
-			rxr->tpa_info[i].mbuf =
-				__bnxt_alloc_rx_data(rxq->mb_pool);
-			if (!rxr->tpa_info[i].mbuf) {
-				rte_atomic64_inc(&rxq->rx_mbuf_alloc_fail);
-				return -ENOMEM;
+			if (unlikely(!rxr->tpa_info[i].mbuf)) {
+				rxr->tpa_info[i].mbuf =
+					__bnxt_alloc_rx_data(rxq->mb_pool);
+				if (!rxr->tpa_info[i].mbuf) {
+					rte_atomic64_inc(&rxq->rx_mbuf_alloc_fail);
+					return -ENOMEM;
+				}
 			}
 		}
 	}
diff --git a/dpdk/drivers/net/bnxt/bnxt_rxr.h b/dpdk/drivers/net/bnxt/bnxt_rxr.h
index 76bf88d707..410b46016b 100644
--- a/dpdk/drivers/net/bnxt/bnxt_rxr.h
+++ b/dpdk/drivers/net/bnxt/bnxt_rxr.h
@@ -212,8 +212,6 @@ struct bnxt_rx_ring_info {
 
 uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 			       uint16_t nb_pkts);
-uint16_t bnxt_dummy_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
-			      uint16_t nb_pkts);
 void bnxt_free_rx_rings(struct bnxt *bp);
 int bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq, unsigned int socket_id);
 int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq);
diff --git a/dpdk/drivers/net/bnxt/bnxt_rxtx_vec_sse.c b/dpdk/drivers/net/bnxt/bnxt_rxtx_vec_sse.c
index 22d9f9e84a..7529d0316b 100644
--- a/dpdk/drivers/net/bnxt/bnxt_rxtx_vec_sse.c
+++ b/dpdk/drivers/net/bnxt/bnxt_rxtx_vec_sse.c
@@ -233,8 +233,13 @@ bnxt_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	/* Return no more than RTE_BNXT_MAX_RX_BURST per call. */
 	nb_pkts = RTE_MIN(nb_pkts, RTE_BNXT_MAX_RX_BURST);
 
-	/* Make nb_pkts an integer multiple of RTE_BNXT_DESCS_PER_LOOP */
+	/*
+	 * Make nb_pkts an integer multiple of RTE_BNXT_DESCS_PER_LOOP.
+	 * nb_pkts < RTE_BNXT_DESCS_PER_LOOP, just return no packet
+	 */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_BNXT_DESCS_PER_LOOP);
+	if (!nb_pkts)
+		return 0;
 
 	/* Handle RX burst request */
 	while (1) {
@@ -289,7 +294,8 @@ bnxt_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 					(RX_PKT_CMPL_METADATA_VID_MASK |
 					RX_PKT_CMPL_METADATA_DE |
 					RX_PKT_CMPL_METADATA_PRI_MASK);
-				mbuf->ol_flags |= PKT_RX_VLAN;
+				mbuf->ol_flags |=
+					PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
 			}
 
 			bnxt_parse_csum(mbuf, rxcmp1);
@@ -332,6 +338,8 @@ bnxt_tx_cmp_vec(struct bnxt_tx_queue *txq, int nr_pkts)
 		tx_buf = &txr->tx_buf_ring[cons];
 		cons = RING_NEXT(txr->tx_ring_struct, cons);
 		mbuf = rte_pktmbuf_prefree_seg(tx_buf->mbuf);
+		if (unlikely(mbuf == NULL))
+			continue;
 		tx_buf->mbuf = NULL;
 
 		if (blk && mbuf->pool != free[0]->pool) {
diff --git a/dpdk/drivers/net/bnxt/bnxt_stats.c b/dpdk/drivers/net/bnxt/bnxt_stats.c
index 14d355fd08..84011fc3ea 100644
--- a/dpdk/drivers/net/bnxt/bnxt_stats.c
+++ b/dpdk/drivers/net/bnxt/bnxt_stats.c
@@ -389,11 +389,8 @@ int bnxt_stats_get_op(struct rte_eth_dev *eth_dev,
 	if (rc)
 		return rc;
 
-	memset(bnxt_stats, 0, sizeof(*bnxt_stats));
-	if (!(bp->flags & BNXT_FLAG_INIT_DONE)) {
-		PMD_DRV_LOG(ERR, "Device Initialization not complete!\n");
+	if (!eth_dev->data->dev_started)
 		return -EIO;
-	}
 
 	num_q_stats = RTE_MIN(bp->rx_cp_nr_rings,
 			      (unsigned int)RTE_ETHDEV_QUEUE_STAT_CNTRS);
@@ -437,7 +434,7 @@ int bnxt_stats_reset_op(struct rte_eth_dev *eth_dev)
 	if (ret)
 		return ret;
 
-	if (!(bp->flags & BNXT_FLAG_INIT_DONE)) {
+	if (!eth_dev->data->dev_started) {
 		PMD_DRV_LOG(ERR, "Device Initialization not complete!\n");
 		return -EINVAL;
 	}
@@ -620,70 +617,3 @@ int bnxt_dev_xstats_reset_op(struct rte_eth_dev *eth_dev)
 
 	return ret;
 }
-
-int bnxt_dev_xstats_get_by_id_op(struct rte_eth_dev *dev, const uint64_t *ids,
-		uint64_t *values, unsigned int limit)
-{
-	/* Account for the Tx drop pkts aka the Anti spoof counter */
-	const unsigned int stat_cnt = RTE_DIM(bnxt_rx_stats_strings) +
-				RTE_DIM(bnxt_tx_stats_strings) + 1 +
-				RTE_DIM(bnxt_rx_ext_stats_strings) +
-				RTE_DIM(bnxt_tx_ext_stats_strings);
-	struct bnxt *bp = dev->data->dev_private;
-	struct rte_eth_xstat xstats[stat_cnt];
-	uint64_t values_copy[stat_cnt];
-	uint16_t i;
-	int rc;
-
-	rc = is_bnxt_in_error(bp);
-	if (rc)
-		return rc;
-
-	if (!ids)
-		return bnxt_dev_xstats_get_op(dev, xstats, stat_cnt);
-
-	bnxt_dev_xstats_get_by_id_op(dev, NULL, values_copy, stat_cnt);
-	for (i = 0; i < limit; i++) {
-		if (ids[i] >= stat_cnt) {
-			PMD_DRV_LOG(ERR, "id value isn't valid");
-			return -EINVAL;
-		}
-		values[i] = values_copy[ids[i]];
-	}
-	return stat_cnt;
-}
-
-int bnxt_dev_xstats_get_names_by_id_op(struct rte_eth_dev *dev,
-				struct rte_eth_xstat_name *xstats_names,
-				const uint64_t *ids, unsigned int limit)
-{
-	/* Account for the Tx drop pkts aka the Anti spoof counter */
-	const unsigned int stat_cnt = RTE_DIM(bnxt_rx_stats_strings) +
-				RTE_DIM(bnxt_tx_stats_strings) + 1 +
-				RTE_DIM(bnxt_rx_ext_stats_strings) +
-				RTE_DIM(bnxt_tx_ext_stats_strings);
-	struct rte_eth_xstat_name xstats_names_copy[stat_cnt];
-	struct bnxt *bp = dev->data->dev_private;
-	uint16_t i;
-	int rc;
-
-	rc = is_bnxt_in_error(bp);
-	if (rc)
-		return rc;
-
-	if (!ids)
-		return bnxt_dev_xstats_get_names_op(dev, xstats_names,
-						    stat_cnt);
-	bnxt_dev_xstats_get_names_by_id_op(dev, xstats_names_copy, NULL,
-			stat_cnt);
-
-	for (i = 0; i < limit; i++) {
-		if (ids[i] >= stat_cnt) {
-			PMD_DRV_LOG(ERR, "id value isn't valid");
-			return -EINVAL;
-		}
-		strcpy(xstats_names[i].name,
-				xstats_names_copy[ids[i]].name);
-	}
-	return stat_cnt;
-}
diff --git a/dpdk/drivers/net/bnxt/bnxt_txq.c b/dpdk/drivers/net/bnxt/bnxt_txq.c
index 2d7645eeb0..78625eef60 100644
--- a/dpdk/drivers/net/bnxt/bnxt_txq.c
+++ b/dpdk/drivers/net/bnxt/bnxt_txq.c
@@ -27,7 +27,7 @@ static void bnxt_tx_queue_release_mbufs(struct bnxt_tx_queue *txq)
 	struct bnxt_sw_tx_bd *sw_ring;
 	uint16_t i;
 
-	if (!txq)
+	if (!txq || !txq->tx_ring)
 		return;
 
 	sw_ring = txq->tx_ring->tx_buf_ring;
@@ -62,10 +62,18 @@ void bnxt_tx_queue_release_op(void *tx_queue)
 
 		/* Free TX ring hardware descriptors */
 		bnxt_tx_queue_release_mbufs(txq);
-		bnxt_free_ring(txq->tx_ring->tx_ring_struct);
+		if (txq->tx_ring) {
+			bnxt_free_ring(txq->tx_ring->tx_ring_struct);
+			rte_free(txq->tx_ring->tx_ring_struct);
+			rte_free(txq->tx_ring);
+		}
 
 		/* Free TX completion ring hardware descriptors */
-		bnxt_free_ring(txq->cp_ring->cp_ring_struct);
+		if (txq->cp_ring) {
+			bnxt_free_ring(txq->cp_ring->cp_ring_struct);
+			rte_free(txq->cp_ring->cp_ring_struct);
+			rte_free(txq->cp_ring);
+		}
 
 		bnxt_free_txq_stats(txq);
 		rte_memzone_free(txq->mz);
@@ -90,7 +98,7 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 	if (rc)
 		return rc;
 
-	if (queue_idx >= BNXT_MAX_RINGS(bp)) {
+	if (queue_idx >= bnxt_max_rings(bp)) {
 		PMD_DRV_LOG(ERR,
 			"Cannot create Tx ring %d. Only %d rings available\n",
 			queue_idx, bp->max_tx_rings);
@@ -99,8 +107,7 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 
 	if (!nb_desc || nb_desc > MAX_TX_DESC_CNT) {
 		PMD_DRV_LOG(ERR, "nb_desc %d is invalid", nb_desc);
-		rc = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	if (eth_dev->data->tx_queues) {
@@ -114,8 +121,7 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 				 RTE_CACHE_LINE_SIZE, socket_id);
 	if (!txq) {
 		PMD_DRV_LOG(ERR, "bnxt_tx_queue allocation failed!");
-		rc = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
 	txq->free = rte_zmalloc_socket(NULL,
@@ -123,9 +129,8 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 				       RTE_CACHE_LINE_SIZE, socket_id);
 	if (!txq->free) {
 		PMD_DRV_LOG(ERR, "allocation of tx mbuf free array failed!");
-		rte_free(txq);
 		rc = -ENOMEM;
-		goto out;
+		goto err;
 	}
 	txq->bp = bp;
 	txq->nb_tx_desc = nb_desc;
@@ -134,7 +139,7 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 
 	rc = bnxt_init_tx_ring_struct(txq, socket_id);
 	if (rc)
-		goto out;
+		goto err;
 
 	txq->queue_id = queue_idx;
 	txq->port_id = eth_dev->data->port_id;
@@ -143,16 +148,14 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 	if (bnxt_alloc_rings(bp, queue_idx, txq, NULL, txq->cp_ring, NULL,
 			     "txr")) {
 		PMD_DRV_LOG(ERR, "ring_dma_zone_reserve for tx_ring failed!");
-		bnxt_tx_queue_release_op(txq);
 		rc = -ENOMEM;
-		goto out;
+		goto err;
 	}
 
 	if (bnxt_init_one_tx_ring(txq)) {
 		PMD_DRV_LOG(ERR, "bnxt_init_one_tx_ring failed!");
-		bnxt_tx_queue_release_op(txq);
 		rc = -ENOMEM;
-		goto out;
+		goto err;
 	}
 
 	eth_dev->data->tx_queues[queue_idx] = txq;
@@ -161,6 +164,9 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
 		txq->tx_started = false;
 	else
 		txq->tx_started = true;
-out:
+
+	return 0;
+err:
+	bnxt_tx_queue_release_op(txq);
 	return rc;
 }
diff --git a/dpdk/drivers/net/bnxt/bnxt_txr.c b/dpdk/drivers/net/bnxt/bnxt_txr.c
index 16021407e8..9a18e8f6f7 100644
--- a/dpdk/drivers/net/bnxt/bnxt_txr.c
+++ b/dpdk/drivers/net/bnxt/bnxt_txr.c
@@ -78,6 +78,7 @@ int bnxt_init_tx_ring_struct(struct bnxt_tx_queue *txq, unsigned int socket_id)
 	ring->bd_dma = txr->tx_desc_mapping;
 	ring->vmem_size = ring->ring_size * sizeof(struct bnxt_sw_tx_bd);
 	ring->vmem = (void **)&txr->tx_buf_ring;
+	ring->fw_ring_id = INVALID_HW_RING_ID;
 
 	cpr = rte_zmalloc_socket("bnxt_tx_ring",
 				 sizeof(struct bnxt_cp_ring_info),
@@ -98,6 +99,7 @@ int bnxt_init_tx_ring_struct(struct bnxt_tx_queue *txq, unsigned int socket_id)
 	ring->bd_dma = cpr->cp_desc_mapping;
 	ring->vmem_size = 0;
 	ring->vmem = NULL;
+	ring->fw_ring_id = INVALID_HW_RING_ID;
 
 	return 0;
 }
diff --git a/dpdk/drivers/net/bnxt/bnxt_txr.h b/dpdk/drivers/net/bnxt/bnxt_txr.h
index e7f43f9d1d..08fd2e0142 100644
--- a/dpdk/drivers/net/bnxt/bnxt_txr.h
+++ b/dpdk/drivers/net/bnxt/bnxt_txr.h
@@ -57,8 +57,6 @@ int bnxt_init_one_tx_ring(struct bnxt_tx_queue *txq);
 int bnxt_init_tx_ring_struct(struct bnxt_tx_queue *txq, unsigned int socket_id);
 uint16_t bnxt_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 			       uint16_t nb_pkts);
-uint16_t bnxt_dummy_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
-			      uint16_t nb_pkts);
 #ifdef RTE_ARCH_X86
 uint16_t bnxt_xmit_pkts_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 			    uint16_t nb_pkts);
diff --git a/dpdk/drivers/net/bnxt/bnxt_vnic.c b/dpdk/drivers/net/bnxt/bnxt_vnic.c
index 104342e13b..ef07721148 100644
--- a/dpdk/drivers/net/bnxt/bnxt_vnic.c
+++ b/dpdk/drivers/net/bnxt/bnxt_vnic.c
@@ -78,6 +78,9 @@ void bnxt_free_all_vnics(struct bnxt *bp)
 	struct bnxt_vnic_info *vnic;
 	unsigned int i;
 
+	if (bp->vnic_info == NULL)
+		return;
+
 	for (i = 0; i < bp->max_vnics; i++) {
 		vnic = &bp->vnic_info[i];
 		STAILQ_INSERT_TAIL(&bp->free_vnic_list, vnic, next);
@@ -150,17 +153,6 @@ int bnxt_alloc_vnic_attributes(struct bnxt *bp)
 			return -ENOMEM;
 	}
 	mz_phys_addr = mz->iova;
-	if ((unsigned long)mz->addr == mz_phys_addr) {
-		PMD_DRV_LOG(DEBUG,
-			    "Memzone physical address same as virtual.\n");
-		PMD_DRV_LOG(DEBUG, "Using rte_mem_virt2iova()\n");
-		mz_phys_addr = rte_mem_virt2iova(mz->addr);
-		if (mz_phys_addr == RTE_BAD_IOVA) {
-			PMD_DRV_LOG(ERR,
-				    "unable to map to physical memory\n");
-			return -ENOMEM;
-		}
-	}
 
 	for (i = 0; i < max_vnics; i++) {
 		vnic = &bp->vnic_info[i];
diff --git a/dpdk/drivers/net/bnxt/rte_pmd_bnxt.h b/dpdk/drivers/net/bnxt/rte_pmd_bnxt.h
index 2e893cc7bf..81d0d0e032 100644
--- a/dpdk/drivers/net/bnxt/rte_pmd_bnxt.h
+++ b/dpdk/drivers/net/bnxt/rte_pmd_bnxt.h
@@ -6,7 +6,8 @@
 #ifndef _PMD_BNXT_H_
 #define _PMD_BNXT_H_
 
-#include <rte_ethdev_driver.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
 
 /*
  * Response sent back to the caller after callback
diff --git a/dpdk/drivers/net/bonding/eth_bond_8023ad_private.h b/dpdk/drivers/net/bonding/eth_bond_8023ad_private.h
index 6e44ffdb1c..9b5738afee 100644
--- a/dpdk/drivers/net/bonding/eth_bond_8023ad_private.h
+++ b/dpdk/drivers/net/bonding/eth_bond_8023ad_private.h
@@ -50,6 +50,7 @@
 #define SM_FLAGS_MOVED                      0x0100
 #define SM_FLAGS_PARTNER_SHORT_TIMEOUT      0x0200
 #define SM_FLAGS_NTT                        0x0400
+#define SM_FLAGS_EXPIRED                    0x0800
 
 #define BOND_LINK_FULL_DUPLEX_KEY           0x01
 #define BOND_LINK_SPEED_KEY_10M             0x02
@@ -103,6 +104,8 @@ struct port {
 
 	/** The operational Partner's port parameters */
 	struct port_params partner;
+	/** Partner administrative parameter values */
+	struct port_params partner_admin;
 
 	/* Additional port parameters not listed in documentation */
 	/** State machine flags */
diff --git a/dpdk/drivers/net/bonding/eth_bond_private.h b/dpdk/drivers/net/bonding/eth_bond_private.h
index c9b2d0fe46..af92a4c52a 100644
--- a/dpdk/drivers/net/bonding/eth_bond_private.h
+++ b/dpdk/drivers/net/bonding/eth_bond_private.h
@@ -50,6 +50,8 @@ extern const struct rte_flow_ops bond_flow_ops;
 /** Port Queue Mapping Structure */
 struct bond_rx_queue {
 	uint16_t queue_id;
+	/**< Next active_slave to poll */
+	uint16_t active_slave;
 	/**< Queue Id */
 	struct bond_dev_private *dev_private;
 	/**< Reference to eth_dev private structure */
@@ -132,7 +134,6 @@ struct bond_dev_private {
 	uint16_t nb_rx_queues;			/**< Total number of rx queues */
 	uint16_t nb_tx_queues;			/**< Total number of tx queues*/
 
-	uint16_t active_slave;		/**< Next active_slave to poll */
 	uint16_t active_slave_count;		/**< Number of active slaves */
 	uint16_t active_slaves[RTE_MAX_ETHPORTS];    /**< Active slave list */
 
diff --git a/dpdk/drivers/net/bonding/rte_eth_bond_8023ad.c b/dpdk/drivers/net/bonding/rte_eth_bond_8023ad.c
index b77a37ddb3..5fe004e551 100644
--- a/dpdk/drivers/net/bonding/rte_eth_bond_8023ad.c
+++ b/dpdk/drivers/net/bonding/rte_eth_bond_8023ad.c
@@ -356,16 +356,28 @@ rx_machine(struct bond_dev_private *internals, uint16_t slave_id,
 
 		timer_set(&port->current_while_timer, timeout);
 		ACTOR_STATE_CLR(port, EXPIRED);
+		SM_FLAG_CLR(port, EXPIRED);
 		return; /* No state change */
 	}
 
 	/* If CURRENT state timer is not running (stopped or expired)
 	 * transit to EXPIRED state from DISABLED or CURRENT */
 	if (!timer_is_running(&port->current_while_timer)) {
-		ACTOR_STATE_SET(port, EXPIRED);
-		PARTNER_STATE_CLR(port, SYNCHRONIZATION);
-		PARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT);
-		timer_set(&port->current_while_timer, internals->mode4.short_timeout);
+		if (SM_FLAG(port, EXPIRED)) {
+			port->selected = UNSELECTED;
+			memcpy(&port->partner, &port->partner_admin,
+				sizeof(struct port_params));
+			record_default(port);
+			ACTOR_STATE_CLR(port, EXPIRED);
+			timer_cancel(&port->current_while_timer);
+		} else {
+			SM_FLAG_SET(port, EXPIRED);
+			ACTOR_STATE_SET(port, EXPIRED);
+			PARTNER_STATE_CLR(port, SYNCHRONIZATION);
+			PARTNER_STATE_SET(port, LACP_SHORT_TIMEOUT);
+			timer_set(&port->current_while_timer,
+				internals->mode4.short_timeout);
+		}
 	}
 }
 
@@ -798,7 +810,8 @@ rx_machine_update(struct bond_dev_private *internals, uint16_t slave_id,
 		RTE_ASSERT(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
 
 		partner = &lacp->lacpdu.partner;
-		if (rte_is_same_ether_addr(&partner->port_params.system,
+		if (rte_is_zero_ether_addr(&partner->port_params.system) ||
+			rte_is_same_ether_addr(&partner->port_params.system,
 			&internals->mode4.mac_addr)) {
 			/* This LACP frame is sending to the bonding port
 			 * so pass it to rx_machine.
@@ -1020,6 +1033,7 @@ bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev,
 	port->actor.port_number = rte_cpu_to_be_16(slave_id + 1);
 
 	memcpy(&port->partner, &initial, sizeof(struct port_params));
+	memcpy(&port->partner_admin, &initial, sizeof(struct port_params));
 
 	/* default states */
 	port->actor_state = STATE_AGGREGATION | STATE_LACP_ACTIVE | STATE_DEFAULTED;
@@ -1043,7 +1057,7 @@ bond_mode_8023ad_activate_slave(struct rte_eth_dev *bond_dev,
 	RTE_ASSERT(port->tx_ring == NULL);
 
 	socket_id = rte_eth_dev_socket_id(slave_id);
-	if (socket_id == (int)LCORE_ID_ANY)
+	if (socket_id == -1)
 		socket_id = rte_socket_id();
 
 	element_size = sizeof(struct slow_protocol_frame) +
@@ -1320,8 +1334,7 @@ bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
 		rte_eth_macaddr_get(slave_id, &m_hdr->eth_hdr.s_addr);
 
 		if (internals->mode4.dedicated_queues.enabled == 0) {
-			int retval = rte_ring_enqueue(port->tx_ring, pkt);
-			if (retval != 0) {
+			if (rte_ring_enqueue(port->tx_ring, pkt) != 0) {
 				/* reset timer */
 				port->rx_marker_timer = 0;
 				wrn = WRN_TX_QUEUE_FULL;
@@ -1341,8 +1354,7 @@ bond_mode_8023ad_handle_slow_pkt(struct bond_dev_private *internals,
 		}
 	} else if (likely(subtype == SLOW_SUBTYPE_LACP)) {
 		if (internals->mode4.dedicated_queues.enabled == 0) {
-			int retval = rte_ring_enqueue(port->rx_ring, pkt);
-			if (retval != 0) {
+			if (rte_ring_enqueue(port->rx_ring, pkt) != 0) {
 				/* If RX fing full free lacpdu message and drop packet */
 				wrn = WRN_RX_QUEUE_FULL;
 				goto free_out;
@@ -1675,9 +1687,6 @@ rte_eth_bond_8023ad_dedicated_queues_enable(uint16_t port)
 	dev = &rte_eth_devices[port];
 	internals = dev->data->dev_private;
 
-	if (check_for_bonded_ethdev(dev) != 0)
-		return -1;
-
 	if (bond_8023ad_slow_pkt_hw_filter_supported(port) != 0)
 		return -1;
 
@@ -1704,9 +1713,6 @@ rte_eth_bond_8023ad_dedicated_queues_disable(uint16_t port)
 	dev = &rte_eth_devices[port];
 	internals = dev->data->dev_private;
 
-	if (check_for_bonded_ethdev(dev) != 0)
-		return -1;
-
 	/* Device must be stopped to set up slow queue */
 	if (dev->data->dev_started)
 		return -1;
diff --git a/dpdk/drivers/net/bonding/rte_eth_bond_api.c b/dpdk/drivers/net/bonding/rte_eth_bond_api.c
index f38eb3b47f..a4007fe07c 100644
--- a/dpdk/drivers/net/bonding/rte_eth_bond_api.c
+++ b/dpdk/drivers/net/bonding/rte_eth_bond_api.c
@@ -129,12 +129,6 @@ deactivate_slave(struct rte_eth_dev *eth_dev, uint16_t port_id)
 	RTE_ASSERT(active_count < RTE_DIM(internals->active_slaves));
 	internals->active_slave_count = active_count;
 
-	/* Resetting active_slave when reaches to max
-	 * no of slaves in active list
-	 */
-	if (internals->active_slave >= active_count)
-		internals->active_slave = 0;
-
 	if (eth_dev->data->dev_started) {
 		if (internals->mode == BONDING_MODE_8023AD) {
 			bond_mode_8023ad_start(eth_dev);
@@ -167,7 +161,7 @@ rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
 
 	ret = rte_vdev_init(name, devargs);
 	if (ret)
-		return -ENOMEM;
+		return ret;
 
 	ret = rte_eth_dev_get_port_by_name(name, &port_id);
 	RTE_ASSERT(!ret);
@@ -698,6 +692,7 @@ __eth_bond_slave_remove_lock_free(uint16_t bonded_port_id,
 			internals->current_primary_port = internals->slaves[0].port_id;
 		else
 			internals->primary_port = 0;
+		mac_address_slaves_update(bonded_eth_dev);
 	}
 
 	if (internals->active_slave_count < 1) {
diff --git a/dpdk/drivers/net/bonding/rte_eth_bond_args.c b/dpdk/drivers/net/bonding/rte_eth_bond_args.c
index abdf552610..8c5f90dc63 100644
--- a/dpdk/drivers/net/bonding/rte_eth_bond_args.c
+++ b/dpdk/drivers/net/bonding/rte_eth_bond_args.c
@@ -22,23 +22,37 @@ const char *pmd_bond_init_valid_arguments[] = {
 	NULL
 };
 
+static inline int
+bond_pci_addr_cmp(const struct rte_device *dev, const void *_pci_addr)
+{
+	const struct rte_pci_device *pdev = RTE_DEV_TO_PCI_CONST(dev);
+	const struct rte_pci_addr *paddr = _pci_addr;
+
+	return rte_pci_addr_cmp(&pdev->addr, paddr);
+}
+
 static inline int
 find_port_id_by_pci_addr(const struct rte_pci_addr *pci_addr)
 {
-	struct rte_pci_device *pci_dev;
-	struct rte_pci_addr *eth_pci_addr;
+	struct rte_bus *pci_bus;
+	struct rte_device *dev;
 	unsigned i;
 
-	RTE_ETH_FOREACH_DEV(i) {
-		pci_dev = RTE_ETH_DEV_TO_PCI(&rte_eth_devices[i]);
-		eth_pci_addr = &pci_dev->addr;
+	pci_bus = rte_bus_find_by_name("pci");
+	if (pci_bus == NULL) {
+		RTE_BOND_LOG(ERR, "No PCI bus found");
+		return -1;
+	}
 
-		if (pci_addr->bus == eth_pci_addr->bus &&
-			pci_addr->devid == eth_pci_addr->devid &&
-			pci_addr->domain == eth_pci_addr->domain &&
-			pci_addr->function == eth_pci_addr->function)
-			return i;
+	dev = pci_bus->find_device(NULL, bond_pci_addr_cmp, pci_addr);
+	if (dev == NULL) {
+		RTE_BOND_LOG(ERR, "unable to find PCI device");
+		return -1;
 	}
+
+	RTE_ETH_FOREACH_DEV(i)
+		if (rte_eth_devices[i].device == dev)
+			return i;
 	return -1;
 }
 
@@ -57,15 +71,6 @@ find_port_id_by_dev_name(const char *name)
 	return -1;
 }
 
-static inline int
-bond_pci_addr_cmp(const struct rte_device *dev, const void *_pci_addr)
-{
-	const struct rte_pci_device *pdev = RTE_DEV_TO_PCI_CONST(dev);
-	const struct rte_pci_addr *paddr = _pci_addr;
-
-	return rte_pci_addr_cmp(&pdev->addr, paddr);
-}
-
 /**
  * Parses a port identifier string to a port id by pci address, then by name,
  * and finally port id.
@@ -74,23 +79,10 @@ static inline int
 parse_port_id(const char *port_str)
 {
 	struct rte_pci_addr dev_addr;
-	struct rte_bus *pci_bus;
-	struct rte_device *dev;
 	int port_id;
 
-	pci_bus = rte_bus_find_by_name("pci");
-	if (pci_bus == NULL) {
-		RTE_BOND_LOG(ERR, "unable to find PCI bus\n");
-		return -1;
-	}
-
 	/* try parsing as pci address, physical devices */
-	if (pci_bus->parse(port_str, &dev_addr) == 0) {
-		dev = pci_bus->find_device(NULL, bond_pci_addr_cmp, &dev_addr);
-		if (dev == NULL) {
-			RTE_BOND_LOG(ERR, "unable to find PCI device");
-			return -1;
-		}
+	if (rte_pci_addr_parse(port_str, &dev_addr) == 0) {
 		port_id = find_port_id_by_pci_addr(&dev_addr);
 		if (port_id < 0)
 			return -1;
@@ -108,9 +100,8 @@ parse_port_id(const char *port_str)
 		}
 	}
 
-	if (port_id < 0 || port_id > RTE_MAX_ETHPORTS) {
-		RTE_BOND_LOG(ERR, "Slave port specified (%s) outside expected range",
-				port_str);
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		RTE_BOND_LOG(ERR, "Specified port (%s) is invalid", port_str);
 		return -1;
 	}
 	return port_id;
diff --git a/dpdk/drivers/net/bonding/rte_eth_bond_pmd.c b/dpdk/drivers/net/bonding/rte_eth_bond_pmd.c
index 707a0f3cdd..e7cb418053 100644
--- a/dpdk/drivers/net/bonding/rte_eth_bond_pmd.c
+++ b/dpdk/drivers/net/bonding/rte_eth_bond_pmd.c
@@ -69,7 +69,7 @@ bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
 	internals = bd_rx_q->dev_private;
 	slave_count = internals->active_slave_count;
-	active_slave = internals->active_slave;
+	active_slave = bd_rx_q->active_slave;
 
 	for (i = 0; i < slave_count && nb_pkts; i++) {
 		uint16_t num_rx_slave;
@@ -86,8 +86,8 @@ bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 			active_slave = 0;
 	}
 
-	if (++internals->active_slave >= slave_count)
-		internals->active_slave = 0;
+	if (++bd_rx_q->active_slave >= slave_count)
+		bd_rx_q->active_slave = 0;
 	return num_rx_total;
 }
 
@@ -303,9 +303,9 @@ rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts,
 	memcpy(slaves, internals->active_slaves,
 			sizeof(internals->active_slaves[0]) * slave_count);
 
-	idx = internals->active_slave;
+	idx = bd_rx_q->active_slave;
 	if (idx >= slave_count) {
-		internals->active_slave = 0;
+		bd_rx_q->active_slave = 0;
 		idx = 0;
 	}
 	for (i = 0; i < slave_count && num_rx_total < nb_pkts; i++) {
@@ -367,8 +367,8 @@ rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts,
 			idx = 0;
 	}
 
-	if (++internals->active_slave >= slave_count)
-		internals->active_slave = 0;
+	if (++bd_rx_q->active_slave >= slave_count)
+		bd_rx_q->active_slave = 0;
 
 	return num_rx_total;
 }
@@ -534,8 +534,8 @@ mode6_debug(const char __attribute__((unused)) *info,
 static uint16_t
 bond_ethdev_rx_burst_alb(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 {
-	struct bond_tx_queue *bd_tx_q = (struct bond_tx_queue *)queue;
-	struct bond_dev_private *internals = bd_tx_q->dev_private;
+	struct bond_rx_queue *bd_rx_q = (struct bond_rx_queue *)queue;
+	struct bond_dev_private *internals = bd_rx_q->dev_private;
 	struct rte_ether_hdr *eth_h;
 	uint16_t ether_type, offset;
 	uint16_t nb_recv_pkts;
@@ -1502,6 +1502,7 @@ int
 mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
 {
 	struct bond_dev_private *internals = bonded_eth_dev->data->dev_private;
+	bool set;
 	int i;
 
 	/* Update slave devices MAC addresses */
@@ -1529,15 +1530,16 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
 	case BONDING_MODE_TLB:
 	case BONDING_MODE_ALB:
 	default:
+		set = true;
 		for (i = 0; i < internals->slave_count; i++) {
 			if (internals->slaves[i].port_id ==
 					internals->current_primary_port) {
 				if (rte_eth_dev_default_mac_addr_set(
-						internals->primary_port,
+						internals->current_primary_port,
 						bonded_eth_dev->data->mac_addrs)) {
 					RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
 							internals->current_primary_port);
-					return -1;
+					set = false;
 				}
 			} else {
 				if (rte_eth_dev_default_mac_addr_set(
@@ -1545,10 +1547,11 @@ mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev)
 						&internals->slaves[i].persisted_mac_addr)) {
 					RTE_BOND_LOG(ERR, "Failed to update port Id %d MAC address",
 							internals->slaves[i].port_id);
-					return -1;
 				}
 			}
 		}
+		if (!set)
+			return -1;
 	}
 
 	return 0;
@@ -2873,6 +2876,7 @@ bond_ethdev_lsc_event_callback(uint16_t port_id, enum rte_eth_event_type type,
 						internals->active_slaves[0]);
 			else
 				internals->current_primary_port = internals->primary_port;
+			mac_address_slaves_update(bonded_eth_dev);
 		}
 	}
 
@@ -2931,7 +2935,8 @@ bond_ethdev_rss_reta_update(struct rte_eth_dev *dev,
 		return -EINVAL;
 
 	 /* Copy RETA table */
-	reta_count = reta_size / RTE_RETA_GROUP_SIZE;
+	reta_count = (reta_size + RTE_RETA_GROUP_SIZE - 1) /
+			RTE_RETA_GROUP_SIZE;
 
 	for (i = 0; i < reta_count; i++) {
 		internals->reta_conf[i].mask = reta_conf[i].mask;
diff --git a/dpdk/drivers/net/cxgbe/base/adapter.h b/dpdk/drivers/net/cxgbe/base/adapter.h
index db654ad9cd..eabd70a213 100644
--- a/dpdk/drivers/net/cxgbe/base/adapter.h
+++ b/dpdk/drivers/net/cxgbe/base/adapter.h
@@ -816,6 +816,7 @@ int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_rspq *rq);
 int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_rspq *rq);
 void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq);
 void t4_sge_eth_clear_queues(struct port_info *pi);
+void t4_sge_eth_release_queues(struct port_info *pi);
 int cxgb4_set_rspq_intr_params(struct sge_rspq *q, unsigned int us,
 			       unsigned int cnt);
 int cxgbe_poll(struct sge_rspq *q, struct rte_mbuf **rx_pkts,
diff --git a/dpdk/drivers/net/cxgbe/cxgbe.h b/dpdk/drivers/net/cxgbe/cxgbe.h
index 6c1f73ac4b..8b8babc5e4 100644
--- a/dpdk/drivers/net/cxgbe/cxgbe.h
+++ b/dpdk/drivers/net/cxgbe/cxgbe.h
@@ -19,6 +19,10 @@
 #define CXGBE_MAX_RX_PKTLEN (9000 + RTE_ETHER_HDR_LEN + \
 				RTE_ETHER_CRC_LEN) /* max pkt */
 
+/* The max frame size with default MTU */
+#define CXGBE_ETH_MAX_LEN (RTE_ETHER_MTU + \
+		RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
+
 /* Max poll time is 100 * 100msec = 10 sec */
 #define CXGBE_LINK_STATUS_POLL_MS 100 /* 100ms */
 #define CXGBE_LINK_STATUS_POLL_CNT 100 /* Max number of times to poll */
@@ -40,7 +44,8 @@
 			   DEV_TX_OFFLOAD_IPV4_CKSUM | \
 			   DEV_TX_OFFLOAD_UDP_CKSUM | \
 			   DEV_TX_OFFLOAD_TCP_CKSUM | \
-			   DEV_TX_OFFLOAD_TCP_TSO)
+			   DEV_TX_OFFLOAD_TCP_TSO | \
+			   DEV_TX_OFFLOAD_MULTI_SEGS)
 
 #define CXGBE_RX_OFFLOADS (DEV_RX_OFFLOAD_VLAN_STRIP | \
 			   DEV_RX_OFFLOAD_IPV4_CKSUM | \
diff --git a/dpdk/drivers/net/cxgbe/cxgbe_ethdev.c b/dpdk/drivers/net/cxgbe/cxgbe_ethdev.c
index 51b63ef574..352b47fdfb 100644
--- a/dpdk/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/dpdk/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -74,6 +74,9 @@ uint16_t cxgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 	t4_os_lock(&txq->txq_lock);
 	/* free up desc from already completed tx */
 	reclaim_completed_tx(&txq->q);
+	if (unlikely(!nb_pkts))
+		goto out_unlock;
+
 	rte_prefetch0(rte_pktmbuf_mtod(tx_pkts[0], volatile void *));
 	while (total_sent < nb_pkts) {
 		pkts_remain = nb_pkts - total_sent;
@@ -94,6 +97,7 @@ uint16_t cxgbe_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 		reclaim_completed_tx(&txq->q);
 	}
 
+out_unlock:
 	t4_os_unlock(&txq->txq_lock);
 	return total_sent;
 }
@@ -300,7 +304,7 @@ int cxgbe_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
 		return -EINVAL;
 
 	/* set to jumbo mode if needed */
-	if (new_mtu > RTE_ETHER_MAX_LEN)
+	if (new_mtu > CXGBE_ETH_MAX_LEN)
 		eth_dev->data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
@@ -329,12 +333,7 @@ void cxgbe_dev_close(struct rte_eth_dev *eth_dev)
 		return;
 
 	cxgbe_down(pi);
-
-	/*
-	 *  We clear queues only if both tx and rx path of the port
-	 *  have been disabled
-	 */
-	t4_sge_eth_clear_queues(pi);
+	t4_sge_eth_release_queues(pi);
 }
 
 /* Start the device.
@@ -649,7 +648,7 @@ int cxgbe_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
 		rxq->fl.size = temp_nb_desc;
 
 	/* Set to jumbo mode if necessary */
-	if (pkt_len > RTE_ETHER_MAX_LEN)
+	if (pkt_len > CXGBE_ETH_MAX_LEN)
 		eth_dev->data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
diff --git a/dpdk/drivers/net/cxgbe/cxgbe_filter.c b/dpdk/drivers/net/cxgbe/cxgbe_filter.c
index b9d9d5d391..7affa0785a 100644
--- a/dpdk/drivers/net/cxgbe/cxgbe_filter.c
+++ b/dpdk/drivers/net/cxgbe/cxgbe_filter.c
@@ -8,6 +8,7 @@
 #include "base/t4_tcb.h"
 #include "base/t4_regs.h"
 #include "cxgbe_filter.h"
+#include "mps_tcam.h"
 #include "clip_tbl.h"
 #include "l2t.h"
 
@@ -269,6 +270,30 @@ int cxgbe_alloc_ftid(struct adapter *adap, u8 nentries)
 	return pos < size ? pos : -1;
 }
 
+/**
+ * Clear a filter and release any of its resources that we own.  This also
+ * clears the filter's "pending" status.
+ */
+static void clear_filter(struct filter_entry *f)
+{
+	struct port_info *pi = ethdev2pinfo(f->dev);
+
+	if (f->clipt)
+		cxgbe_clip_release(f->dev, f->clipt);
+
+	if (f->l2t)
+		cxgbe_l2t_release(f->l2t);
+
+	if (f->fs.mask.macidx)
+		cxgbe_mpstcam_remove(pi, f->fs.val.macidx);
+
+	/* The zeroing of the filter rule below clears the filter valid,
+	 * pending, locked flags etc. so it's all we need for
+	 * this operation.
+	 */
+	memset(f, 0, sizeof(*f));
+}
+
 /**
  * Construct hash filter ntuple.
  */
@@ -555,13 +580,26 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev,
 
 	f = t4_os_alloc(sizeof(*f));
 	if (!f)
-		goto out_err;
+		return -ENOMEM;
 
 	f->fs = *fs;
 	f->ctx = ctx;
 	f->dev = dev;
 	f->fs.iq = iq;
 
+	/* Allocate MPS TCAM entry to match Destination MAC. */
+	if (f->fs.mask.macidx) {
+		int idx;
+
+		idx = cxgbe_mpstcam_alloc(pi, f->fs.val.dmac, f->fs.mask.dmac);
+		if (idx <= 0) {
+			ret = -ENOMEM;
+			goto out_err;
+		}
+
+		f->fs.val.macidx = idx;
+	}
+
 	/*
 	 * If the new filter requires loopback Destination MAC and/or VLAN
 	 * rewriting then we need to allocate a Layer 2 Table (L2T) entry for
@@ -592,7 +630,7 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev,
 		mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
 		if (!mbuf) {
 			ret = -ENOMEM;
-			goto free_clip;
+			goto free_atid;
 		}
 
 		mbuf->data_len = size;
@@ -622,33 +660,15 @@ static int cxgbe_set_hash_filter(struct rte_eth_dev *dev,
 	t4_mgmt_tx(ctrlq, mbuf);
 	return 0;
 
-free_clip:
-	cxgbe_clip_release(f->dev, f->clipt);
 free_atid:
 	cxgbe_free_atid(t, atid);
 
 out_err:
+	clear_filter(f);
 	t4_os_free(f);
 	return ret;
 }
 
-/**
- * Clear a filter and release any of its resources that we own.  This also
- * clears the filter's "pending" status.
- */
-static void clear_filter(struct filter_entry *f)
-{
-	if (f->clipt)
-		cxgbe_clip_release(f->dev, f->clipt);
-
-	/*
-	 * The zeroing of the filter rule below clears the filter valid,
-	 * pending, locked flags etc. so it's all we need for
-	 * this operation.
-	 */
-	memset(f, 0, sizeof(*f));
-}
-
 /**
  * t4_mk_filtdelwr - create a delete filter WR
  * @adap: adapter context
@@ -718,19 +738,6 @@ static int set_filter_wr(struct rte_eth_dev *dev, unsigned int fidx)
 	unsigned int port_id = ethdev2pinfo(dev)->port_id;
 	int ret;
 
-	/*
-	 * If the new filter requires loopback Destination MAC and/or VLAN
-	 * rewriting then we need to allocate a Layer 2 Table (L2T) entry for
-	 * the filter.
-	 */
-	if (f->fs.newvlan) {
-		/* allocate L2T entry for new filter */
-		f->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan,
-						   f->fs.eport, f->fs.dmac);
-		if (!f->l2t)
-			return -ENOMEM;
-	}
-
 	ctrlq = &adapter->sge.ctrlq[port_id];
 	mbuf = rte_pktmbuf_alloc(ctrlq->mb_pool);
 	if (!mbuf) {
@@ -1007,16 +1014,6 @@ int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,
 		return ret;
 	}
 
-	/*
-	 * Allocate a clip table entry only if we have non-zero IPv6 address
-	 */
-	if (chip_ver > CHELSIO_T5 && fs->type &&
-	    memcmp(fs->val.lip, bitoff, sizeof(bitoff))) {
-		f->clipt = cxgbe_clip_alloc(dev, (u32 *)&fs->val.lip);
-		if (!f->clipt)
-			goto free_tid;
-	}
-
 	/*
 	 * Convert the filter specification into our internal format.
 	 * We copy the PF/VF specification into the Outer VLAN field
@@ -1027,6 +1024,42 @@ int cxgbe_set_filter(struct rte_eth_dev *dev, unsigned int filter_id,
 	f->fs.iq = iq;
 	f->dev = dev;
 
+	/* Allocate MPS TCAM entry to match Destination MAC. */
+	if (f->fs.mask.macidx) {
+		int idx;
+
+		idx = cxgbe_mpstcam_alloc(pi, f->fs.val.dmac, f->fs.mask.dmac);
+		if (idx <= 0) {
+			ret = -ENOMEM;
+			goto free_tid;
+		}
+
+		f->fs.val.macidx = idx;
+	}
+
+	/* Allocate a clip table entry only if we have non-zero IPv6 address. */
+	if (chip_ver > CHELSIO_T5 && f->fs.type &&
+	    memcmp(f->fs.val.lip, bitoff, sizeof(bitoff))) {
+		f->clipt = cxgbe_clip_alloc(dev, (u32 *)&f->fs.val.lip);
+		if (!f->clipt) {
+			ret = -ENOMEM;
+			goto free_tid;
+		}
+	}
+
+	/* If the new filter requires loopback Destination MAC and/or VLAN
+	 * rewriting then we need to allocate a Layer 2 Table (L2T) entry for
+	 * the filter.
+	 */
+	if (f->fs.newvlan) {
+		f->l2t = cxgbe_l2t_alloc_switching(f->dev, f->fs.vlan,
+						   f->fs.eport, f->fs.dmac);
+		if (!f->l2t) {
+			ret = -ENOMEM;
+			goto free_tid;
+		}
+	}
+
 	/*
 	 * Attempt to set the filter.  If we don't succeed, we clear
 	 * it and return the failure.
@@ -1107,6 +1140,7 @@ void cxgbe_hash_filter_rpl(struct adapter *adap,
 		}
 
 		cxgbe_free_atid(t, ftid);
+		clear_filter(f);
 		t4_os_free(f);
 	}
 
@@ -1331,13 +1365,8 @@ void cxgbe_hash_del_filter_rpl(struct adapter *adap,
 	}
 
 	ctx = f->ctx;
-	f->ctx = NULL;
-
-	f->valid = 0;
-
-	if (f->clipt)
-		cxgbe_clip_release(f->dev, f->clipt);
 
+	clear_filter(f);
 	cxgbe_remove_tid(t, 0, tid, 0);
 	t4_os_free(f);
 
diff --git a/dpdk/drivers/net/cxgbe/cxgbe_filter.h b/dpdk/drivers/net/cxgbe/cxgbe_filter.h
index 06021c8544..e69e9d3f59 100644
--- a/dpdk/drivers/net/cxgbe/cxgbe_filter.h
+++ b/dpdk/drivers/net/cxgbe/cxgbe_filter.h
@@ -69,8 +69,10 @@ struct ch_filter_tuple {
 	uint16_t lport;		/* local port */
 	uint16_t fport;		/* foreign port */
 
+	uint8_t dmac[6];        /* Destination MAC to match */
+
 	/* reservations for future additions */
-	uint8_t rsvd[12];
+	uint8_t rsvd[6];
 };
 
 /*
diff --git a/dpdk/drivers/net/cxgbe/cxgbe_flow.c b/dpdk/drivers/net/cxgbe/cxgbe_flow.c
index 9070f4960d..1298fb12a8 100644
--- a/dpdk/drivers/net/cxgbe/cxgbe_flow.c
+++ b/dpdk/drivers/net/cxgbe/cxgbe_flow.c
@@ -190,20 +190,9 @@ ch_rte_parsetype_eth(const void *dmask, const struct rte_flow_item *item,
 					  "src mac filtering not supported");
 
 	if (!rte_is_zero_ether_addr(&mask->dst)) {
-		const u8 *addr = (const u8 *)&spec->dst.addr_bytes[0];
-		const u8 *m = (const u8 *)&mask->dst.addr_bytes[0];
-		struct rte_flow *flow = (struct rte_flow *)fs->private;
-		struct port_info *pi = (struct port_info *)
-					(flow->dev->data->dev_private);
-		int idx;
-
-		idx = cxgbe_mpstcam_alloc(pi, addr, m);
-		if (idx <= 0)
-			return rte_flow_error_set(e, idx,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
-						  NULL, "unable to allocate mac"
-						  " entry in h/w");
-		CXGBE_FILL_FS(idx, 0x1ff, macidx);
+		CXGBE_FILL_FS(0, 0x1ff, macidx);
+		CXGBE_FILL_FS_MEMCPY(spec->dst.addr_bytes, mask->dst.addr_bytes,
+				     dmac);
 	}
 
 	/* Only set outer ethertype, if we didn't encounter VLAN item yet.
@@ -230,7 +219,7 @@ ch_rte_parsetype_port(const void *dmask, const struct rte_flow_item *item,
 	if (val->index > 0x7)
 		return rte_flow_error_set(e, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
 					  item,
-					  "port index upto 0x7 is supported");
+					  "port index up to 0x7 is supported");
 
 	CXGBE_FILL_FS(val->index, mask->index, iport);
 
@@ -1085,17 +1074,6 @@ static int __cxgbe_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
 		return ctx.result;
 	}
 
-	fs = &flow->fs;
-	if (fs->mask.macidx) {
-		struct port_info *pi = (struct port_info *)
-					(dev->data->dev_private);
-		int ret;
-
-		ret = cxgbe_mpstcam_remove(pi, fs->val.macidx);
-		if (!ret)
-			return ret;
-	}
-
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/cxgbe/mps_tcam.c b/dpdk/drivers/net/cxgbe/mps_tcam.c
index 5302d1343d..6e5fae9928 100644
--- a/dpdk/drivers/net/cxgbe/mps_tcam.c
+++ b/dpdk/drivers/net/cxgbe/mps_tcam.c
@@ -140,6 +140,7 @@ int cxgbe_mpstcam_modify(struct port_info *pi, int idx, const u8 *addr)
 	/* idx can now be different from what user provided */
 	entry = &mpstcam->entry[idx];
 	memcpy(entry->eth_addr, addr, RTE_ETHER_ADDR_LEN);
+	memset(entry->mask, ~0, RTE_ETHER_ADDR_LEN);
 	/* NOTE: we have considered the case that idx returned by t4_change_mac
 	 * will be different from the user provided value only if user
 	 * provided value is -1
diff --git a/dpdk/drivers/net/cxgbe/sge.c b/dpdk/drivers/net/cxgbe/sge.c
index aba85a2090..7587c46aab 100644
--- a/dpdk/drivers/net/cxgbe/sge.c
+++ b/dpdk/drivers/net/cxgbe/sge.c
@@ -1421,16 +1421,49 @@ int t4_mgmt_tx(struct sge_ctrl_txq *q, struct rte_mbuf *mbuf)
 	return ctrl_xmit(q, mbuf);
 }
 
+static int cxgbe_dma_mzone_name(char *name, size_t len, uint16_t port_id,
+				uint16_t queue_id, const char *ring_name)
+{
+	return snprintf(name, len, "eth_p%d_q%d_%s",
+			port_id, queue_id, ring_name);
+}
+
+static int cxgbe_dma_zone_free(const struct rte_eth_dev *dev,
+			       const char *ring_name,
+			       uint16_t queue_id)
+{
+	char z_name[RTE_MEMZONE_NAMESIZE];
+	const struct rte_memzone *mz;
+	int rc = 0;
+
+	rc = cxgbe_dma_mzone_name(z_name, sizeof(z_name), dev->data->port_id,
+				  queue_id, ring_name);
+	if (rc >= RTE_MEMZONE_NAMESIZE) {
+		RTE_ETHDEV_LOG(ERR, "ring name too long\n");
+		return -ENAMETOOLONG;
+	}
+
+	mz = rte_memzone_lookup(z_name);
+	if (mz)
+		rc = rte_memzone_free(mz);
+	else
+		rc = -ENOENT;
+
+	return rc;
+}
+
 /**
  * alloc_ring - allocate resources for an SGE descriptor ring
- * @dev: the PCI device's core device
+ * @dev: the port associated with the queue
+ * @z_name: memzone's name
+ * @queue_id: queue index
+ * @socket_id: preferred socket id for memory allocations
  * @nelem: the number of descriptors
  * @elem_size: the size of each descriptor
+ * @stat_size: extra space in HW ring for status information
  * @sw_size: the size of the SW state associated with each ring element
  * @phys: the physical address of the allocated ring
  * @metadata: address of the array holding the SW state for the ring
- * @stat_size: extra space in HW ring for status information
- * @node: preferred node for memory allocations
  *
  * Allocates resources for an SGE descriptor ring, such as Tx queues,
  * free buffer lists, or response queues.  Each SGE ring requires
@@ -1440,39 +1473,34 @@ int t4_mgmt_tx(struct sge_ctrl_txq *q, struct rte_mbuf *mbuf)
  * of the function), the bus address of the HW ring, and the address
  * of the SW ring.
  */
-static void *alloc_ring(size_t nelem, size_t elem_size,
-			size_t sw_size, dma_addr_t *phys, void *metadata,
-			size_t stat_size, __rte_unused uint16_t queue_id,
-			int socket_id, const char *z_name,
-			const char *z_name_sw)
+static void *alloc_ring(struct rte_eth_dev *dev, const char *z_name,
+			uint16_t queue_id, int socket_id, size_t nelem,
+			size_t elem_size, size_t stat_size, size_t sw_size,
+			dma_addr_t *phys, void *metadata)
 {
 	size_t len = CXGBE_MAX_RING_DESC_SIZE * elem_size + stat_size;
+	char z_name_sw[RTE_MEMZONE_NAMESIZE];
 	const struct rte_memzone *tz;
 	void *s = NULL;
 
+	snprintf(z_name_sw, sizeof(z_name_sw), "eth_p%d_q%d_%s_sw_ring",
+		 dev->data->port_id, queue_id, z_name);
+
 	dev_debug(adapter, "%s: nelem = %zu; elem_size = %zu; sw_size = %zu; "
 		  "stat_size = %zu; queue_id = %u; socket_id = %d; z_name = %s;"
 		  " z_name_sw = %s\n", __func__, nelem, elem_size, sw_size,
 		  stat_size, queue_id, socket_id, z_name, z_name_sw);
 
-	tz = rte_memzone_lookup(z_name);
-	if (tz) {
-		dev_debug(adapter, "%s: tz exists...returning existing..\n",
-			  __func__);
-		goto alloc_sw_ring;
-	}
-
 	/*
 	 * Allocate TX/RX ring hardware descriptors. A memzone large enough to
 	 * handle the maximum ring size is allocated in order to allow for
 	 * resizing in later calls to the queue setup function.
 	 */
-	tz = rte_memzone_reserve_aligned(z_name, len, socket_id,
-			RTE_MEMZONE_IOVA_CONTIG, 4096);
+	tz = rte_eth_dma_zone_reserve(dev, z_name, queue_id, len, 4096,
+				      socket_id);
 	if (!tz)
 		return NULL;
 
-alloc_sw_ring:
 	memset(tz->addr, 0, len);
 	if (sw_size) {
 		s = rte_zmalloc_socket(z_name_sw, nelem * sw_size,
@@ -1788,21 +1816,15 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
 	struct fw_iq_cmd c;
 	struct sge *s = &adap->sge;
 	struct port_info *pi = eth_dev->data->dev_private;
-	char z_name[RTE_MEMZONE_NAMESIZE];
-	char z_name_sw[RTE_MEMZONE_NAMESIZE];
 	unsigned int nb_refill;
 	u8 pciechan;
 
 	/* Size needs to be multiple of 16, including status entry. */
 	iq->size = cxgbe_roundup(iq->size, 16);
 
-	snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
-			eth_dev->data->port_id, queue_id,
-			fwevtq ? "fwq_ring" : "rx_ring");
-	snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
-	iq->desc = alloc_ring(iq->size, iq->iqe_len, 0, &iq->phys_addr, NULL, 0,
-			      queue_id, socket_id, z_name, z_name_sw);
+	iq->desc = alloc_ring(eth_dev, fwevtq ? "fwq_ring" : "rx_ring",
+			      queue_id, socket_id, iq->size, iq->iqe_len,
+			      0, 0, &iq->phys_addr, NULL);
 	if (!iq->desc)
 		return -ENOMEM;
 
@@ -1860,18 +1882,14 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
 			fl->size = s->fl_starve_thres - 1 + 2 * 8;
 		fl->size = cxgbe_roundup(fl->size, 8);
 
-		snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
-				eth_dev->data->port_id, queue_id,
-				fwevtq ? "fwq_ring" : "fl_ring");
-		snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
-		fl->desc = alloc_ring(fl->size, sizeof(__be64),
+		fl->desc = alloc_ring(eth_dev, "fl_ring", queue_id, socket_id,
+				      fl->size, sizeof(__be64), s->stat_len,
 				      sizeof(struct rx_sw_desc),
-				      &fl->addr, &fl->sdesc, s->stat_len,
-				      queue_id, socket_id, z_name, z_name_sw);
-
-		if (!fl->desc)
-			goto fl_nomem;
+				      &fl->addr, &fl->sdesc);
+		if (!fl->desc) {
+			ret = -ENOMEM;
+			goto err;
+		}
 
 		flsz = fl->size / 8 + s->stat_len / sizeof(struct tx_desc);
 		c.iqns_to_fl0congen |=
@@ -1991,8 +2009,6 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq,
 refill_fl_err:
 	t4_iq_free(adap, adap->mbox, adap->pf, 0, FW_IQ_TYPE_FL_INT_CAP,
 		   iq->cntxt_id, fl->cntxt_id, 0xffff);
-fl_nomem:
-	ret = -ENOMEM;
 err:
 	iq->cntxt_id = 0;
 	iq->abs_id = 0;
@@ -2058,21 +2074,15 @@ int t4_sge_alloc_eth_txq(struct adapter *adap, struct sge_eth_txq *txq,
 	struct fw_eq_eth_cmd c;
 	struct sge *s = &adap->sge;
 	struct port_info *pi = eth_dev->data->dev_private;
-	char z_name[RTE_MEMZONE_NAMESIZE];
-	char z_name_sw[RTE_MEMZONE_NAMESIZE];
 	u8 pciechan;
 
 	/* Add status entries */
 	nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
 
-	snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
-			eth_dev->data->port_id, queue_id, "tx_ring");
-	snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
-	txq->q.desc = alloc_ring(txq->q.size, sizeof(struct tx_desc),
-				 sizeof(struct tx_sw_desc), &txq->q.phys_addr,
-				 &txq->q.sdesc, s->stat_len, queue_id,
-				 socket_id, z_name, z_name_sw);
+	txq->q.desc = alloc_ring(eth_dev, "tx_ring", queue_id, socket_id,
+				 txq->q.size, sizeof(struct tx_desc),
+				 s->stat_len, sizeof(struct tx_sw_desc),
+				 &txq->q.phys_addr, &txq->q.sdesc);
 	if (!txq->q.desc)
 		return -ENOMEM;
 
@@ -2137,20 +2147,13 @@ int t4_sge_alloc_ctrl_txq(struct adapter *adap, struct sge_ctrl_txq *txq,
 	struct fw_eq_ctrl_cmd c;
 	struct sge *s = &adap->sge;
 	struct port_info *pi = eth_dev->data->dev_private;
-	char z_name[RTE_MEMZONE_NAMESIZE];
-	char z_name_sw[RTE_MEMZONE_NAMESIZE];
 
 	/* Add status entries */
 	nentries = txq->q.size + s->stat_len / sizeof(struct tx_desc);
 
-	snprintf(z_name, sizeof(z_name), "eth_p%d_q%d_%s",
-			eth_dev->data->port_id, queue_id, "ctrl_tx_ring");
-	snprintf(z_name_sw, sizeof(z_name_sw), "%s_sw_ring", z_name);
-
-	txq->q.desc = alloc_ring(txq->q.size, sizeof(struct tx_desc),
-				 0, &txq->q.phys_addr,
-				 NULL, 0, queue_id,
-				 socket_id, z_name, z_name_sw);
+	txq->q.desc = alloc_ring(eth_dev, "ctrl_tx_ring", queue_id,
+				 socket_id, txq->q.size, sizeof(struct tx_desc),
+				 0, 0, &txq->q.phys_addr, NULL);
 	if (!txq->q.desc)
 		return -ENOMEM;
 
@@ -2262,6 +2265,36 @@ void t4_sge_eth_txq_release(struct adapter *adap, struct sge_eth_txq *txq)
 	}
 }
 
+void t4_sge_eth_release_queues(struct port_info *pi)
+{
+	struct adapter *adap = pi->adapter;
+	struct sge_eth_rxq *rxq;
+	struct sge_eth_txq *txq;
+	unsigned int i;
+
+	rxq = &adap->sge.ethrxq[pi->first_qset];
+	/* clean up Ethernet Tx/Rx queues */
+	for (i = 0; i < pi->n_rx_qsets; i++, rxq++) {
+		/* Free only the queues allocated */
+		if (rxq->rspq.desc) {
+			t4_sge_eth_rxq_release(adap, rxq);
+			cxgbe_dma_zone_free(rxq->rspq.eth_dev, "fl_ring", i);
+			cxgbe_dma_zone_free(rxq->rspq.eth_dev, "rx_ring", i);
+			rxq->rspq.eth_dev = NULL;
+		}
+	}
+
+	txq = &adap->sge.ethtxq[pi->first_qset];
+	for (i = 0; i < pi->n_tx_qsets; i++, txq++) {
+		/* Free only the queues allocated */
+		if (txq->q.desc) {
+			t4_sge_eth_txq_release(adap, txq);
+			cxgbe_dma_zone_free(txq->eth_dev, "tx_ring", i);
+			txq->eth_dev = NULL;
+		}
+	}
+}
+
 void t4_sge_tx_monitor_start(struct adapter *adap)
 {
 	rte_eal_alarm_set(50, tx_timer_cb, (void *)adap);
@@ -2281,21 +2314,6 @@ void t4_sge_tx_monitor_stop(struct adapter *adap)
 void t4_free_sge_resources(struct adapter *adap)
 {
 	unsigned int i;
-	struct sge_eth_rxq *rxq = &adap->sge.ethrxq[0];
-	struct sge_eth_txq *txq = &adap->sge.ethtxq[0];
-
-	/* clean up Ethernet Tx/Rx queues */
-	for (i = 0; i < adap->sge.max_ethqsets; i++, rxq++, txq++) {
-		/* Free only the queues allocated */
-		if (rxq->rspq.desc) {
-			t4_sge_eth_rxq_release(adap, rxq);
-			rxq->rspq.eth_dev = NULL;
-		}
-		if (txq->q.desc) {
-			t4_sge_eth_txq_release(adap, txq);
-			txq->eth_dev = NULL;
-		}
-	}
 
 	/* clean up control Tx queues */
 	for (i = 0; i < ARRAY_SIZE(adap->sge.ctrlq); i++) {
@@ -2305,12 +2323,17 @@ void t4_free_sge_resources(struct adapter *adap)
 			reclaim_completed_tx_imm(&cq->q);
 			t4_ctrl_eq_free(adap, adap->mbox, adap->pf, 0,
 					cq->q.cntxt_id);
+			cxgbe_dma_zone_free(adap->eth_dev, "ctrl_tx_ring", i);
+			rte_mempool_free(cq->mb_pool);
 			free_txq(&cq->q);
 		}
 	}
 
-	if (adap->sge.fw_evtq.desc)
+	/* clean up firmware event queue */
+	if (adap->sge.fw_evtq.desc) {
 		free_rspq_fl(adap, &adap->sge.fw_evtq, NULL);
+		cxgbe_dma_zone_free(adap->eth_dev, "fwq_ring", 0);
+	}
 }
 
 /**
diff --git a/dpdk/drivers/net/dpaa/dpaa_ethdev.c b/dpdk/drivers/net/dpaa/dpaa_ethdev.c
index 26805f17b7..4d5946103a 100644
--- a/dpdk/drivers/net/dpaa/dpaa_ethdev.c
+++ b/dpdk/drivers/net/dpaa/dpaa_ethdev.c
@@ -173,8 +173,8 @@ dpaa_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EINVAL;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
-		dev->data->dev_conf.rxmode.offloads &=
+	if (frame_size > DPAA_ETH_MAX_LEN)
+		dev->data->dev_conf.rxmode.offloads |=
 						DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
 		dev->data->dev_conf.rxmode.offloads &=
@@ -881,8 +881,8 @@ dpaa_dev_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	PMD_INIT_FUNC_TRACE();
 
 	if (qman_query_fq_frm_cnt(rxq, &frm_cnt) == 0) {
-		RTE_LOG(DEBUG, PMD, "RX frame count for q(%d) is %u\n",
-			rx_queue_id, frm_cnt);
+		DPAA_PMD_DEBUG("RX frame count for q(%d) is %u",
+			       rx_queue_id, frm_cnt);
 	}
 	return frm_cnt;
 }
@@ -996,8 +996,7 @@ dpaa_dev_add_mac_addr(struct rte_eth_dev *dev,
 	ret = fman_if_add_mac_addr(dpaa_intf->fif, addr->addr_bytes, index);
 
 	if (ret)
-		RTE_LOG(ERR, PMD, "error: Adding the MAC ADDR failed:"
-			" err = %d", ret);
+		DPAA_PMD_ERR("Adding the MAC ADDR failed: err = %d", ret);
 	return 0;
 }
 
@@ -1023,7 +1022,7 @@ dpaa_dev_set_mac_addr(struct rte_eth_dev *dev,
 
 	ret = fman_if_add_mac_addr(dpaa_intf->fif, addr->addr_bytes, 0);
 	if (ret)
-		RTE_LOG(ERR, PMD, "error: Setting the MAC ADDR failed %d", ret);
+		DPAA_PMD_ERR("Setting the MAC ADDR failed %d", ret);
 
 	return ret;
 }
@@ -1121,7 +1120,7 @@ is_dpaa_supported(struct rte_eth_dev *dev)
 }
 
 int
-rte_pmd_dpaa_set_tx_loopback(uint8_t port, uint8_t on)
+rte_pmd_dpaa_set_tx_loopback(uint16_t port, uint8_t on)
 {
 	struct rte_eth_dev *dev;
 	struct dpaa_if *dpaa_intf;
@@ -1306,6 +1305,7 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
 	struct fman_if *fman_intf;
 	struct fman_if_bpool *bp, *tmp_bp;
 	uint32_t cgrid[DPAA_MAX_NUM_PCD_QUEUES];
+	char eth_buf[RTE_ETHER_ADDR_FMT_SIZE];
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1457,15 +1457,9 @@ dpaa_dev_init(struct rte_eth_dev *eth_dev)
 
 	/* copy the primary mac address */
 	rte_ether_addr_copy(&fman_intf->mac_addr, &eth_dev->data->mac_addrs[0]);
+	rte_ether_format_addr(eth_buf, sizeof(eth_buf), &fman_intf->mac_addr);
 
-	RTE_LOG(INFO, PMD, "net: dpaa: %s: %02x:%02x:%02x:%02x:%02x:%02x\n",
-		dpaa_device->name,
-		fman_intf->mac_addr.addr_bytes[0],
-		fman_intf->mac_addr.addr_bytes[1],
-		fman_intf->mac_addr.addr_bytes[2],
-		fman_intf->mac_addr.addr_bytes[3],
-		fman_intf->mac_addr.addr_bytes[4],
-		fman_intf->mac_addr.addr_bytes[5]);
+	DPAA_PMD_INFO("net: dpaa: %s: %s", dpaa_device->name, eth_buf);
 
 	/* Disable RX mode */
 	fman_if_discard_rx_errors(fman_intf);
@@ -1578,8 +1572,7 @@ rte_dpaa_probe(struct rte_dpaa_driver *dpaa_drv __rte_unused,
 
 	if (!is_global_init && (rte_eal_process_type() == RTE_PROC_PRIMARY)) {
 		if (access("/tmp/fmc.bin", F_OK) == -1) {
-			RTE_LOG(INFO, PMD,
-				"* FMC not configured.Enabling default mode\n");
+			DPAA_PMD_INFO("* FMC not configured.Enabling default mode");
 			default_q = 1;
 		}
 
diff --git a/dpdk/drivers/net/dpaa/dpaa_ethdev.h b/dpdk/drivers/net/dpaa/dpaa_ethdev.h
index da06f1faa1..9d27aa34bf 100644
--- a/dpdk/drivers/net/dpaa/dpaa_ethdev.h
+++ b/dpdk/drivers/net/dpaa/dpaa_ethdev.h
@@ -57,6 +57,10 @@
 #define VLAN_TAG_SIZE   4 /** < Vlan Header Length */
 #endif
 
+#define DPAA_ETH_MAX_LEN (RTE_ETHER_MTU + \
+			  RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + \
+			  VLAN_TAG_SIZE)
+
 /* PCD frame queues */
 #define DPAA_PCD_FQID_START		0x400
 #define DPAA_PCD_FQID_MULTIPLIER	0x100
diff --git a/dpdk/drivers/net/dpaa/dpaa_rxtx.c b/dpdk/drivers/net/dpaa/dpaa_rxtx.c
index 5dba1db8b3..3aeecb7d2e 100644
--- a/dpdk/drivers/net/dpaa/dpaa_rxtx.c
+++ b/dpdk/drivers/net/dpaa/dpaa_rxtx.c
@@ -305,7 +305,7 @@ dpaa_eth_sg_to_mbuf(const struct qm_fd *fd, uint32_t ifid)
 	struct qm_sg_entry *sgt, *sg_temp;
 	void *vaddr, *sg_vaddr;
 	int i = 0;
-	uint8_t fd_offset = fd->offset;
+	uint16_t fd_offset = fd->offset;
 
 	vaddr = DPAA_MEMPOOL_PTOV(bp_info, qm_fd_addr(fd));
 	if (!vaddr) {
diff --git a/dpdk/drivers/net/dpaa/rte_pmd_dpaa.h b/dpdk/drivers/net/dpaa/rte_pmd_dpaa.h
index 37eea9b032..ec45633ba2 100644
--- a/dpdk/drivers/net/dpaa/rte_pmd_dpaa.h
+++ b/dpdk/drivers/net/dpaa/rte_pmd_dpaa.h
@@ -15,8 +15,6 @@
  *
  */
 
-#include <rte_ethdev_driver.h>
-
 /**
  * Enable/Disable TX loopback
  *
@@ -31,6 +29,6 @@
  *   - (-EINVAL) if bad parameter.
  */
 int
-rte_pmd_dpaa_set_tx_loopback(uint8_t port, uint8_t on);
+rte_pmd_dpaa_set_tx_loopback(uint16_t port, uint8_t on);
 
 #endif /* _PMD_DPAA_H_ */
diff --git a/dpdk/drivers/net/dpaa2/dpaa2_ethdev.c b/dpdk/drivers/net/dpaa2/dpaa2_ethdev.c
index 2cde55e7cc..5b7529690b 100644
--- a/dpdk/drivers/net/dpaa2/dpaa2_ethdev.c
+++ b/dpdk/drivers/net/dpaa2/dpaa2_ethdev.c
@@ -147,7 +147,7 @@ dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
 	struct dpaa2_dev_priv *priv = dev->data->dev_private;
 	struct fsl_mc_io *dpni = dev->process_private;
-	int ret;
+	int ret = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -155,7 +155,7 @@ dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 		/* VLAN Filter not avaialble */
 		if (!priv->max_vlan_filters) {
 			DPAA2_PMD_INFO("VLAN filter not available");
-			goto next_mask;
+			return -ENOTSUP;
 		}
 
 		if (dev->data->dev_conf.rxmode.offloads &
@@ -168,14 +168,8 @@ dpaa2_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 		if (ret < 0)
 			DPAA2_PMD_INFO("Unable to set vlan filter = %d", ret);
 	}
-next_mask:
-	if (mask & ETH_VLAN_EXTEND_MASK) {
-		if (dev->data->dev_conf.rxmode.offloads &
-			DEV_RX_OFFLOAD_VLAN_EXTEND)
-			DPAA2_PMD_INFO("VLAN extend offload not supported");
-	}
 
-	return 0;
+	return ret;
 }
 
 static int
@@ -255,8 +249,6 @@ dpaa2_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 
 	PMD_INIT_FUNC_TRACE();
 
-	dev_info->if_index = priv->hw_id;
-
 	dev_info->max_mac_addrs = priv->max_mac_filters;
 	dev_info->max_rx_pktlen = DPAA2_MAX_RX_PKT_LEN;
 	dev_info->min_rx_bufsize = DPAA2_MIN_RX_BUF_SIZE;
@@ -553,9 +545,6 @@ dpaa2_eth_dev_configure(struct rte_eth_dev *dev)
 	if (rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
 		dpaa2_vlan_offload_set(dev, ETH_VLAN_FILTER_MASK);
 
-	/* update the current status */
-	dpaa2_dev_link_update(dev, 0);
-
 	return 0;
 }
 
@@ -663,7 +652,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
 						DPNI_CP_CONGESTION_GROUP,
 						DPNI_QUEUE_RX,
 						dpaa2_q->tc_index,
-						flow_id, &taildrop);
+						dpaa2_q->cgid, &taildrop);
 		} else {
 			/*enabling per rx queue congestion control */
 			taildrop.threshold = CONG_THRESHOLD_RX_BYTES_Q;
@@ -690,7 +679,7 @@ dpaa2_dev_rx_queue_setup(struct rte_eth_dev *dev,
 			ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token,
 					DPNI_CP_CONGESTION_GROUP, DPNI_QUEUE_RX,
 					dpaa2_q->tc_index,
-					flow_id, &taildrop);
+					dpaa2_q->cgid, &taildrop);
 		} else {
 			ret = dpni_set_taildrop(dpni, CMD_PRI_LOW, priv->token,
 					DPNI_CP_QUEUE, DPNI_QUEUE_RX,
@@ -1288,7 +1277,7 @@ dpaa2_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	if (mtu < RTE_ETHER_MIN_MTU || frame_size > DPAA2_MAX_RX_PKT_LEN)
 		return -EINVAL;
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > DPAA2_ETH_MAX_LEN)
 		dev->data->dev_conf.rxmode.offloads |=
 						DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
@@ -1757,6 +1746,7 @@ dpaa2_dev_set_link_up(struct rte_eth_dev *dev)
 	/* changing tx burst function to start enqueues */
 	dev->tx_pkt_burst = dpaa2_dev_tx;
 	dev->data->dev_link.link_status = state.up;
+	dev->data->dev_link.link_speed = state.rate;
 
 	if (state.up)
 		DPAA2_PMD_INFO("Port %d Link is Up", dev->data->port_id);
diff --git a/dpdk/drivers/net/dpaa2/dpaa2_ethdev.h b/dpdk/drivers/net/dpaa2/dpaa2_ethdev.h
index 95674b26b9..a4807881fc 100644
--- a/dpdk/drivers/net/dpaa2/dpaa2_ethdev.h
+++ b/dpdk/drivers/net/dpaa2/dpaa2_ethdev.h
@@ -24,6 +24,10 @@
 #define MAX_TX_QUEUES		16
 #define MAX_DPNI		8
 
+#define DPAA2_ETH_MAX_LEN (RTE_ETHER_MTU + \
+			   RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + \
+			   VLAN_TAG_SIZE)
+
 /*default tc to be used for ,congestion, distribution etc configuration. */
 #define DPAA2_DEF_TC		0
 
@@ -135,7 +139,6 @@ struct dpaa2_dev_priv {
 	uint16_t ss_offset;
 	uint64_t ss_iova;
 	uint64_t ss_param_iova;
-#if defined(RTE_LIBRTE_IEEE1588)
 	/*stores timestamp of last received packet on dev*/
 	uint64_t rx_timestamp;
 	/*stores timestamp of last received tx confirmation packet on dev*/
@@ -144,7 +147,6 @@ struct dpaa2_dev_priv {
 	 * it corresponds to last packet transmitted
 	 */
 	struct dpaa2_queue *next_tx_conf_queue;
-#endif
 
 	struct rte_eth_dev *eth_dev; /**< Pointer back to holding ethdev */
 
@@ -200,7 +202,6 @@ void dpaa2_dev_free_eqresp_buf(uint16_t eqresp_ci);
 void dpaa2_flow_clean(struct rte_eth_dev *dev);
 uint16_t dpaa2_dev_tx_conf(void *queue)  __attribute__((unused));
 
-#if defined(RTE_LIBRTE_IEEE1588)
 int dpaa2_timesync_enable(struct rte_eth_dev *dev);
 int dpaa2_timesync_disable(struct rte_eth_dev *dev);
 int dpaa2_timesync_read_time(struct rte_eth_dev *dev,
@@ -213,5 +214,4 @@ int dpaa2_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 						uint32_t flags __rte_unused);
 int dpaa2_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 					  struct timespec *timestamp);
-#endif
 #endif /* _DPAA2_ETHDEV_H */
diff --git a/dpdk/drivers/net/dpaa2/dpaa2_flow.c b/dpdk/drivers/net/dpaa2/dpaa2_flow.c
index 2212650320..8aa65db305 100644
--- a/dpdk/drivers/net/dpaa2/dpaa2_flow.c
+++ b/dpdk/drivers/net/dpaa2/dpaa2_flow.c
@@ -1850,13 +1850,13 @@ struct rte_flow *dpaa2_flow_create(struct rte_eth_dev *dev,
 	key_iova = (size_t)rte_malloc(NULL, 256, 64);
 	if (!key_iova) {
 		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configration\n");
+			"Memory allocation failure for rule configuration\n");
 		goto mem_failure;
 	}
 	mask_iova = (size_t)rte_malloc(NULL, 256, 64);
 	if (!mask_iova) {
 		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configration\n");
+			"Memory allocation failure for rule configuration\n");
 		goto mem_failure;
 	}
 
diff --git a/dpdk/drivers/net/dpaa2/dpaa2_mux.c b/dpdk/drivers/net/dpaa2/dpaa2_mux.c
index 1910cc4184..af90adb828 100644
--- a/dpdk/drivers/net/dpaa2/dpaa2_mux.c
+++ b/dpdk/drivers/net/dpaa2/dpaa2_mux.c
@@ -84,7 +84,7 @@ rte_pmd_dpaa2_mux_flow_create(uint32_t dpdmux_id,
 			   (2 * DIST_PARAM_IOVA_SIZE), RTE_CACHE_LINE_SIZE);
 	if (!flow) {
 		DPAA2_PMD_ERR(
-			"Memory allocation failure for rule configration\n");
+			"Memory allocation failure for rule configuration\n");
 		goto creation_error;
 	}
 	key_iova = (void *)((size_t)flow + sizeof(struct rte_flow));
diff --git a/dpdk/drivers/net/dpaa2/dpaa2_ptp.c b/dpdk/drivers/net/dpaa2/dpaa2_ptp.c
index 316912fe3e..bd9bcd58b0 100644
--- a/dpdk/drivers/net/dpaa2/dpaa2_ptp.c
+++ b/dpdk/drivers/net/dpaa2/dpaa2_ptp.c
@@ -129,6 +129,7 @@ int dpaa2_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 	return 0;
 }
 
+#if defined(RTE_LIBRTE_IEEE1588)
 static int
 dpaa2_create_dprtc_device(int vdev_fd __rte_unused,
 			   struct vfio_device_info *obj_info __rte_unused,
@@ -179,3 +180,4 @@ static struct rte_dpaa2_object rte_dpaa2_dprtc_obj = {
 };
 
 RTE_PMD_REGISTER_DPAA2_OBJECT(dprtc, rte_dpaa2_dprtc_obj);
+#endif
diff --git a/dpdk/drivers/net/dpaa2/meson.build b/dpdk/drivers/net/dpaa2/meson.build
index 571cdb7d4b..fc4707db10 100644
--- a/dpdk/drivers/net/dpaa2/meson.build
+++ b/dpdk/drivers/net/dpaa2/meson.build
@@ -13,15 +13,12 @@ sources = files('base/dpaa2_hw_dpni.c',
 		'dpaa2_flow.c',
 		'dpaa2_rxtx.c',
 		'dpaa2_sparser.c',
+		'dpaa2_ptp.c',
+		'mc/dprtc.c',
 		'mc/dpkg.c',
 		'mc/dpdmux.c',
 		'mc/dpni.c')
 
-if dpdk_conf.has('RTE_LIBRTE_IEEE1588')
-	sources += files('mc/dprtc.c')
-	sources += files('dpaa2_ptp.c')
-endif
-
 includes += include_directories('base', 'mc')
 
 # depends on fslmc bus which uses experimental API
diff --git a/dpdk/drivers/net/e1000/e1000_ethdev.h b/dpdk/drivers/net/e1000/e1000_ethdev.h
index 1e41ae9de1..6b1e599441 100644
--- a/dpdk/drivers/net/e1000/e1000_ethdev.h
+++ b/dpdk/drivers/net/e1000/e1000_ethdev.h
@@ -97,7 +97,7 @@
  */
 #define E1000_ETH_OVERHEAD (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + \
 				VLAN_TAG_SIZE)
-
+#define E1000_ETH_MAX_LEN (RTE_ETHER_MTU + E1000_ETH_OVERHEAD)
 /*
  * Maximum number of Ring Descriptors.
  *
diff --git a/dpdk/drivers/net/e1000/em_ethdev.c b/dpdk/drivers/net/e1000/em_ethdev.c
index 080cbe2df5..4a6e6b8d73 100644
--- a/dpdk/drivers/net/e1000/em_ethdev.c
+++ b/dpdk/drivers/net/e1000/em_ethdev.c
@@ -321,7 +321,7 @@ eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
 	PMD_INIT_FUNC_TRACE();
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return -EPERM;
+		return 0;
 
 	eth_em_close(eth_dev);
 
@@ -1795,8 +1795,7 @@ eth_em_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	if (ret != 0)
 		return ret;
 
-	frame_size = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN +
-		VLAN_TAG_SIZE;
+	frame_size = mtu + E1000_ETH_OVERHEAD;
 
 	/* check that mtu is within the allowed range */
 	if (mtu < RTE_ETHER_MIN_MTU || frame_size > dev_info.max_rx_pktlen)
@@ -1812,7 +1811,7 @@ eth_em_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	rctl = E1000_READ_REG(hw, E1000_RCTL);
 
 	/* switch to jumbo mode if needed */
-	if (frame_size > RTE_ETHER_MAX_LEN) {
+	if (frame_size > E1000_ETH_MAX_LEN) {
 		dev->data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 		rctl |= E1000_RCTL_LPE;
diff --git a/dpdk/drivers/net/e1000/igb_ethdev.c b/dpdk/drivers/net/e1000/igb_ethdev.c
index a3e30dbe5a..a7886041f6 100644
--- a/dpdk/drivers/net/e1000/igb_ethdev.c
+++ b/dpdk/drivers/net/e1000/igb_ethdev.c
@@ -922,7 +922,7 @@ eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
 	PMD_INIT_FUNC_TRACE();
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return -EPERM;
+		return 0;
 
 	eth_igb_close(eth_dev);
 
@@ -1043,7 +1043,7 @@ eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
 	PMD_INIT_FUNC_TRACE();
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return -EPERM;
+		return 0;
 
 	igbvf_dev_close(eth_dev);
 
@@ -3087,6 +3087,7 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 	uint32_t rx_buf_size;
 	uint32_t max_high_water;
 	uint32_t rctl;
+	uint32_t ctrl;
 
 	hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	if (fc_conf->autoneg != hw->mac.autoneg)
@@ -3124,6 +3125,39 @@ eth_igb_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 			rctl &= ~E1000_RCTL_PMCF;
 
 		E1000_WRITE_REG(hw, E1000_RCTL, rctl);
+
+		/*
+		 * check if we want to change flow control mode - driver doesn't have native
+		 * capability to do that, so we'll write the registers ourselves
+		 */
+		ctrl = E1000_READ_REG(hw, E1000_CTRL);
+
+		/*
+		 * set or clear E1000_CTRL_RFCE and E1000_CTRL_TFCE bits depending
+		 * on configuration
+		 */
+		switch (fc_conf->mode) {
+		case RTE_FC_NONE:
+			ctrl &= ~E1000_CTRL_RFCE & ~E1000_CTRL_TFCE;
+			break;
+		case RTE_FC_RX_PAUSE:
+			ctrl |= E1000_CTRL_RFCE;
+			ctrl &= ~E1000_CTRL_TFCE;
+			break;
+		case RTE_FC_TX_PAUSE:
+			ctrl |= E1000_CTRL_TFCE;
+			ctrl &= ~E1000_CTRL_RFCE;
+			break;
+		case RTE_FC_FULL:
+			ctrl |= E1000_CTRL_RFCE | E1000_CTRL_TFCE;
+			break;
+		default:
+			PMD_INIT_LOG(ERR, "invalid flow control mode");
+			return -EINVAL;
+		}
+
+		E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
 		E1000_WRITE_FLUSH(hw);
 
 		return 0;
@@ -4543,7 +4577,7 @@ eth_igb_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	rctl = E1000_READ_REG(hw, E1000_RCTL);
 
 	/* switch to jumbo mode if needed */
-	if (frame_size > RTE_ETHER_MAX_LEN) {
+	if (frame_size > E1000_ETH_MAX_LEN) {
 		dev->data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 		rctl |= E1000_RCTL_LPE;
diff --git a/dpdk/drivers/net/e1000/igb_rxtx.c b/dpdk/drivers/net/e1000/igb_rxtx.c
index 684fa4ad89..5260bbe341 100644
--- a/dpdk/drivers/net/e1000/igb_rxtx.c
+++ b/dpdk/drivers/net/e1000/igb_rxtx.c
@@ -1295,113 +1295,107 @@ igb_tx_done_cleanup(struct igb_tx_queue *txq, uint32_t free_cnt)
 	uint16_t tx_id;    /* Current segment being processed. */
 	uint16_t tx_last;  /* Last segment in the current packet. */
 	uint16_t tx_next;  /* First segment of the next packet. */
-	int count;
+	int count = 0;
 
-	if (txq != NULL) {
-		count = 0;
-		sw_ring = txq->sw_ring;
-		txr = txq->tx_ring;
+	if (!txq)
+		return -ENODEV;
 
-		/*
-		 * tx_tail is the last sent packet on the sw_ring. Goto the end
-		 * of that packet (the last segment in the packet chain) and
-		 * then the next segment will be the start of the oldest segment
-		 * in the sw_ring. This is the first packet that will be
-		 * attempted to be freed.
-		 */
+	sw_ring = txq->sw_ring;
+	txr = txq->tx_ring;
+
+	/* tx_tail is the last sent packet on the sw_ring. Goto the end
+	 * of that packet (the last segment in the packet chain) and
+	 * then the next segment will be the start of the oldest segment
+	 * in the sw_ring. This is the first packet that will be
+	 * attempted to be freed.
+	 */
 
-		/* Get last segment in most recently added packet. */
-		tx_first = sw_ring[txq->tx_tail].last_id;
+	/* Get last segment in most recently added packet. */
+	tx_first = sw_ring[txq->tx_tail].last_id;
 
-		/* Get the next segment, which is the oldest segment in ring. */
-		tx_first = sw_ring[tx_first].next_id;
+	/* Get the next segment, which is the oldest segment in ring. */
+	tx_first = sw_ring[tx_first].next_id;
 
-		/* Set the current index to the first. */
-		tx_id = tx_first;
+	/* Set the current index to the first. */
+	tx_id = tx_first;
 
-		/*
-		 * Loop through each packet. For each packet, verify that an
-		 * mbuf exists and that the last segment is free. If so, free
-		 * it and move on.
-		 */
-		while (1) {
-			tx_last = sw_ring[tx_id].last_id;
-
-			if (sw_ring[tx_last].mbuf) {
-				if (txr[tx_last].wb.status &
-						E1000_TXD_STAT_DD) {
-					/*
-					 * Increment the number of packets
-					 * freed.
-					 */
-					count++;
-
-					/* Get the start of the next packet. */
-					tx_next = sw_ring[tx_last].next_id;
-
-					/*
-					 * Loop through all segments in a
-					 * packet.
-					 */
-					do {
-						rte_pktmbuf_free_seg(sw_ring[tx_id].mbuf);
+	/* Loop through each packet. For each packet, verify that an
+	 * mbuf exists and that the last segment is free. If so, free
+	 * it and move on.
+	 */
+	while (1) {
+		tx_last = sw_ring[tx_id].last_id;
+
+		if (sw_ring[tx_last].mbuf) {
+			if (txr[tx_last].wb.status &
+			    E1000_TXD_STAT_DD) {
+				/* Increment the number of packets
+				 * freed.
+				 */
+				count++;
+
+				/* Get the start of the next packet. */
+				tx_next = sw_ring[tx_last].next_id;
+
+				/* Loop through all segments in a
+				 * packet.
+				 */
+				do {
+					if (sw_ring[tx_id].mbuf) {
+						rte_pktmbuf_free_seg(
+							sw_ring[tx_id].mbuf);
 						sw_ring[tx_id].mbuf = NULL;
 						sw_ring[tx_id].last_id = tx_id;
+					}
 
-						/* Move to next segemnt. */
-						tx_id = sw_ring[tx_id].next_id;
+					/* Move to next segemnt. */
+					tx_id = sw_ring[tx_id].next_id;
 
-					} while (tx_id != tx_next);
+				} while (tx_id != tx_next);
 
-					if (unlikely(count == (int)free_cnt))
-						break;
-				} else
-					/*
-					 * mbuf still in use, nothing left to
-					 * free.
-					 */
+				if (unlikely(count == (int)free_cnt))
 					break;
 			} else {
-				/*
-				 * There are multiple reasons to be here:
-				 * 1) All the packets on the ring have been
-				 *    freed - tx_id is equal to tx_first
-				 *    and some packets have been freed.
-				 *    - Done, exit
-				 * 2) Interfaces has not sent a rings worth of
-				 *    packets yet, so the segment after tail is
-				 *    still empty. Or a previous call to this
-				 *    function freed some of the segments but
-				 *    not all so there is a hole in the list.
-				 *    Hopefully this is a rare case.
-				 *    - Walk the list and find the next mbuf. If
-				 *      there isn't one, then done.
+				/* mbuf still in use, nothing left to
+				 * free.
 				 */
-				if (likely((tx_id == tx_first) && (count != 0)))
-					break;
+				break;
+			}
+		} else {
+			/* There are multiple reasons to be here:
+			 * 1) All the packets on the ring have been
+			 *    freed - tx_id is equal to tx_first
+			 *    and some packets have been freed.
+			 *    - Done, exit
+			 * 2) Interfaces has not sent a rings worth of
+			 *    packets yet, so the segment after tail is
+			 *    still empty. Or a previous call to this
+			 *    function freed some of the segments but
+			 *    not all so there is a hole in the list.
+			 *    Hopefully this is a rare case.
+			 *    - Walk the list and find the next mbuf. If
+			 *      there isn't one, then done.
+			 */
+			if (likely(tx_id == tx_first && count != 0))
+				break;
 
-				/*
-				 * Walk the list and find the next mbuf, if any.
-				 */
-				do {
-					/* Move to next segemnt. */
-					tx_id = sw_ring[tx_id].next_id;
+			/* Walk the list and find the next mbuf, if any. */
+			do {
+				/* Move to next segemnt. */
+				tx_id = sw_ring[tx_id].next_id;
 
-					if (sw_ring[tx_id].mbuf)
-						break;
+				if (sw_ring[tx_id].mbuf)
+					break;
 
-				} while (tx_id != tx_first);
+			} while (tx_id != tx_first);
 
-				/*
-				 * Determine why previous loop bailed. If there
-				 * is not an mbuf, done.
-				 */
-				if (sw_ring[tx_id].mbuf == NULL)
-					break;
-			}
+			/* Determine why previous loop bailed. If there
+			 * is not an mbuf, done.
+			 */
+			if (!sw_ring[tx_id].mbuf)
+				break;
 		}
-	} else
-		count = -ENODEV;
+	}
 
 	return count;
 }
@@ -1637,8 +1631,10 @@ uint64_t
 igb_get_rx_port_offloads_capa(struct rte_eth_dev *dev)
 {
 	uint64_t rx_offload_capa;
+	struct e1000_hw *hw;
+
+	hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
-	RTE_SET_USED(dev);
 	rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP  |
 			  DEV_RX_OFFLOAD_VLAN_FILTER |
 			  DEV_RX_OFFLOAD_IPV4_CKSUM  |
@@ -1649,6 +1645,11 @@ igb_get_rx_port_offloads_capa(struct rte_eth_dev *dev)
 			  DEV_RX_OFFLOAD_SCATTER     |
 			  DEV_RX_OFFLOAD_RSS_HASH;
 
+	if (hw->mac.type == e1000_i350 ||
+	    hw->mac.type == e1000_i210 ||
+	    hw->mac.type == e1000_i211)
+		rx_offload_capa |= DEV_RX_OFFLOAD_VLAN_EXTEND;
+
 	return rx_offload_capa;
 }
 
diff --git a/dpdk/drivers/net/ena/base/ena_com.c b/dpdk/drivers/net/ena/base/ena_com.c
index 8b51660a45..f8e8f448e3 100644
--- a/dpdk/drivers/net/ena/base/ena_com.c
+++ b/dpdk/drivers/net/ena/base/ena_com.c
@@ -401,19 +401,21 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev,
 	size = io_cq->cdesc_entry_size_in_bytes * io_cq->q_depth;
 	io_cq->bus = ena_dev->bus;
 
-	ENA_MEM_ALLOC_COHERENT_NODE(ena_dev->dmadev,
-			size,
-			io_cq->cdesc_addr.virt_addr,
-			io_cq->cdesc_addr.phys_addr,
-			io_cq->cdesc_addr.mem_handle,
-			ctx->numa_node,
-			prev_node);
+	ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(ena_dev->dmadev,
+					    size,
+					    io_cq->cdesc_addr.virt_addr,
+					    io_cq->cdesc_addr.phys_addr,
+					    io_cq->cdesc_addr.mem_handle,
+					    ctx->numa_node,
+					    prev_node,
+					    ENA_CDESC_RING_SIZE_ALIGNMENT);
 	if (!io_cq->cdesc_addr.virt_addr) {
-		ENA_MEM_ALLOC_COHERENT(ena_dev->dmadev,
-				       size,
-				       io_cq->cdesc_addr.virt_addr,
-				       io_cq->cdesc_addr.phys_addr,
-				       io_cq->cdesc_addr.mem_handle);
+		ENA_MEM_ALLOC_COHERENT_ALIGNED(ena_dev->dmadev,
+					       size,
+					       io_cq->cdesc_addr.virt_addr,
+					       io_cq->cdesc_addr.phys_addr,
+					       io_cq->cdesc_addr.mem_handle,
+					       ENA_CDESC_RING_SIZE_ALIGNMENT);
 	}
 
 	if (!io_cq->cdesc_addr.virt_addr) {
@@ -525,11 +527,11 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c
 	timeout = ENA_GET_SYSTEM_TIMEOUT(admin_queue->completion_timeout);
 
 	while (1) {
-                ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags);
-                ena_com_handle_admin_completion(admin_queue);
-                ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags);
+		ENA_SPINLOCK_LOCK(admin_queue->q_lock, flags);
+		ena_com_handle_admin_completion(admin_queue);
+		ENA_SPINLOCK_UNLOCK(admin_queue->q_lock, flags);
 
-                if (comp_ctx->status != ENA_CMD_SUBMITTED)
+		if (comp_ctx->status != ENA_CMD_SUBMITTED)
 			break;
 
 		if (ENA_TIME_EXPIRE(timeout)) {
@@ -1634,9 +1636,11 @@ void ena_com_admin_destroy(struct ena_com_dev *ena_dev)
 	struct ena_com_aenq *aenq = &ena_dev->aenq;
 	u16 size;
 
-	ENA_WAIT_EVENT_DESTROY(admin_queue->comp_ctx->wait_event);
-	if (admin_queue->comp_ctx)
+	if (admin_queue->comp_ctx) {
+		ENA_WAIT_EVENT_DESTROY(admin_queue->comp_ctx->wait_event);
 		ENA_MEM_FREE(ena_dev->dmadev, admin_queue->comp_ctx);
+	}
+
 	admin_queue->comp_ctx = NULL;
 	size = ADMIN_SQ_SIZE(admin_queue->q_depth);
 	if (sq->entries)
@@ -2313,7 +2317,7 @@ int ena_com_set_hash_function(struct ena_com_dev *ena_dev)
 	if (unlikely(ret))
 		return ret;
 
-	if (get_resp.u.flow_hash_func.supported_func & (1 << rss->hash_func)) {
+	if (get_resp.u.flow_hash_func.supported_func & BIT(rss->hash_func)) {
 		ena_trc_err("Func hash %d isn't supported by device, abort\n",
 			    rss->hash_func);
 		return ENA_COM_UNSUPPORTED;
@@ -2356,12 +2360,14 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
 			       enum ena_admin_hash_functions func,
 			       const u8 *key, u16 key_len, u32 init_val)
 {
-	struct ena_rss *rss = &ena_dev->rss;
+	struct ena_admin_feature_rss_flow_hash_control *hash_key;
 	struct ena_admin_get_feat_resp get_resp;
-	struct ena_admin_feature_rss_flow_hash_control *hash_key =
-		rss->hash_key;
+	enum ena_admin_hash_functions old_func;
+	struct ena_rss *rss = &ena_dev->rss;
 	int rc;
 
+	hash_key = rss->hash_key;
+
 	/* Make sure size is a mult of DWs */
 	if (unlikely(key_len & 0x3))
 		return ENA_COM_INVAL;
@@ -2373,7 +2379,7 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
 	if (unlikely(rc))
 		return rc;
 
-	if (!((1 << func) & get_resp.u.flow_hash_func.supported_func)) {
+	if (!(BIT(func) & get_resp.u.flow_hash_func.supported_func)) {
 		ena_trc_err("Flow hash function %d isn't supported\n", func);
 		return ENA_COM_UNSUPPORTED;
 	}
@@ -2398,11 +2404,13 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev,
 		return ENA_COM_INVAL;
 	}
 
+	old_func = rss->hash_func;
+	rss->hash_func = func;
 	rc = ena_com_set_hash_function(ena_dev);
 
 	/* Restore the old function */
 	if (unlikely(rc))
-		ena_com_get_hash_function(ena_dev, NULL, NULL);
+		rss->hash_func = old_func;
 
 	return rc;
 }
@@ -2424,7 +2432,11 @@ int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
 	if (unlikely(rc))
 		return rc;
 
-	rss->hash_func = get_resp.u.flow_hash_func.selected_func;
+	/* ENA_FFS returns 1 in case the lsb is set */
+	rss->hash_func = ENA_FFS(get_resp.u.flow_hash_func.selected_func);
+	if (rss->hash_func)
+		rss->hash_func--;
+
 	if (func)
 		*func = rss->hash_func;
 
diff --git a/dpdk/drivers/net/ena/base/ena_com.h b/dpdk/drivers/net/ena/base/ena_com.h
index ef42bd4f56..fed2dec3e4 100644
--- a/dpdk/drivers/net/ena/base/ena_com.h
+++ b/dpdk/drivers/net/ena/base/ena_com.h
@@ -9,9 +9,9 @@
 #include "ena_plat.h"
 #include "ena_includes.h"
 
-#define ENA_MAX_NUM_IO_QUEUES		128U
+#define ENA_MAX_NUM_IO_QUEUES 128U
 /* We need to queues for each IO (on for Tx and one for Rx) */
-#define ENA_TOTAL_NUM_QUEUES		(2 * (ENA_MAX_NUM_IO_QUEUES))
+#define ENA_TOTAL_NUM_QUEUES (2 * (ENA_MAX_NUM_IO_QUEUES))
 
 #define ENA_MAX_HANDLERS 256
 
@@ -24,6 +24,8 @@
 #define ADMIN_CQ_SIZE(depth)	((depth) * sizeof(struct ena_admin_acq_entry))
 #define ADMIN_AENQ_SIZE(depth)	((depth) * sizeof(struct ena_admin_aenq_entry))
 
+#define ENA_CDESC_RING_SIZE_ALIGNMENT	(1 << 12) /* 4K */
+
 /*****************************************************************************/
 /*****************************************************************************/
 /* ENA adaptive interrupt moderation settings */
@@ -55,9 +57,9 @@
 #define ENA_INTR_MODER_LEVEL_STRIDE			1
 #define ENA_INTR_BYTE_COUNT_NOT_SUPPORTED		0xFFFFFF
 
-#define ENA_HW_HINTS_NO_TIMEOUT				0xFFFF
+#define ENA_HW_HINTS_NO_TIMEOUT 0xFFFF
 
-#define ENA_FEATURE_MAX_QUEUE_EXT_VER	1
+#define ENA_FEATURE_MAX_QUEUE_EXT_VER 1
 
 enum ena_intr_moder_level {
 	ENA_INTR_MODER_LOWEST = 0,
@@ -404,7 +406,7 @@ extern "C" {
  */
 int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev);
 
-/* ena_com_set_mmio_read_mode - Enable/disable the mmio reg read mechanism
+/* ena_com_set_mmio_read_mode - Enable/disable the indirect mmio reg read mechanism
  * @ena_dev: ENA communication layer struct
  * @readless_supported: readless mode (enable/disable)
  */
@@ -527,7 +529,7 @@ bool ena_com_get_ena_admin_polling_mode(struct ena_com_dev *ena_dev);
 /* ena_com_admin_q_comp_intr_handler - admin queue interrupt handler
  * @ena_dev: ENA communication layer struct
  *
- * This method go over the admin completion queue and wake up all the pending
+ * This method goes over the admin completion queue and wakes up all the pending
  * threads that wait on the commands wait event.
  *
  * @note: Should be called after MSI-X interrupt.
@@ -537,7 +539,7 @@ void ena_com_admin_q_comp_intr_handler(struct ena_com_dev *ena_dev);
 /* ena_com_aenq_intr_handler - AENQ interrupt handler
  * @ena_dev: ENA communication layer struct
  *
- * This method go over the async event notification queue and call the proper
+ * This method goes over the async event notification queue and calls the proper
  * aenq handler.
  */
 void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data);
@@ -554,14 +556,14 @@ void ena_com_abort_admin_commands(struct ena_com_dev *ena_dev);
 /* ena_com_wait_for_abort_completion - Wait for admin commands abort.
  * @ena_dev: ENA communication layer struct
  *
- * This method wait until all the outstanding admin commands will be completed.
+ * This method waits until all the outstanding admin commands are completed.
  */
 void ena_com_wait_for_abort_completion(struct ena_com_dev *ena_dev);
 
 /* ena_com_validate_version - Validate the device parameters
  * @ena_dev: ENA communication layer struct
  *
- * This method validate the device parameters are the same as the saved
+ * This method verifies the device parameters are the same as the saved
  * parameters in ena_dev.
  * This method is useful after device reset, to validate the device mac address
  * and the device offloads are the same as before the reset.
@@ -763,7 +765,7 @@ int ena_com_set_hash_ctrl(struct ena_com_dev *ena_dev);
  *
  * Retrieve the hash control from the device.
  *
- * @note, If the caller called ena_com_fill_hash_ctrl but didn't flash
+ * @note: If the caller called ena_com_fill_hash_ctrl but didn't flash
  * it to the device, the new configuration will be lost.
  *
  * @return: 0 on Success and negative value otherwise.
@@ -815,7 +817,7 @@ int ena_com_indirect_table_set(struct ena_com_dev *ena_dev);
  *
  * Retrieve the RSS indirection table from the device.
  *
- * @note: If the caller called ena_com_indirect_table_fill_entry but didn't flash
+ * @note: If the caller called ena_com_indirect_table_fill_entry but didn't flush
  * it to the device, the new configuration will be lost.
  *
  * @return: 0 on Success and negative value otherwise.
@@ -841,14 +843,14 @@ int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev,
 /* ena_com_delete_debug_area - Free the debug area resources.
  * @ena_dev: ENA communication layer struct
  *
- * Free the allocate debug area.
+ * Free the allocated debug area.
  */
 void ena_com_delete_debug_area(struct ena_com_dev *ena_dev);
 
 /* ena_com_delete_host_info - Free the host info resources.
  * @ena_dev: ENA communication layer struct
  *
- * Free the allocate host info.
+ * Free the allocated host info.
  */
 void ena_com_delete_host_info(struct ena_com_dev *ena_dev);
 
@@ -889,9 +891,9 @@ int ena_com_destroy_io_cq(struct ena_com_dev *ena_dev,
  * @cmd_completion: command completion return value.
  * @cmd_comp_size: command completion size.
 
- * Submit an admin command and then wait until the device will return a
+ * Submit an admin command and then wait until the device returns a
  * completion.
- * The completion will be copyed into cmd_comp.
+ * The completion will be copied into cmd_comp.
  *
  * @return - 0 on success, negative value on failure.
  */
@@ -1083,7 +1085,7 @@ static inline void ena_com_calculate_interrupt_delay(struct ena_com_dev *ena_dev
  * @intr_reg: interrupt register to update.
  * @rx_delay_interval: Rx interval in usecs
  * @tx_delay_interval: Tx interval in usecs
- * @unmask: unask enable/disable
+ * @unmask: unmask enable/disable
  *
  * Prepare interrupt update register with the supplied parameters.
  */
diff --git a/dpdk/drivers/net/ena/base/ena_plat_dpdk.h b/dpdk/drivers/net/ena/base/ena_plat_dpdk.h
index 9e1492cac4..9773be09e7 100644
--- a/dpdk/drivers/net/ena/base/ena_plat_dpdk.h
+++ b/dpdk/drivers/net/ena/base/ena_plat_dpdk.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright (c) 2015-2019 Amazon.com, Inc. or its affiliates.
+ * Copyright (c) 2015-2020 Amazon.com, Inc. or its affiliates.
  * All rights reserved.
  */
 
@@ -55,8 +55,8 @@ typedef uint64_t dma_addr_t;
 
 #define ENA_ABORT() abort()
 
-#define ENA_MSLEEP(x) rte_delay_ms(x)
-#define ENA_UDELAY(x) rte_delay_us(x)
+#define ENA_MSLEEP(x) rte_delay_us_sleep(x * 1000)
+#define ENA_UDELAY(x) rte_delay_us_block(x)
 
 #define ENA_TOUCH(x) ((void)(x))
 #define memcpy_toio memcpy
@@ -71,26 +71,15 @@ typedef uint64_t dma_addr_t;
 	(rte_get_timer_cycles() * US_PER_S / rte_get_timer_hz())
 
 extern int ena_logtype_com;
-#if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
-#define ENA_ASSERT(cond, format, arg...)				\
-	do {								\
-		if (unlikely(!(cond))) {				\
-			rte_log(RTE_LOGTYPE_ERR, ena_logtype_com,	\
-				format, ##arg);				\
-			rte_panic("line %d\tassert \"" #cond "\""	\
-					"failed\n", __LINE__);		\
-		}							\
-	} while (0)
-#else
-#define ENA_ASSERT(cond, format, arg...) do {} while (0)
-#endif
 
-#define ENA_MAX32(x, y) RTE_MAX((x), (y))
-#define ENA_MAX16(x, y) RTE_MAX((x), (y))
-#define ENA_MAX8(x, y) RTE_MAX((x), (y))
-#define ENA_MIN32(x, y) RTE_MIN((x), (y))
-#define ENA_MIN16(x, y) RTE_MIN((x), (y))
-#define ENA_MIN8(x, y) RTE_MIN((x), (y))
+#define ENA_MAX_T(type, x, y) RTE_MAX((type)(x), (type)(y))
+#define ENA_MAX32(x, y) ENA_MAX_T(uint32_t, (x), (y))
+#define ENA_MAX16(x, y) ENA_MAX_T(uint16_t, (x), (y))
+#define ENA_MAX8(x, y) ENA_MAX_T(uint8_t, (x), (y))
+#define ENA_MIN_T(type, x, y) RTE_MIN((type)(x), (type)(y))
+#define ENA_MIN32(x, y) ENA_MIN_T(uint32_t, (x), (y))
+#define ENA_MIN16(x, y) ENA_MIN_T(uint16_t, (x), (y))
+#define ENA_MIN8(x, y) ENA_MIN_T(uint8_t, (x), (y))
 
 #define BITS_PER_LONG_LONG (__SIZEOF_LONG_LONG__ * 8)
 #define U64_C(x) x ## ULL
@@ -178,18 +167,24 @@ do {                                                                   \
  * Each rte_memzone should have unique name.
  * To satisfy it, count number of allocations and add it to name.
  */
-extern uint32_t ena_alloc_cnt;
+extern rte_atomic32_t ena_alloc_cnt;
 
-#define ENA_MEM_ALLOC_COHERENT(dmadev, size, virt, phys, handle)	\
+#define ENA_MEM_ALLOC_COHERENT_ALIGNED(					\
+	dmadev, size, virt, phys, handle, alignment)			\
 	do {								\
-		const struct rte_memzone *mz;				\
-		char z_name[RTE_MEMZONE_NAMESIZE];			\
+		const struct rte_memzone *mz = NULL;			\
 		ENA_TOUCH(dmadev); ENA_TOUCH(handle);			\
-		snprintf(z_name, sizeof(z_name),			\
-				"ena_alloc_%d", ena_alloc_cnt++);	\
-		mz = rte_memzone_reserve(z_name, size, SOCKET_ID_ANY,	\
-				RTE_MEMZONE_IOVA_CONTIG);		\
-		handle = mz;						\
+		if (size > 0) {						\
+			char z_name[RTE_MEMZONE_NAMESIZE];		\
+			snprintf(z_name, sizeof(z_name),		\
+			 "ena_alloc_%d",				\
+			 rte_atomic32_add_return(&ena_alloc_cnt, 1));	\
+			mz = rte_memzone_reserve_aligned(z_name, size,	\
+					SOCKET_ID_ANY,			\
+					RTE_MEMZONE_IOVA_CONTIG,	\
+					alignment);			\
+			handle = mz;					\
+		}							\
 		if (mz == NULL) {					\
 			virt = NULL;					\
 			phys = 0;					\
@@ -199,22 +194,33 @@ extern uint32_t ena_alloc_cnt;
 			phys = mz->iova;				\
 		}							\
 	} while (0)
+#define ENA_MEM_ALLOC_COHERENT(dmadev, size, virt, phys, handle)	\
+		ENA_MEM_ALLOC_COHERENT_ALIGNED(				\
+			dmadev,						\
+			size,						\
+			virt,						\
+			phys,						\
+			handle,						\
+			RTE_CACHE_LINE_SIZE)
 #define ENA_MEM_FREE_COHERENT(dmadev, size, virt, phys, handle) 	\
 		({ ENA_TOUCH(size); ENA_TOUCH(phys);			\
 		   ENA_TOUCH(dmadev);					\
 		   rte_memzone_free(handle); })
 
-#define ENA_MEM_ALLOC_COHERENT_NODE(					\
-	dmadev, size, virt, phys, mem_handle, node, dev_node)		\
+#define ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(				\
+	dmadev, size, virt, phys, mem_handle, node, dev_node, alignment) \
 	do {								\
-		const struct rte_memzone *mz;				\
-		char z_name[RTE_MEMZONE_NAMESIZE];			\
+		const struct rte_memzone *mz = NULL;			\
 		ENA_TOUCH(dmadev); ENA_TOUCH(dev_node);			\
-		snprintf(z_name, sizeof(z_name),			\
-				"ena_alloc_%d", ena_alloc_cnt++);	\
-		mz = rte_memzone_reserve(z_name, size, node,		\
-				RTE_MEMZONE_IOVA_CONTIG);		\
-		mem_handle = mz;					\
+		if (size > 0) {						\
+			char z_name[RTE_MEMZONE_NAMESIZE];		\
+			snprintf(z_name, sizeof(z_name),		\
+			 "ena_alloc_%d",				\
+			 rte_atomic32_add_return(&ena_alloc_cnt, 1));   \
+			mz = rte_memzone_reserve_aligned(z_name, size, node, \
+				RTE_MEMZONE_IOVA_CONTIG, alignment);	\
+			mem_handle = mz;				\
+		}							\
 		if (mz == NULL) {					\
 			virt = NULL;					\
 			phys = 0;					\
@@ -224,7 +230,17 @@ extern uint32_t ena_alloc_cnt;
 			phys = mz->iova;				\
 		}							\
 	} while (0)
-
+#define ENA_MEM_ALLOC_COHERENT_NODE(					\
+	dmadev, size, virt, phys, mem_handle, node, dev_node)		\
+		ENA_MEM_ALLOC_COHERENT_NODE_ALIGNED(			\
+			dmadev,						\
+			size,						\
+			virt,						\
+			phys,						\
+			mem_handle,					\
+			node,						\
+			dev_node,					\
+			RTE_CACHE_LINE_SIZE)
 #define ENA_MEM_ALLOC_NODE(dmadev, size, virt, node, dev_node) \
 	do {								\
 		ENA_TOUCH(dmadev); ENA_TOUCH(dev_node);			\
@@ -290,4 +306,6 @@ extern uint32_t ena_alloc_cnt;
 
 #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
 
+#define ENA_FFS(x) ffs(x)
+
 #endif /* DPDK_ENA_COM_ENA_PLAT_DPDK_H_ */
diff --git a/dpdk/drivers/net/ena/ena_ethdev.c b/dpdk/drivers/net/ena/ena_ethdev.c
index 8bbd80dfb3..d098387a8c 100644
--- a/dpdk/drivers/net/ena/ena_ethdev.c
+++ b/dpdk/drivers/net/ena/ena_ethdev.c
@@ -89,7 +89,7 @@ struct ena_stats {
  * Each rte_memzone should have unique name.
  * To satisfy it, count number of allocation and add it to name.
  */
-uint32_t ena_alloc_cnt;
+rte_atomic32_t ena_alloc_cnt;
 
 static const struct ena_stats ena_stats_global_strings[] = {
 	ENA_STAT_GLOBAL_ENTRY(wd_expired),
@@ -267,21 +267,23 @@ static inline void ena_rx_mbuf_prepare(struct rte_mbuf *mbuf,
 	else if (ena_rx_ctx->l4_proto == ENA_ETH_IO_L4_PROTO_UDP)
 		packet_type |= RTE_PTYPE_L4_UDP;
 
-	if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV4)
+	if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV4) {
 		packet_type |= RTE_PTYPE_L3_IPV4;
-	else if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV6)
+		if (unlikely(ena_rx_ctx->l3_csum_err))
+			ol_flags |= PKT_RX_IP_CKSUM_BAD;
+		else
+			ol_flags |= PKT_RX_IP_CKSUM_GOOD;
+	} else if (ena_rx_ctx->l3_proto == ENA_ETH_IO_L3_PROTO_IPV6) {
 		packet_type |= RTE_PTYPE_L3_IPV6;
+	}
 
-	if (!ena_rx_ctx->l4_csum_checked)
+	if (!ena_rx_ctx->l4_csum_checked || ena_rx_ctx->frag)
 		ol_flags |= PKT_RX_L4_CKSUM_UNKNOWN;
 	else
-		if (unlikely(ena_rx_ctx->l4_csum_err) && !ena_rx_ctx->frag)
+		if (unlikely(ena_rx_ctx->l4_csum_err))
 			ol_flags |= PKT_RX_L4_CKSUM_BAD;
 		else
-			ol_flags |= PKT_RX_L4_CKSUM_UNKNOWN;
-
-	if (unlikely(ena_rx_ctx->l3_csum_err))
-		ol_flags |= PKT_RX_IP_CKSUM_BAD;
+			ol_flags |= PKT_RX_L4_CKSUM_GOOD;
 
 	mbuf->ol_flags = ol_flags;
 	mbuf->packet_type = packet_type;
@@ -1079,16 +1081,15 @@ static int ena_create_io_queue(struct ena_ring *ring)
 		ena_qid = ENA_IO_TXQ_IDX(ring->id);
 		ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_TX;
 		ctx.mem_queue_type = ena_dev->tx_mem_queue_type;
-		ctx.queue_size = adapter->tx_ring_size;
 		for (i = 0; i < ring->ring_size; i++)
 			ring->empty_tx_reqs[i] = i;
 	} else {
 		ena_qid = ENA_IO_RXQ_IDX(ring->id);
 		ctx.direction = ENA_COM_IO_QUEUE_DIRECTION_RX;
-		ctx.queue_size = adapter->rx_ring_size;
 		for (i = 0; i < ring->ring_size; i++)
 			ring->empty_rx_reqs[i] = i;
 	}
+	ctx.queue_size = ring->ring_size;
 	ctx.qid = ena_qid;
 	ctx.msix_vector = -1; /* interrupts not used */
 	ctx.numa_node = ring->numa_socket_id;
@@ -1181,6 +1182,10 @@ static int ena_queue_start(struct ena_ring *ring)
 		PMD_INIT_LOG(ERR, "Failed to populate rx ring !");
 		return ENA_COM_FAULT;
 	}
+	/* Flush per-core RX buffers pools cache as they can be used on other
+	 * cores as well.
+	 */
+	rte_mempool_cache_flush(NULL, ring->mb_pool);
 
 	return 0;
 }
@@ -1675,7 +1680,7 @@ static int eth_ena_dev_init(struct rte_eth_dev *eth_dev)
 	int rc;
 
 	static int adapters_found;
-	bool wd_state;
+	bool wd_state = false;
 
 	eth_dev->dev_ops = &ena_dev_ops;
 	eth_dev->rx_pkt_burst = &eth_ena_recv_pkts;
@@ -2480,7 +2485,7 @@ static int ena_xstats_get(struct rte_eth_dev *dev,
 		return 0;
 
 	for (stat = 0; stat < ENA_STATS_ARRAY_GLOBAL; stat++, count++) {
-		stat_offset = ena_stats_rx_strings[stat].stat_offset;
+		stat_offset = ena_stats_global_strings[stat].stat_offset;
 		stats_begin = &adapter->dev_stats;
 
 		xstats[count].id = count;
diff --git a/dpdk/drivers/net/enetc/base/enetc_hw.h b/dpdk/drivers/net/enetc/base/enetc_hw.h
index 2fe7ccb5bb..00813284ee 100644
--- a/dpdk/drivers/net/enetc/base/enetc_hw.h
+++ b/dpdk/drivers/net/enetc/base/enetc_hw.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2019 NXP
+ * Copyright 2018-2020 NXP
  */
 
 #ifndef _ENETC_HW_H_
@@ -86,6 +86,7 @@ enum enetc_bdr_type {TX, RX};
 #define ENETC_PSIPMAR1(n)		(0x00104 + (n) * 0x20)
 #define ENETC_PCAPR0			0x00900
 #define ENETC_PCAPR1			0x00904
+#define ENETC_PM0_RX_FIFO		0x801C
 #define ENETC_PM0_IF_MODE		0x8300
 #define ENETC_PM1_IF_MODE		0x9300
 #define ENETC_PMO_IFM_RG		BIT(2)
diff --git a/dpdk/drivers/net/enetc/enetc.h b/dpdk/drivers/net/enetc/enetc.h
index 8c830a5c06..6a2c4c68e5 100644
--- a/dpdk/drivers/net/enetc/enetc.h
+++ b/dpdk/drivers/net/enetc/enetc.h
@@ -29,6 +29,10 @@
 /* maximum frame size supported */
 #define ENETC_MAC_MAXFRM_SIZE	9600
 
+/* The max frame size with default MTU */
+#define ENETC_ETH_MAX_LEN (RTE_ETHER_MTU + \
+		RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
+
 /*
  * upper_32_bits - return bits 32-63 of a number
  * @n: the number we're accessing
diff --git a/dpdk/drivers/net/enetc/enetc_ethdev.c b/dpdk/drivers/net/enetc/enetc_ethdev.c
index 20b77c006c..4f3e61cfdc 100644
--- a/dpdk/drivers/net/enetc/enetc_ethdev.c
+++ b/dpdk/drivers/net/enetc/enetc_ethdev.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright 2018-2019 NXP
+ * Copyright 2018-2020 NXP
  */
 
 #include <stdbool.h>
@@ -147,6 +147,9 @@ enetc_hardware_init(struct enetc_eth_hw *hw)
 	hw->hw.port = (void *)((size_t)hw->hw.reg + ENETC_PORT_BASE);
 	hw->hw.global = (void *)((size_t)hw->hw.reg + ENETC_GLOBAL_BASE);
 
+	/* WA for Rx lock-up HW erratum */
+	enetc_port_wr(enetc_hw, ENETC_PM0_RX_FIFO, 1);
+
 	/* Enabling Station Interface */
 	enetc_wr(enetc_hw, ENETC_SIMR, ENETC_SIMR_EN);
 
@@ -658,7 +661,7 @@ enetc_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EINVAL;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > ENETC_ETH_MAX_LEN)
 		dev->data->dev_conf.rxmode.offloads &=
 						DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
diff --git a/dpdk/drivers/net/enic/enic_ethdev.c b/dpdk/drivers/net/enic/enic_ethdev.c
index a7a178e41b..2733ac73a1 100644
--- a/dpdk/drivers/net/enic/enic_ethdev.c
+++ b/dpdk/drivers/net/enic/enic_ethdev.c
@@ -374,18 +374,6 @@ static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 			enic->ig_vlan_strip_en = 0;
 	}
 
-	if ((mask & ETH_VLAN_FILTER_MASK) &&
-	    (offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) {
-		dev_warning(enic,
-			"Configuration of VLAN filter is not supported\n");
-	}
-
-	if ((mask & ETH_VLAN_EXTEND_MASK) &&
-	    (offloads & DEV_RX_OFFLOAD_VLAN_EXTEND)) {
-		dev_warning(enic,
-			"Configuration of extended VLAN is not supported\n");
-	}
-
 	return enic_set_vlan_strip(enic);
 }
 
diff --git a/dpdk/drivers/net/enic/enic_flow.c b/dpdk/drivers/net/enic/enic_flow.c
index 6cd3640174..a845dd4b41 100644
--- a/dpdk/drivers/net/enic/enic_flow.c
+++ b/dpdk/drivers/net/enic/enic_flow.c
@@ -1389,7 +1389,7 @@ enic_dump_filter(const struct filter_v2 *filt)
 
 		if (gp->mask_flags & FILTER_GENERIC_1_IPV6)
 			sprintf(ip6, "%s ",
-				(gp->val_flags & FILTER_GENERIC_1_IPV4)
+				(gp->val_flags & FILTER_GENERIC_1_IPV6)
 				 ? "ip6(y)" : "ip6(n)");
 		else
 			sprintf(ip6, "%s ", "ip6(x)");
@@ -1595,6 +1595,8 @@ enic_flow_parse(struct rte_eth_dev *dev,
 		return -rte_errno;
 	}
 	enic_filter->type = enic->flow_filter_mode;
+	if (enic->adv_filters)
+		enic_filter->type = FILTER_DPDK_1;
 	ret = enic_copy_filter(pattern, enic_filter_cap, enic,
 				       enic_filter, error);
 	return ret;
diff --git a/dpdk/drivers/net/enic/enic_fm_flow.c b/dpdk/drivers/net/enic/enic_fm_flow.c
index e3e3d737bc..e87988f48b 100644
--- a/dpdk/drivers/net/enic/enic_fm_flow.c
+++ b/dpdk/drivers/net/enic/enic_fm_flow.c
@@ -312,8 +312,8 @@ enic_fm_copy_item_eth(struct copy_item_args *arg)
 	fm_mask = &entry->ftm_mask.fk_hdrset[lvl];
 	fm_data->fk_header_select |= FKH_ETHER;
 	fm_mask->fk_header_select |= FKH_ETHER;
-	memcpy(&fm_data->l2.eth, spec, sizeof(*spec));
-	memcpy(&fm_mask->l2.eth, mask, sizeof(*mask));
+	memcpy(&fm_data->l2.eth, spec, sizeof(struct rte_ether_hdr));
+	memcpy(&fm_mask->l2.eth, mask, sizeof(struct rte_ether_hdr));
 	return 0;
 }
 
@@ -349,8 +349,11 @@ enic_fm_copy_item_vlan(struct copy_item_args *arg)
 	eth_mask = (void *)&fm_mask->l2.eth;
 	eth_val = (void *)&fm_data->l2.eth;
 
-	/* Outer TPID cannot be matched */
-	if (eth_mask->ether_type)
+	/*
+	 * Outer TPID cannot be matched. If inner_type is 0, use what is
+	 * in the eth header.
+	 */
+	if (eth_mask->ether_type && mask->inner_type)
 		return -ENOTSUP;
 
 	/*
@@ -358,8 +361,10 @@ enic_fm_copy_item_vlan(struct copy_item_args *arg)
 	 * L2, regardless of vlan stripping settings. So, the inner type
 	 * from vlan becomes the ether type of the eth header.
 	 */
-	eth_mask->ether_type = mask->inner_type;
-	eth_val->ether_type = spec->inner_type;
+	if (mask->inner_type) {
+		eth_mask->ether_type = mask->inner_type;
+		eth_val->ether_type = spec->inner_type;
+	}
 	fm_data->fk_header_select |= FKH_ETHER | FKH_QTAG;
 	fm_mask->fk_header_select |= FKH_ETHER | FKH_QTAG;
 	fm_data->fk_vlan = rte_be_to_cpu_16(spec->tci);
@@ -418,8 +423,8 @@ enic_fm_copy_item_ipv6(struct copy_item_args *arg)
 
 	fm_data->fk_header_select |= FKH_IPV6;
 	fm_mask->fk_header_select |= FKH_IPV6;
-	memcpy(&fm_data->l3.ip6, spec, sizeof(*spec));
-	memcpy(&fm_mask->l3.ip6, mask, sizeof(*mask));
+	memcpy(&fm_data->l3.ip6, spec, sizeof(struct rte_ipv6_hdr));
+	memcpy(&fm_mask->l3.ip6, mask, sizeof(struct rte_ipv6_hdr));
 	return 0;
 }
 
@@ -869,46 +874,36 @@ enic_fm_append_action_op(struct enic_flowman *fm,
 	return 0;
 }
 
-/* Steer operations need to appear before other ops */
+/* NIC requires that 1st steer appear before decap.
+ * Correct example: steer, decap, steer, steer, ...
+ */
 static void
 enic_fm_reorder_action_op(struct enic_flowman *fm)
 {
-	struct fm_action_op *dst, *dst_head, *src, *src_head;
+	struct fm_action_op *op, *steer, *decap;
+	struct fm_action_op tmp_op;
 
 	ENICPMD_FUNC_TRACE();
-	/* Move steer ops to the front. */
-	src = fm->action.fma_action_ops;
-	src_head = src;
-	dst = fm->action_tmp.fma_action_ops;
-	dst_head = dst;
-	/* Copy steer ops to tmp */
-	while (src->fa_op != FMOP_END) {
-		if (src->fa_op == FMOP_RQ_STEER) {
-			ENICPMD_LOG(DEBUG, "move op: %ld -> dst %ld",
-				    (long)(src - src_head),
-				    (long)(dst - dst_head));
-			*dst = *src;
-			dst++;
-		}
-		src++;
-	}
-	/* Then append non-steer ops */
-	src = src_head;
-	while (src->fa_op != FMOP_END) {
-		if (src->fa_op != FMOP_RQ_STEER) {
-			ENICPMD_LOG(DEBUG, "move op: %ld -> dst %ld",
-				    (long)(src - src_head),
-				    (long)(dst - dst_head));
-			*dst = *src;
-			dst++;
-		}
-		src++;
+	/* Find 1st steer and decap */
+	op = fm->action.fma_action_ops;
+	steer = NULL;
+	decap = NULL;
+	while (op->fa_op != FMOP_END) {
+		if (!decap && op->fa_op == FMOP_DECAP_NOSTRIP)
+			decap = op;
+		else if (!steer && op->fa_op == FMOP_RQ_STEER)
+			steer = op;
+		op++;
+	}
+	/* If decap is before steer, swap */
+	if (steer && decap && decap < steer) {
+		op = fm->action.fma_action_ops;
+		ENICPMD_LOG(DEBUG, "swap decap %ld <-> steer %ld",
+			    (long)(decap - op), (long)(steer - op));
+		tmp_op = *decap;
+		*decap = *steer;
+		*steer = tmp_op;
 	}
-	/* Copy END */
-	*dst = *src;
-	/* Finally replace the original action with the reordered one */
-	memcpy(fm->action.fma_action_ops, fm->action_tmp.fma_action_ops,
-	       sizeof(fm->action.fma_action_ops));
 }
 
 /* VXLAN decap is done via flowman compound action */
@@ -934,6 +929,17 @@ enic_fm_copy_vxlan_decap(struct enic_flowman *fm,
 	return enic_fm_append_action_op(fm, &fm_op, error);
 }
 
+/* Generate a reasonable source port number */
+static uint16_t
+gen_src_port(void)
+{
+	/* Min/max below are the default values in OVS-DPDK and Linux */
+	uint16_t p = rte_rand();
+	p = RTE_MAX(p, 32768);
+	p = RTE_MIN(p, 61000);
+	return rte_cpu_to_be_16(p);
+}
+
 /* VXLAN encap is done via flowman compound action */
 static int
 enic_fm_copy_vxlan_encap(struct enic_flowman *fm,
@@ -942,6 +948,7 @@ enic_fm_copy_vxlan_encap(struct enic_flowman *fm,
 {
 	struct fm_action_op fm_op;
 	struct rte_ether_hdr *eth;
+	struct rte_udp_hdr *udp;
 	uint16_t *ethertype;
 	void *template;
 	uint8_t off;
@@ -963,7 +970,7 @@ enic_fm_copy_vxlan_encap(struct enic_flowman *fm,
 	eth = (struct rte_ether_hdr *)template;
 	ethertype = &eth->ether_type;
 	append_template(&template, &off, item->spec,
-			sizeof(struct rte_flow_item_eth));
+			sizeof(struct rte_ether_hdr));
 	item++;
 	flow_item_skip_void(&item);
 	/* Optional VLAN */
@@ -1040,8 +1047,17 @@ enic_fm_copy_vxlan_encap(struct enic_flowman *fm,
 		off + offsetof(struct rte_udp_hdr, dgram_len);
 	fm_op.encap.len2_delta =
 		sizeof(struct rte_udp_hdr) + sizeof(struct rte_vxlan_hdr);
+	udp = (struct rte_udp_hdr *)template;
 	append_template(&template, &off, item->spec,
 			sizeof(struct rte_udp_hdr));
+	/*
+	 * Firmware does not hash/fill source port yet. Generate a
+	 * random port, as there is *usually* one rte_flow for the
+	 * given inner packet stream (i.e. a single stream has one
+	 * random port).
+	 */
+	if (udp->src_port == 0)
+		udp->src_port = gen_src_port();
 	item++;
 	flow_item_skip_void(&item);
 
@@ -1099,6 +1115,7 @@ enic_fm_copy_action(struct enic_flowman *fm,
 		PASSTHRU = 1 << 2,
 		COUNT = 1 << 3,
 		ENCAP = 1 << 4,
+		DECAP = 1 << 5,
 	};
 	struct fm_tcam_match_entry *fmt;
 	struct fm_action_op fm_op;
@@ -1281,6 +1298,10 @@ enic_fm_copy_action(struct enic_flowman *fm,
 			break;
 		}
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: {
+			if (overlap & DECAP)
+				goto unsupported;
+			overlap |= DECAP;
+
 			ret = enic_fm_copy_vxlan_decap(fm, fmt, actions,
 				error);
 			if (ret != 0)
diff --git a/dpdk/drivers/net/failsafe/failsafe.c b/dpdk/drivers/net/failsafe/failsafe.c
index 8af31d71b3..72362f35de 100644
--- a/dpdk/drivers/net/failsafe/failsafe.c
+++ b/dpdk/drivers/net/failsafe/failsafe.c
@@ -190,6 +190,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev)
 	}
 	priv = PRIV(dev);
 	priv->data = dev->data;
+	priv->rxp = FS_RX_PROXY_INIT;
 	dev->dev_ops = &failsafe_ops;
 	dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0];
 	dev->data->dev_link = eth_link;
diff --git a/dpdk/drivers/net/failsafe/failsafe_ether.c b/dpdk/drivers/net/failsafe/failsafe_ether.c
index 93deacd134..98fbdefc50 100644
--- a/dpdk/drivers/net/failsafe/failsafe_ether.c
+++ b/dpdk/drivers/net/failsafe/failsafe_ether.c
@@ -322,10 +322,10 @@ fs_dev_stats_save(struct sub_device *sdev)
 	if (err) {
 		uint64_t timestamp = sdev->stats_snapshot.timestamp;
 
-		WARN("Could not access latest statistics from sub-device %d.\n",
+		WARN("Could not access latest statistics from sub-device %d.",
 			 SUB_ID(sdev));
 		if (timestamp != 0)
-			WARN("Using latest snapshot taken before %"PRIu64" seconds.\n",
+			WARN("Using latest snapshot taken before %"PRIu64" seconds.",
 				 (rte_rdtsc() - timestamp) / rte_get_tsc_hz());
 	}
 	failsafe_stats_increment
@@ -383,14 +383,23 @@ failsafe_dev_remove(struct rte_eth_dev *dev)
 	struct sub_device *sdev;
 	uint8_t i;
 
-	FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE)
-		if (sdev->remove && fs_rxtx_clean(sdev)) {
-			if (fs_lock(dev, 1) != 0)
-				return;
+	FOREACH_SUBDEV(sdev, i, dev) {
+		if (!sdev->remove)
+			continue;
+
+		/* Active devices must have finished their burst and
+		 * their stats must be saved.
+		 */
+		if (sdev->state >= DEV_ACTIVE &&
+		    fs_rxtx_clean(sdev) == 0)
+			continue;
+		if (fs_lock(dev, 1) != 0)
+			return;
+		if (sdev->state >= DEV_ACTIVE)
 			fs_dev_stats_save(sdev);
-			fs_dev_remove(sdev);
-			fs_unlock(dev, 1);
-		}
+		fs_dev_remove(sdev);
+		fs_unlock(dev, 1);
+	}
 }
 
 static int
diff --git a/dpdk/drivers/net/failsafe/failsafe_intr.c b/dpdk/drivers/net/failsafe/failsafe_intr.c
index 0f34c5bbac..bb5b089b31 100644
--- a/dpdk/drivers/net/failsafe/failsafe_intr.c
+++ b/dpdk/drivers/net/failsafe/failsafe_intr.c
@@ -394,7 +394,7 @@ fs_rx_event_proxy_uninstall(struct fs_priv *priv)
 		free(priv->rxp.evec);
 		priv->rxp.evec = NULL;
 	}
-	if (priv->rxp.efd > 0) {
+	if (priv->rxp.efd >= 0) {
 		close(priv->rxp.efd);
 		priv->rxp.efd = -1;
 	}
diff --git a/dpdk/drivers/net/failsafe/failsafe_ops.c b/dpdk/drivers/net/failsafe/failsafe_ops.c
index a87e49b97d..96f7e456f9 100644
--- a/dpdk/drivers/net/failsafe/failsafe_ops.c
+++ b/dpdk/drivers/net/failsafe/failsafe_ops.c
@@ -380,7 +380,7 @@ fs_rx_queue_release(void *queue)
 	rxq = queue;
 	dev = &rte_eth_devices[rxq->priv->data->port_id];
 	fs_lock(dev, 0);
-	if (rxq->event_fd > 0)
+	if (rxq->event_fd >= 0)
 		close(rxq->event_fd);
 	FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) {
 		if (ETH(sdev)->data->rx_queues != NULL &&
@@ -1068,6 +1068,15 @@ fs_dev_merge_info(struct rte_eth_dev_info *info,
 	info->rx_queue_offload_capa &= sinfo->rx_queue_offload_capa;
 	info->tx_queue_offload_capa &= sinfo->tx_queue_offload_capa;
 	info->flow_type_rss_offloads &= sinfo->flow_type_rss_offloads;
+
+	/*
+	 * RETA size is a GCD of RETA sizes indicated by sub-devices.
+	 * Each of these sizes is a power of 2, so use the lower one.
+	 */
+	info->reta_size = RTE_MIN(info->reta_size, sinfo->reta_size);
+
+	info->hash_key_size = RTE_MIN(info->hash_key_size,
+				      sinfo->hash_key_size);
 }
 
 /**
@@ -1117,6 +1126,8 @@ fs_dev_infos_get(struct rte_eth_dev *dev,
 	infos->max_hash_mac_addrs = UINT32_MAX;
 	infos->max_vfs = UINT16_MAX;
 	infos->max_vmdq_pools = UINT16_MAX;
+	infos->reta_size = UINT16_MAX;
+	infos->hash_key_size = UINT8_MAX;
 
 	/*
 	 * Set of capabilities that can be verified upon
diff --git a/dpdk/drivers/net/failsafe/failsafe_private.h b/dpdk/drivers/net/failsafe/failsafe_private.h
index 8e9706aef0..651578a128 100644
--- a/dpdk/drivers/net/failsafe/failsafe_private.h
+++ b/dpdk/drivers/net/failsafe/failsafe_private.h
@@ -58,6 +58,14 @@ struct rx_proxy {
 	enum rxp_service_state sstate;
 };
 
+#define FS_RX_PROXY_INIT (struct rx_proxy){ \
+	.efd = -1, \
+	.evec = NULL, \
+	.sid = 0, \
+	.scid = 0, \
+	.sstate = SS_NO_SERVICE, \
+}
+
 struct rxq {
 	struct fs_priv *priv;
 	uint16_t qid;
diff --git a/dpdk/drivers/net/fm10k/Makefile b/dpdk/drivers/net/fm10k/Makefile
index 722bf1ee04..338de40f23 100644
--- a/dpdk/drivers/net/fm10k/Makefile
+++ b/dpdk/drivers/net/fm10k/Makefile
@@ -73,6 +73,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_common.c
 SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_mbx.c
 SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_vf.c
 SRCS-$(CONFIG_RTE_LIBRTE_FM10K_PMD) += fm10k_api.c
+ifeq ($(CONFIG_RTE_ARCH_X86), y)
 SRCS-$(CONFIG_RTE_LIBRTE_FM10K_INC_VECTOR) += fm10k_rxtx_vec.c
+endif
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/dpdk/drivers/net/fm10k/fm10k_ethdev.c b/dpdk/drivers/net/fm10k/fm10k_ethdev.c
index 407baa16c3..7a83b6f68e 100644
--- a/dpdk/drivers/net/fm10k/fm10k_ethdev.c
+++ b/dpdk/drivers/net/fm10k/fm10k_ethdev.c
@@ -1575,28 +1575,9 @@ fm10k_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 }
 
 static int
-fm10k_vlan_offload_set(struct rte_eth_dev *dev, int mask)
+fm10k_vlan_offload_set(struct rte_eth_dev *dev __rte_unused,
+		       int mask __rte_unused)
 {
-	if (mask & ETH_VLAN_STRIP_MASK) {
-		if (!(dev->data->dev_conf.rxmode.offloads &
-			DEV_RX_OFFLOAD_VLAN_STRIP))
-			PMD_INIT_LOG(ERR, "VLAN stripping is "
-					"always on in fm10k");
-	}
-
-	if (mask & ETH_VLAN_EXTEND_MASK) {
-		if (dev->data->dev_conf.rxmode.offloads &
-			DEV_RX_OFFLOAD_VLAN_EXTEND)
-			PMD_INIT_LOG(ERR, "VLAN QinQ is not "
-					"supported in fm10k");
-	}
-
-	if (mask & ETH_VLAN_FILTER_MASK) {
-		if (!(dev->data->dev_conf.rxmode.offloads &
-			DEV_RX_OFFLOAD_VLAN_FILTER))
-			PMD_INIT_LOG(ERR, "VLAN filter is always on in fm10k");
-	}
-
 	return 0;
 }
 
@@ -1873,9 +1854,10 @@ fm10k_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
 	q->tail_ptr = (volatile uint32_t *)
 		&((uint32_t *)hw->hw_addr)[FM10K_RDT(queue_id)];
 	q->offloads = offloads;
-	if (handle_rxconf(q, conf))
+	if (handle_rxconf(q, conf)) {
+		rte_free(q);
 		return -EINVAL;
-
+	}
 	/* allocate memory for the software ring */
 	q->sw_ring = rte_zmalloc_socket("fm10k sw ring",
 			(nb_desc + q->nb_fake_desc) * sizeof(struct rte_mbuf *),
@@ -2055,8 +2037,10 @@ fm10k_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_id,
 	q->ops = &def_txq_ops;
 	q->tail_ptr = (volatile uint32_t *)
 		&((uint32_t *)hw->hw_addr)[FM10K_TDT(queue_id)];
-	if (handle_txconf(q, conf))
+	if (handle_txconf(q, conf)) {
+		rte_free(q);
 		return -EINVAL;
+	}
 
 	/* allocate memory for the software ring */
 	q->sw_ring = rte_zmalloc_socket("fm10k sw ring",
diff --git a/dpdk/drivers/net/fm10k/fm10k_rxtx.c b/dpdk/drivers/net/fm10k/fm10k_rxtx.c
index 5c31121839..4accaa2cd6 100644
--- a/dpdk/drivers/net/fm10k/fm10k_rxtx.c
+++ b/dpdk/drivers/net/fm10k/fm10k_rxtx.c
@@ -611,6 +611,8 @@ static inline void tx_xmit_pkt(struct fm10k_tx_queue *q, struct rte_mbuf *mb)
 	/* set vlan if requested */
 	if (mb->ol_flags & PKT_TX_VLAN_PKT)
 		q->hw_ring[q->next_free].vlan = mb->vlan_tci;
+	else
+		q->hw_ring[q->next_free].vlan = 0;
 
 	q->sw_ring[q->next_free] = mb;
 	q->hw_ring[q->next_free].buffer_addr =
diff --git a/dpdk/drivers/net/fm10k/fm10k_rxtx_vec.c b/dpdk/drivers/net/fm10k/fm10k_rxtx_vec.c
index d76dfd16fd..1194251396 100644
--- a/dpdk/drivers/net/fm10k/fm10k_rxtx_vec.c
+++ b/dpdk/drivers/net/fm10k/fm10k_rxtx_vec.c
@@ -645,18 +645,15 @@ fm10k_reassemble_packets(struct fm10k_rx_queue *rxq,
 	return pkt_idx;
 }
 
-/*
- * vPMD receive routine that reassembles scattered packets
+/**
+ * vPMD receive routine that reassembles single burst of 32 scattered packets
  *
  * Notice:
  * - don't support ol_flags for rss and csum err
- * - nb_pkts > RTE_FM10K_MAX_RX_BURST, only scan RTE_FM10K_MAX_RX_BURST
- *   numbers of DD bit
  */
-uint16_t
-fm10k_recv_scattered_pkts_vec(void *rx_queue,
-				struct rte_mbuf **rx_pkts,
-				uint16_t nb_pkts)
+static uint16_t
+fm10k_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			       uint16_t nb_pkts)
 {
 	struct fm10k_rx_queue *rxq = rx_queue;
 	uint8_t split_flags[RTE_FM10K_MAX_RX_BURST] = {0};
@@ -691,6 +688,32 @@ fm10k_recv_scattered_pkts_vec(void *rx_queue,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+fm10k_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > RTE_FM10K_MAX_RX_BURST) {
+		uint16_t burst;
+
+		burst = fm10k_recv_scattered_burst_vec(rx_queue,
+						       rx_pkts + retval,
+						       RTE_FM10K_MAX_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < RTE_FM10K_MAX_RX_BURST)
+			return retval;
+	}
+
+	return retval + fm10k_recv_scattered_burst_vec(rx_queue,
+						       rx_pkts + retval,
+						       nb_pkts);
+}
+
 static const struct fm10k_txq_ops vec_txq_ops = {
 	.reset = fm10k_reset_tx_queue,
 };
diff --git a/dpdk/drivers/net/hinic/base/hinic_compat.h b/dpdk/drivers/net/hinic/base/hinic_compat.h
index e4a7f12d15..473a273b6b 100644
--- a/dpdk/drivers/net/hinic/base/hinic_compat.h
+++ b/dpdk/drivers/net/hinic/base/hinic_compat.h
@@ -150,22 +150,25 @@ static inline int hinic_test_and_set_bit(int nr, volatile unsigned long *addr)
 }
 
 void *dma_zalloc_coherent(void *dev, size_t size, dma_addr_t *dma_handle,
-			  gfp_t flag);
-void *dma_zalloc_coherent_aligned(void *dev, size_t size,
-				dma_addr_t *dma_handle, gfp_t flag);
-void *dma_zalloc_coherent_aligned256k(void *dev, size_t size,
-				dma_addr_t *dma_handle, gfp_t flag);
+			  unsigned int socket_id);
+
+void *dma_zalloc_coherent_aligned(void *hwdev, size_t size,
+		dma_addr_t *dma_handle, unsigned int socket_id);
+
+void *dma_zalloc_coherent_aligned256k(void *hwdev, size_t size,
+			      dma_addr_t *dma_handle, unsigned int socket_id);
+
 void dma_free_coherent(void *dev, size_t size, void *virt, dma_addr_t phys);
 
 /* dma pool alloc and free */
 #define	pci_pool dma_pool
-#define	pci_pool_alloc(pool, flags, handle) dma_pool_alloc(pool, flags, handle)
+#define	pci_pool_alloc(pool, handle) dma_pool_alloc(pool, handle)
 #define	pci_pool_free(pool, vaddr, addr) dma_pool_free(pool, vaddr, addr)
 
 struct dma_pool *dma_pool_create(const char *name, void *dev, size_t size,
 				size_t align, size_t boundary);
 void dma_pool_destroy(struct dma_pool *pool);
-void *dma_pool_alloc(struct pci_pool *pool, int flags, dma_addr_t *dma_addr);
+void *dma_pool_alloc(struct pci_pool *pool, dma_addr_t *dma_addr);
 void dma_pool_free(struct pci_pool *pool, void *vaddr, dma_addr_t dma);
 
 #define kzalloc(size, flag) rte_zmalloc(NULL, size, HINIC_MEM_ALLOC_ALIGN_MIN)
@@ -195,16 +198,23 @@ static inline u32 readl(const volatile void *addr)
 #define spin_lock(spinlock_prt)		rte_spinlock_lock(spinlock_prt)
 #define spin_unlock(spinlock_prt)	rte_spinlock_unlock(spinlock_prt)
 
-static inline unsigned long get_timeofday_ms(void)
+#ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
+#define CLOCK_TYPE CLOCK_MONOTONIC_RAW
+#else
+#define CLOCK_TYPE CLOCK_MONOTONIC
+#endif
+
+static inline unsigned long clock_gettime_ms(void)
 {
-	struct timeval tv;
+	struct timespec tv;
 
-	(void)gettimeofday(&tv, NULL);
+	(void)clock_gettime(CLOCK_TYPE, &tv);
 
-	return (unsigned long)tv.tv_sec * 1000 + tv.tv_usec / 1000;
+	return (unsigned long)tv.tv_sec * 1000 +
+	       (unsigned long)tv.tv_nsec / 1000000;
 }
 
-#define jiffies	get_timeofday_ms()
+#define jiffies	clock_gettime_ms()
 #define msecs_to_jiffies(ms)	(ms)
 #define time_before(now, end)	((now) < (end))
 
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_api_cmd.c b/dpdk/drivers/net/hinic/base/hinic_pmd_api_cmd.c
index dbffc2e3b0..b72edc0652 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_api_cmd.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_api_cmd.c
@@ -658,7 +658,7 @@ static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain,
 
 	cmd_vaddr_alloc = dma_zalloc_coherent(dev, (API_CMD_BUF_SIZE +
 					      API_PAYLOAD_ALIGN_SIZE),
-					      &cmd_paddr, GFP_KERNEL);
+					      &cmd_paddr, SOCKET_ID_ANY);
 	if (!cmd_vaddr_alloc) {
 		PMD_DRV_LOG(ERR, "Allocate API CMD dma memory failed");
 		return -ENOMEM;
@@ -712,7 +712,7 @@ static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain,
 
 	node_vaddr_alloc = dma_zalloc_coherent(dev, (chain->cell_size +
 					       API_CMD_NODE_ALIGN_SIZE),
-					       &node_paddr, GFP_KERNEL);
+					       &node_paddr, SOCKET_ID_ANY);
 	if (!node_vaddr_alloc) {
 		PMD_DRV_LOG(ERR, "Allocate dma API CMD cell failed");
 		return -ENOMEM;
@@ -889,8 +889,7 @@ static int api_chain_init(struct hinic_api_cmd_chain *chain,
 
 	chain->wb_status = (struct hinic_api_cmd_status *)
 			   dma_zalloc_coherent(dev, sizeof(*chain->wb_status),
-					       &chain->wb_status_paddr,
-					       GFP_KERNEL);
+				&chain->wb_status_paddr, SOCKET_ID_ANY);
 	if (!chain->wb_status) {
 		PMD_DRV_LOG(ERR, "Allocate DMA wb status failed");
 		err = -ENOMEM;
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.c b/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.c
index aa883e0274..d0270738ae 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.c
@@ -112,6 +112,7 @@ static void hinic_parse_pub_res_cap(struct service_cap *cap,
 	cap->host_id = dev_cap->host_id;
 	cap->ep_id = dev_cap->ep_id;
 	cap->max_cos_id = dev_cap->max_cos_id;
+	cap->valid_cos_bitmap = dev_cap->valid_cos_bitmap;
 	cap->er_id = dev_cap->er_id;
 	cap->port_id = dev_cap->port_id;
 
@@ -134,9 +135,11 @@ static void hinic_parse_pub_res_cap(struct service_cap *cap,
 	cap->host_oq_id_mask_val = dev_cap->host_oq_id_mask_val;
 
 	PMD_DRV_LOG(INFO, "Get public resource capability:");
-	PMD_DRV_LOG(INFO, "host_id: 0x%x, ep_id: 0x%x, intr_type: 0x%x, max_cos_id: 0x%x, er_id: 0x%x, port_id: 0x%x",
+	PMD_DRV_LOG(INFO, "host_id: 0x%x, ep_id: 0x%x, intr_type: 0x%x, "
+		    "max_cos_id: 0x%x, cos_bitmap: 0x%x, er_id: 0x%x, port_id: 0x%x",
 		    cap->host_id, cap->ep_id, cap->intr_chip_en,
-		    cap->max_cos_id, cap->er_id, cap->port_id);
+		    cap->max_cos_id, cap->valid_cos_bitmap, cap->er_id,
+		    cap->port_id);
 	PMD_DRV_LOG(INFO, "host_total_function: 0x%x, host_oq_id_mask_val: 0x%x, max_vf: 0x%x",
 		    cap->host_total_function, cap->host_oq_id_mask_val,
 		    cap->max_vf);
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.h b/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.h
index 1741ca44a4..6e76e1d232 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_cfg.h
@@ -54,6 +54,7 @@ struct service_cap {
 	u8 ep_id;
 	u8 intr_chip_en;
 	u8 max_cos_id;	/* PF/VF's max cos id */
+	u8 valid_cos_bitmap;
 	u8 er_id;	/* PF/VF's ER */
 	u8 port_id;	/* PF/VF's physical port */
 	u8 max_vf;	/* max VF number that PF supported */
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.c b/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.c
index eb8de24d6e..1816636c34 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.c
@@ -7,6 +7,7 @@
 #include "hinic_pmd_hwif.h"
 #include "hinic_pmd_wq.h"
 #include "hinic_pmd_mgmt.h"
+#include "hinic_pmd_mbox.h"
 #include "hinic_pmd_cmdq.h"
 
 #define CMDQ_CMD_TIMEOUT				5000 /* millisecond */
@@ -171,8 +172,7 @@ struct hinic_cmd_buf *hinic_alloc_cmd_buf(void *hwdev)
 		return NULL;
 	}
 
-	cmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, GFP_KERNEL,
-				      &cmd_buf->dma_addr);
+	cmd_buf->buf = pci_pool_alloc(cmdqs->cmd_buf_pool, &cmd_buf->dma_addr);
 	if (!cmd_buf->buf) {
 		PMD_DRV_LOG(ERR, "Allocate cmd from the pool failed");
 		goto alloc_pci_buf_err;
@@ -426,25 +426,35 @@ static int hinic_set_cmdq_ctxts(struct hinic_hwdev *hwdev)
 {
 	struct hinic_cmdqs *cmdqs = hwdev->cmdqs;
 	struct hinic_cmdq_ctxt *cmdq_ctxt;
+	struct hinic_cmdq_ctxt cmdq_ctxt_out;
 	enum hinic_cmdq_type cmdq_type;
+	u16 out_size = sizeof(cmdq_ctxt_out);
 	u16 in_size;
 	int err;
 
 	cmdq_type = HINIC_CMDQ_SYNC;
+	memset(&cmdq_ctxt_out, 0, out_size);
 	for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
 		cmdq_ctxt = &cmdqs->cmdq[cmdq_type].cmdq_ctxt;
 		cmdq_ctxt->resp_aeq_num = HINIC_AEQ1;
 		in_size = sizeof(*cmdq_ctxt);
 		err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
 					     HINIC_MGMT_CMD_CMDQ_CTXT_SET,
-					     cmdq_ctxt, in_size, NULL,
-					     NULL, 0);
-		if (err) {
-			PMD_DRV_LOG(ERR, "Set cmdq ctxt failed");
-			return -EFAULT;
+					     cmdq_ctxt, in_size, &cmdq_ctxt_out,
+					     &out_size, 0);
+		if (err || !out_size || cmdq_ctxt_out.status) {
+			if (err == HINIC_MBOX_PF_BUSY_ACTIVE_FW ||
+				err == HINIC_DEV_BUSY_ACTIVE_FW) {
+				cmdqs->status |= HINIC_CMDQ_SET_FAIL;
+				PMD_DRV_LOG(ERR, "PF or VF fw is hot active");
+			}
+			PMD_DRV_LOG(ERR, "Set cmdq ctxt failed, err: %d, status: 0x%x, out_size: 0x%x",
+				err, cmdq_ctxt_out.status, out_size);
+			return -EIO;
 		}
 	}
 
+	cmdqs->status &= ~HINIC_CMDQ_SET_FAIL;
 	cmdqs->status |= HINIC_CMDQ_ENABLE;
 
 	return 0;
@@ -625,6 +635,8 @@ static void hinic_cmdqs_free(struct hinic_hwdev *hwdev)
 static int hinic_set_cmdq_depth(struct hinic_hwdev *hwdev, u16 cmdq_depth)
 {
 	struct hinic_root_ctxt root_ctxt;
+	u16 out_size = sizeof(root_ctxt);
+	int err;
 
 	memset(&root_ctxt, 0, sizeof(root_ctxt));
 	root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
@@ -632,10 +644,17 @@ static int hinic_set_cmdq_depth(struct hinic_hwdev *hwdev, u16 cmdq_depth)
 	root_ctxt.ppf_idx = hinic_ppf_idx(hwdev);
 	root_ctxt.set_cmdq_depth = 1;
 	root_ctxt.cmdq_depth = (u8)ilog2(cmdq_depth);
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
-				      HINIC_MGMT_CMD_VAT_SET,
-				      &root_ctxt, sizeof(root_ctxt),
-				      NULL, NULL, 0);
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+				     HINIC_MGMT_CMD_VAT_SET,
+				     &root_ctxt, sizeof(root_ctxt),
+				     &root_ctxt, &out_size, 0);
+	if (err || !out_size || root_ctxt.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Set cmdq depth failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, root_ctxt.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 int hinic_comm_cmdqs_init(struct hinic_hwdev *hwdev)
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.h b/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.h
index da939e16fa..4ce0a4c5b8 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_cmdq.h
@@ -170,6 +170,7 @@ struct hinic_cmdq_ctxt {
 
 enum hinic_cmdq_status {
 	HINIC_CMDQ_ENABLE = BIT(0),
+	HINIC_CMDQ_SET_FAIL = BIT(1)
 };
 
 enum hinic_cmdq_cmd_type {
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.c b/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.c
index abe0daee6c..fecb653401 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.c
@@ -240,7 +240,7 @@ static int alloc_eq_pages(struct hinic_eq *eq)
 		eq->virt_addr[pg_num] =
 			(u8 *)dma_zalloc_coherent_aligned(eq->hwdev,
 					eq->page_size, &eq->dma_addr[pg_num],
-					GFP_KERNEL);
+					SOCKET_ID_ANY);
 		if (!eq->virt_addr[pg_num]) {
 			err = -ENOMEM;
 			goto dma_alloc_err;
@@ -470,10 +470,10 @@ int hinic_comm_aeqs_init(struct hinic_hwdev *hwdev)
 	struct irq_info aeq_irqs[HINIC_MAX_AEQS];
 
 	num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
-	if (num_aeqs < HINIC_MAX_AEQS) {
-		PMD_DRV_LOG(ERR, "Warning: PMD need %d AEQs, Chip have %d",
-			HINIC_MAX_AEQS, num_aeqs);
-		return HINIC_ERROR;
+	if (num_aeqs < HINIC_MIN_AEQS) {
+		PMD_DRV_LOG(ERR, "PMD need %d AEQs, Chip has %d\n",
+				HINIC_MIN_AEQS, num_aeqs);
+		return -EINVAL;
 	}
 
 	memset(aeq_irqs, 0, sizeof(aeq_irqs));
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.h b/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.h
index 16046ecde3..5e6dc3914b 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_eqs.h
@@ -9,6 +9,10 @@
 
 #define HINIC_AEQN_START		0
 #define HINIC_MAX_AEQS			4
+#define HINIC_MIN_AEQS			2
+#define HINIC_AEQN_0			0
+#define HINIC_AEQN_1			1
+#define HINIC_AEQN_2			2
 
 #define HINIC_EQ_MAX_PAGES		8
 
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.c b/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.c
index 8b16897ade..8a0faa6975 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.c
@@ -112,9 +112,9 @@ void hinic_be32_to_cpu(void *data, u32 len)
 	}
 }
 
-static void *
-hinic_dma_mem_zalloc(struct hinic_hwdev *hwdev, size_t size,
-		dma_addr_t *dma_handle, unsigned int flag, unsigned int align)
+static void *hinic_dma_mem_zalloc(struct hinic_hwdev *hwdev, size_t size,
+			   dma_addr_t *dma_handle, unsigned int align,
+			   unsigned int socket_id)
 {
 	int rc, alloc_cnt;
 	const struct rte_memzone *mz;
@@ -129,8 +129,8 @@ hinic_dma_mem_zalloc(struct hinic_hwdev *hwdev, size_t size,
 	snprintf(z_name, sizeof(z_name), "%s_%d",
 		 hwdev->pcidev_hdl->name, alloc_cnt);
 
-	mz = rte_memzone_reserve_aligned(z_name, size, SOCKET_ID_ANY,
-					 flag, align);
+	mz = rte_memzone_reserve_aligned(z_name, size, socket_id,
+					 RTE_MEMZONE_IOVA_CONTIG, align);
 	if (!mz) {
 		PMD_DRV_LOG(ERR, "Alloc dma able memory failed, errno: %d, ma_name: %s, size: 0x%zx",
 			    rte_errno, z_name, size);
@@ -209,25 +209,26 @@ hinic_dma_mem_free(struct hinic_hwdev *hwdev, size_t size,
 	(void)rte_memzone_free(mz);
 }
 
-void *dma_zalloc_coherent(void *hwdev, size_t size,
-			  dma_addr_t *dma_handle, gfp_t flag)
+void *dma_zalloc_coherent(void *hwdev, size_t size, dma_addr_t *dma_handle,
+			  unsigned int socket_id)
 {
-	return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag,
-				    RTE_CACHE_LINE_SIZE);
+	return hinic_dma_mem_zalloc(hwdev, size, dma_handle,
+				    RTE_CACHE_LINE_SIZE, socket_id);
 }
 
 void *dma_zalloc_coherent_aligned(void *hwdev, size_t size,
-				  dma_addr_t *dma_handle, gfp_t flag)
+				dma_addr_t *dma_handle, unsigned int socket_id)
 {
-	return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag,
-				    HINIC_PAGE_SIZE);
+	return hinic_dma_mem_zalloc(hwdev, size, dma_handle, HINIC_PAGE_SIZE,
+				    socket_id);
 }
 
 void *dma_zalloc_coherent_aligned256k(void *hwdev, size_t size,
-				      dma_addr_t *dma_handle, gfp_t flag)
+				      dma_addr_t *dma_handle,
+				      unsigned int socket_id)
 {
-	return hinic_dma_mem_zalloc(hwdev, size, dma_handle, flag,
-				    HINIC_PAGE_SIZE * 64);
+	return hinic_dma_mem_zalloc(hwdev, size, dma_handle,
+				    HINIC_PAGE_SIZE * 64, socket_id);
 }
 
 void dma_free_coherent(void *hwdev, size_t size, void *virt, dma_addr_t phys)
@@ -304,12 +305,12 @@ void dma_pool_destroy(struct dma_pool *pool)
 	rte_free(pool);
 }
 
-void *dma_pool_alloc(struct pci_pool *pool, int flags, dma_addr_t *dma_addr)
+void *dma_pool_alloc(struct pci_pool *pool, dma_addr_t *dma_addr)
 {
 	void *buf;
 
-	buf = hinic_dma_mem_zalloc(pool->hwdev, pool->elem_size,
-				   dma_addr, flags, (u32)pool->align);
+	buf = hinic_dma_mem_zalloc(pool->hwdev, pool->elem_size, dma_addr,
+				(u32)pool->align, SOCKET_ID_ANY);
 	if (buf)
 		rte_atomic32_inc(&pool->inuse);
 
@@ -389,6 +390,8 @@ void hinic_osdep_deinit(struct hinic_hwdev *hwdev)
 int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr)
 {
 	struct hinic_cons_idx_attr cons_idx_attr;
+	u16 out_size = sizeof(cons_idx_attr);
+	int err;
 
 	memset(&cons_idx_attr, 0, sizeof(cons_idx_attr));
 	cons_idx_attr.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
@@ -405,10 +408,17 @@ int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr)
 	cons_idx_attr.sq_id = q_id;
 	cons_idx_attr.ci_addr = attr->ci_dma_base;
 
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
 				      HINIC_MGMT_CMD_L2NIC_SQ_CI_ATTR_SET,
 				      &cons_idx_attr, sizeof(cons_idx_attr),
-				      NULL, NULL, 0);
+				      &cons_idx_attr, &out_size, 0);
+	if (err || !out_size || cons_idx_attr.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Set ci attribute table failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, cons_idx_attr.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /**
@@ -421,7 +431,9 @@ int hinic_set_ci_table(void *hwdev, u16 q_id, struct hinic_sq_attr *attr)
  */
 int hinic_set_pagesize(void *hwdev, u8 page_size)
 {
-	struct hinic_page_size cmd;
+	struct hinic_page_size page_size_info;
+	u16 out_size = sizeof(page_size_info);
+	int err;
 
 	if (page_size > HINIC_PAGE_SIZE_MAX) {
 		PMD_DRV_LOG(ERR, "Invalid page_size %u, bigger than %u",
@@ -429,16 +441,23 @@ int hinic_set_pagesize(void *hwdev, u8 page_size)
 		return -EINVAL;
 	}
 
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
-	cmd.func_idx = hinic_global_func_id(hwdev);
-	cmd.ppf_idx = hinic_ppf_idx(hwdev);
-	cmd.page_size = page_size;
+	memset(&page_size_info, 0, sizeof(page_size_info));
+	page_size_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+	page_size_info.func_idx = hinic_global_func_id(hwdev);
+	page_size_info.ppf_idx = hinic_ppf_idx(hwdev);
+	page_size_info.page_size = page_size;
 
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
-					HINIC_MGMT_CMD_PAGESIZE_SET,
-					&cmd, sizeof(cmd),
-					NULL, NULL, 0);
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+				     HINIC_MGMT_CMD_PAGESIZE_SET,
+				     &page_size_info, sizeof(page_size_info),
+				     &page_size_info, &out_size, 0);
+	if (err || !out_size || page_size_info.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Set wq page size failed, err: %d, status: 0x%x, out_size: 0x%0x",
+			err, page_size_info.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 static int wait_for_flr_finish(struct hinic_hwif *hwif)
@@ -528,7 +547,7 @@ static int hinic_vf_rx_tx_flush(struct hinic_hwdev *hwdev)
 
 	err = hinic_reinit_cmdq_ctxts(hwdev);
 	if (err)
-		PMD_DRV_LOG(WARNING, "Reinit cmdq failed");
+		PMD_DRV_LOG(WARNING, "Reinit cmdq failed when vf flush");
 
 	return err;
 }
@@ -545,7 +564,9 @@ static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
 	struct hinic_hwif *hwif = hwdev->hwif;
 	struct hinic_clear_doorbell clear_db;
 	struct hinic_clear_resource clr_res;
+	u16 out_size;
 	int err;
+	int ret = 0;
 
 	rte_delay_ms(100);
 
@@ -556,15 +577,19 @@ static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
 	}
 
 	hinic_disable_doorbell(hwif);
+	out_size = sizeof(clear_db);
 	memset(&clear_db, 0, sizeof(clear_db));
 	clear_db.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
 	clear_db.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
 	clear_db.ppf_idx  = HINIC_HWIF_PPF_IDX(hwif);
 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
 				     HINIC_MGMT_CMD_FLUSH_DOORBELL, &clear_db,
-				     sizeof(clear_db), NULL, NULL, 0);
-	if (err)
-		PMD_DRV_LOG(WARNING, "Flush doorbell failed");
+				     sizeof(clear_db), &clear_db, &out_size, 0);
+	if (err || !out_size || clear_db.mgmt_msg_head.status) {
+		PMD_DRV_LOG(WARNING, "Flush doorbell failed, err: %d, status: 0x%x, out_size: 0x%x",
+			 err, clear_db.mgmt_msg_head.status, out_size);
+		ret = err ? err : (-EIO);
+	}
 
 	hinic_set_pf_status(hwif, HINIC_PF_STATUS_FLR_START_FLAG);
 	memset(&clr_res, 0, sizeof(clr_res));
@@ -574,21 +599,28 @@ static int hinic_pf_rx_tx_flush(struct hinic_hwdev *hwdev)
 
 	err = hinic_msg_to_mgmt_no_ack(hwdev, HINIC_MOD_COMM,
 				       HINIC_MGMT_CMD_START_FLR, &clr_res,
-				       sizeof(clr_res), NULL, NULL);
-	if (err)
-		PMD_DRV_LOG(WARNING, "Notice flush message failed");
+				       sizeof(clr_res));
+	if (err) {
+		PMD_DRV_LOG(WARNING, "Notice flush msg failed, err: %d", err);
+		ret = err;
+	}
 
 	err = wait_for_flr_finish(hwif);
-	if (err)
-		PMD_DRV_LOG(WARNING, "Wait firmware FLR timeout");
+	if (err) {
+		PMD_DRV_LOG(WARNING, "Wait firmware FLR timeout, err: %d", err);
+		ret = err;
+	}
 
 	hinic_enable_doorbell(hwif);
 
 	err = hinic_reinit_cmdq_ctxts(hwdev);
-	if (err)
-		PMD_DRV_LOG(WARNING, "Reinit cmdq failed");
+	if (err) {
+		PMD_DRV_LOG(WARNING,
+			    "Reinit cmdq failed when pf flush, err: %d", err);
+		ret = err;
+	}
 
-	return 0;
+	return ret;
 }
 
 int hinic_func_rx_tx_flush(struct hinic_hwdev *hwdev)
@@ -622,9 +654,9 @@ static int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev,
 				     &msix_cfg, sizeof(msix_cfg),
 				     &msix_cfg, &out_size, 0);
 	if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
-		PMD_DRV_LOG(ERR, "Get interrupt config failed, ret: %d",
-			msix_cfg.mgmt_msg_head.status);
-		return -EINVAL;
+		PMD_DRV_LOG(ERR, "Get interrupt config failed, err: %d, status: 0x%x, out size: 0x%x",
+			err, msix_cfg.mgmt_msg_head.status, out_size);
+		return -EIO;
 	}
 
 	interrupt_info->lli_credit_limit = msix_cfg.lli_credit_cnt;
@@ -682,9 +714,9 @@ int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
 				     &msix_cfg, sizeof(msix_cfg),
 				     &msix_cfg, &out_size, 0);
 	if (err || !out_size || msix_cfg.mgmt_msg_head.status) {
-		PMD_DRV_LOG(ERR, "Set interrupt config failed, ret: %d",
-			msix_cfg.mgmt_msg_head.status);
-		return -EINVAL;
+		PMD_DRV_LOG(ERR, "Set interrupt config failed, err: %d, status: 0x%x, out size: 0x%x",
+			err, msix_cfg.mgmt_msg_head.status, out_size);
+		return -EIO;
 	}
 
 	return 0;
@@ -769,6 +801,8 @@ static int set_vf_dma_attr_entry(struct hinic_hwdev *hwdev, u8 entry_idx,
 				enum hinic_pcie_tph tph_en)
 {
 	struct hinic_vf_dma_attr_table attr;
+	u16 out_size = sizeof(attr);
+	int err;
 
 	memset(&attr, 0, sizeof(attr));
 	attr.func_idx = hinic_global_func_id(hwdev);
@@ -781,9 +815,16 @@ static int set_vf_dma_attr_entry(struct hinic_hwdev *hwdev, u8 entry_idx,
 	attr.no_snooping = no_snooping;
 	attr.tph_en = tph_en;
 
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
-					HINIC_MGMT_CMD_DMA_ATTR_SET,
-					&attr, sizeof(attr), NULL, NULL, 0);
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+				     HINIC_MGMT_CMD_DMA_ATTR_SET,
+				     &attr, sizeof(attr), &attr, &out_size, 0);
+	if (err || !out_size || attr.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Set dma attribute failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, attr.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /**
@@ -925,17 +966,26 @@ static void fault_report_show(struct hinic_hwdev *hwdev,
 static int resources_state_set(struct hinic_hwdev *hwdev,
 			       enum hinic_res_state state)
 {
-	struct hinic_hwif *hwif = hwdev->hwif;
 	struct hinic_cmd_set_res_state res_state;
+	u16 out_size = sizeof(res_state);
+	int err;
 
 	memset(&res_state, 0, sizeof(res_state));
 	res_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
-	res_state.func_idx = HINIC_HWIF_GLOBAL_IDX(hwif);
+	res_state.func_idx = HINIC_HWIF_GLOBAL_IDX(hwdev->hwif);
 	res_state.state = state;
 
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
 				 HINIC_MGMT_CMD_RES_STATE_SET,
-				 &res_state, sizeof(res_state), NULL, NULL, 0);
+				 &res_state, sizeof(res_state),
+				 &res_state, &out_size, 0);
+	if (err || !out_size || res_state.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Set resources state failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, res_state.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /**
@@ -1019,6 +1069,7 @@ int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
 {
 	struct hinic_hwif *hwif = hwdev->hwif;
 	struct hinic_l2nic_reset l2nic_reset;
+	u16 out_size = sizeof(l2nic_reset);
 	int err = 0;
 
 	err = hinic_set_vport_enable(hwdev, false);
@@ -1035,10 +1086,11 @@ int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
 				     HINIC_MGMT_CMD_L2NIC_RESET,
 				     &l2nic_reset, sizeof(l2nic_reset),
-				     NULL, NULL, 0);
-	if (err || l2nic_reset.mgmt_msg_head.status) {
-		PMD_DRV_LOG(ERR, "Reset L2NIC resources failed");
-		return -EFAULT;
+				     &l2nic_reset, &out_size, 0);
+	if (err || !out_size || l2nic_reset.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Reset L2NIC resources failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, l2nic_reset.mgmt_msg_head.status, out_size);
+		return -EIO;
 	}
 
 	return 0;
@@ -1390,14 +1442,14 @@ static void print_cable_info(struct hinic_link_info *info)
 	}
 
 	memcpy(tmp_vendor, info->vendor_name, sizeof(info->vendor_name));
-	snprintf(tmp_str, (sizeof(tmp_str) - 1),
+	snprintf(tmp_str, sizeof(tmp_str),
 		 "Vendor: %s, %s, %s, length: %um, max_speed: %uGbps",
 		 tmp_vendor, info->sfp_type ? "SFP" : "QSFP", port_type,
 		 info->cable_length, info->cable_max_speed);
 	if (info->port_type != LINK_PORT_COPPER)
-		snprintf(tmp_str + strlen(tmp_str), (sizeof(tmp_str) - 1),
-			 "%s, Temperature: %u", tmp_str,
-			 info->cable_temp);
+		snprintf(tmp_str + strlen(tmp_str),
+			 sizeof(tmp_str) - strlen(tmp_str),
+			 ", Temperature: %u", info->cable_temp);
 
 	PMD_DRV_LOG(INFO, "Cable information: %s", tmp_str);
 }
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.h b/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.h
index ac21947dc2..d6896b3f13 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_hwdev.h
@@ -442,7 +442,6 @@ struct hinic_hwdev {
 	struct hinic_msg_pf_to_mgmt *pf_to_mgmt;
 	struct hinic_cmdqs *cmdqs;
 	struct hinic_nic_io *nic_io;
-
 };
 
 int hinic_osdep_init(struct hinic_hwdev *hwdev);
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.c b/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.c
index 3d3c1bc4ab..fb7d16dc6a 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.c
@@ -241,20 +241,22 @@ static void recv_func_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 }
 
 static bool check_mbox_seq_id_and_seg_len(struct hinic_recv_mbox *recv_mbox,
-					  u8 seq_id, u8 seg_len)
+					  u8 seq_id, u8 seg_len, u8 msg_id)
 {
 	if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN)
 		return false;
 
 	if (seq_id == 0) {
-		recv_mbox->sed_id = seq_id;
+		recv_mbox->seq_id = seq_id;
+		recv_mbox->msg_info.msg_id = msg_id;
 	} else {
-		if (seq_id != recv_mbox->sed_id + 1) {
-			recv_mbox->sed_id = 0;
+		if ((seq_id != recv_mbox->seq_id + 1) ||
+			msg_id != recv_mbox->msg_info.msg_id) {
+			recv_mbox->seq_id = 0;
 			return false;
 		}
 
-		recv_mbox->sed_id = seq_id;
+		recv_mbox->seq_id = seq_id;
 	}
 
 	return true;
@@ -298,15 +300,52 @@ mbox_copy_send_data(struct hinic_send_mbox *mbox, void *seg, u16 seg_len)
 				mbox->data + MBOX_HEADER_SZ + i * sizeof(u32));
 }
 
+static int mbox_msg_ack_aeqn(struct hinic_hwdev *hwdev)
+{
+	u16 aeq_num = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
+	int msg_ack_aeqn;
+
+	if (aeq_num >= HINIC_MAX_AEQS - 1) {
+		msg_ack_aeqn = HINIC_AEQN_2;
+	} else if (aeq_num == HINIC_MIN_AEQS) {
+		/* This is used for ovs */
+		msg_ack_aeqn = HINIC_AEQN_1;
+	} else {
+		PMD_DRV_LOG(ERR, "Warning: Invalid aeq num: %d\n", aeq_num);
+		msg_ack_aeqn = -1;
+	}
+
+	return msg_ack_aeqn;
+}
+
+static u16 mbox_msg_dst_aeqn(struct hinic_hwdev *hwdev,
+			enum hinic_hwif_direction_type seq_dir)
+{
+	u16 dst_aeqn;
+
+	if (seq_dir == HINIC_HWIF_DIRECT_SEND)
+		dst_aeqn = HINIC_AEQN_0;
+	else
+		dst_aeqn = mbox_msg_ack_aeqn(hwdev);
+
+	return dst_aeqn;
+}
+
+static int mbox_seg_ack_aeqn(struct hinic_hwdev *hwdev)
+{
+	return mbox_msg_ack_aeqn(hwdev);
+}
+
 static void write_mbox_msg_attr(struct hinic_mbox_func_to_func *func_to_func,
-			u16 dst_func, u16 dst_aeqn,
+			u16 dst_func, u16 dst_aeqn, u16 seg_ack_aeqn,
 			__rte_unused u16 seg_len, int poll)
 {
 	u32 mbox_int, mbox_ctrl;
 
 	mbox_int = HINIC_MBOX_INT_SET(dst_func, DST_FUNC) |
 		HINIC_MBOX_INT_SET(dst_aeqn, DST_AEQN) |
-		HINIC_MBOX_INT_SET(HINIC_MBOX_RSP_AEQN, SRC_RESP_AEQN) |
+		/* N/A in polling mode */
+		HINIC_MBOX_INT_SET(seg_ack_aeqn, SRC_RESP_AEQN) |
 		HINIC_MBOX_INT_SET(NO_DMA_ATTRIBUTE_VAL, STAT_DMA) |
 		HINIC_MBOX_INT_SET(ALIGN(MBOX_SIZE, MBOX_SEG_LEN_ALIGN) >> 2,
 					TX_SIZE) |
@@ -404,10 +443,8 @@ static int alloc_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
 	struct hinic_hwif *hwif = hwdev->hwif;
 	u32 addr_h, addr_l;
 
-	send_mbox->wb_vaddr = dma_zalloc_coherent(hwdev,
-				  MBOX_WB_STATUS_LEN,
-				  &send_mbox->wb_paddr,
-				  GFP_KERNEL);
+	send_mbox->wb_vaddr = dma_zalloc_coherent(hwdev, MBOX_WB_STATUS_LEN,
+					&send_mbox->wb_paddr, SOCKET_ID_ANY);
 	if (!send_mbox->wb_vaddr) {
 		PMD_DRV_LOG(ERR, "Allocating memory for mailbox wb status failed");
 		return -ENOMEM;
@@ -443,16 +480,24 @@ static int recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 	u16 src_func_idx;
 	enum hinic_hwif_direction_type direction;
 	u8 seq_id, seg_len;
+	u8 msg_id;
+	u8 front_id;
 
 	seq_id = HINIC_MBOX_HEADER_GET(mbox_header, SEQID);
 	seg_len = HINIC_MBOX_HEADER_GET(mbox_header, SEG_LEN);
 	direction = HINIC_MBOX_HEADER_GET(mbox_header, DIRECTION);
 	src_func_idx = HINIC_MBOX_HEADER_GET(mbox_header, SRC_GLB_FUNC_IDX);
+	msg_id = HINIC_MBOX_HEADER_GET(mbox_header, MSG_ID);
+	front_id = recv_mbox->seq_id;
 
-	if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len)) {
+	if (!check_mbox_seq_id_and_seg_len(recv_mbox, seq_id, seg_len,
+		msg_id)) {
 		PMD_DRV_LOG(ERR,
-			"Mailbox sequence and segment check failed, src func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x\n",
-			src_func_idx, recv_mbox->sed_id, seq_id, seg_len);
+			"Mailbox sequence and segment check failed, src func id: 0x%x, "
+			"front id: 0x%x, current id: 0x%x, seg len: 0x%x "
+			"front msg_id: %d, cur msg_id: %d",
+			src_func_idx, front_id, seq_id, seg_len,
+			recv_mbox->msg_info.msg_id, msg_id);
 		return HINIC_ERROR;
 	}
 
@@ -462,7 +507,7 @@ static int recv_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 	if (!HINIC_MBOX_HEADER_GET(mbox_header, LAST))
 		return HINIC_ERROR;
 
-	recv_mbox->sed_id = 0;
+	recv_mbox->seq_id = 0;
 	recv_mbox->cmd = HINIC_MBOX_HEADER_GET(mbox_header, CMD);
 	recv_mbox->mod = HINIC_MBOX_HEADER_GET(mbox_header, MODULE);
 	recv_mbox->mbox_len = HINIC_MBOX_HEADER_GET(mbox_header, MSG_LEN);
@@ -554,19 +599,21 @@ static int send_mbox_seg(struct hinic_mbox_func_to_func *func_to_func,
 	struct hinic_send_mbox *send_mbox = &func_to_func->send_mbox;
 	struct hinic_hwdev *hwdev = func_to_func->hwdev;
 	u16 seq_dir = HINIC_MBOX_HEADER_GET(header, DIRECTION);
-	u16 dst_aeqn = (seq_dir == HINIC_HWIF_DIRECT_SEND) ?
-				HINIC_MBOX_RECV_AEQN : HINIC_MBOX_RSP_AEQN;
+	u16 dst_aeqn, seg_ack_aeqn;
 	u16 err_code, wb_status = 0;
 	u32 cnt = 0;
 
+	dst_aeqn = mbox_msg_dst_aeqn(hwdev, seq_dir);
+	seg_ack_aeqn = mbox_seg_ack_aeqn(hwdev);
+
 	clear_mbox_status(send_mbox);
 
 	mbox_copy_header(send_mbox, &header);
 
 	mbox_copy_send_data(send_mbox, seg, seg_len);
 
-	write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_len,
-			    MBOX_SEND_MSG_POLL);
+	write_mbox_msg_attr(func_to_func, dst_func, dst_aeqn, seg_ack_aeqn,
+				seg_len, MBOX_SEND_MSG_POLL);
 
 	rte_wmb();
 
@@ -700,7 +747,7 @@ static int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
 		goto send_err;
 
 	time = msecs_to_jiffies(timeout ? timeout : HINIC_MBOX_COMP_TIME_MS);
-	err = hinic_aeq_poll_msg(func_to_func->rsp_aeq, time, NULL);
+	err = hinic_aeq_poll_msg(func_to_func->ack_aeq, time, NULL);
 	if (err) {
 		set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
 		PMD_DRV_LOG(ERR, "Send mailbox message time out");
@@ -872,7 +919,7 @@ static int hinic_func_to_func_init(struct hinic_hwdev *hwdev)
 
 	err = alloc_mbox_info(func_to_func->mbox_resp);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Allocating memory for mailbox responsing failed");
+		PMD_DRV_LOG(ERR, "Allocating memory for mailbox responding failed");
 		goto alloc_mbox_for_resp_err;
 	}
 
@@ -923,13 +970,16 @@ void hinic_comm_func_to_func_free(struct hinic_hwdev *hwdev)
 int hinic_comm_func_to_func_init(struct hinic_hwdev *hwdev)
 {
 	int rc;
+	u16 msg_ack_aeqn;
 
 	rc = hinic_func_to_func_init(hwdev);
 	if (rc)
 		return rc;
 
-	hwdev->func_to_func->rsp_aeq = &hwdev->aeqs->aeq[HINIC_MBOX_RSP_AEQN];
-	hwdev->func_to_func->recv_aeq = &hwdev->aeqs->aeq[HINIC_MBOX_RECV_AEQN];
+	msg_ack_aeqn = mbox_msg_ack_aeqn(hwdev);
+
+	hwdev->func_to_func->ack_aeq = &hwdev->aeqs->aeq[msg_ack_aeqn];
+	hwdev->func_to_func->recv_aeq = &hwdev->aeqs->aeq[HINIC_AEQN_0];
 
 	return 0;
 }
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.h b/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.h
index bf7b4906dc..b17f0df1db 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_mbox.h
@@ -5,9 +5,6 @@
 #ifndef _HINIC_PMD_MBOX_H_
 #define _HINIC_PMD_MBOX_H_
 
-#define HINIC_MBOX_RECV_AEQN		0
-#define HINIC_MBOX_RSP_AEQN		2
-
 #define HINIC_MBOX_PF_SEND_ERR		0x1
 #define HINIC_MBOX_PF_BUSY_ACTIVE_FW	0x2
 #define HINIC_MBOX_VF_CMD_ERROR		0x3
@@ -42,7 +39,7 @@ struct hinic_recv_mbox {
 	void *buf_out;
 	enum hinic_mbox_ack_type ack_type;
 	struct mbox_msg_info msg_info;
-	u8 sed_id;
+	u8 seq_id;
 };
 
 struct hinic_send_mbox {
@@ -69,7 +66,7 @@ struct hinic_mbox_func_to_func {
 	struct hinic_recv_mbox mbox_resp[HINIC_MAX_FUNCTIONS];
 	struct hinic_recv_mbox mbox_send[HINIC_MAX_FUNCTIONS];
 
-	struct hinic_eq *rsp_aeq;
+	struct hinic_eq *ack_aeq;
 	struct hinic_eq *recv_aeq;
 
 	u8 send_msg_id;
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.c b/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.c
index eee50a80d1..d5fd16f235 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.c
@@ -248,6 +248,19 @@ static void free_msg_buf(struct hinic_msg_pf_to_mgmt *pf_to_mgmt)
 	free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
 }
 
+static int hinic_get_mgmt_channel_status(void *hwdev)
+{
+	struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
+	u32 val;
+
+	if (hinic_func_type((struct hinic_hwdev *)hwdev) == TYPE_VF)
+		return false;
+
+	val = hinic_hwif_read_reg(hwif, HINIC_ICPL_RESERVD_ADDR);
+
+	return HINIC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
+}
+
 /**
  * send_msg_to_mgmt_async - send async message
  * @pf_to_mgmt: PF to MGMT channel
@@ -309,6 +322,14 @@ static int send_msg_to_mgmt_sync(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
 	u64 header;
 	u16 cmd_size = mgmt_msg_len(msg_len);
 
+	/* If fw is hot active, return failed */
+	if (hinic_get_mgmt_channel_status(pf_to_mgmt->hwdev)) {
+		if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC)
+			return HINIC_DEV_BUSY_ACTIVE_FW;
+		else
+			return -EBUSY;
+	}
+
 	if (direction == HINIC_MSG_RESPONSE)
 		prepare_header(pf_to_mgmt, &header, msg_len, mod, ack_type,
 			       direction, cmd, resp_msg_id);
@@ -462,19 +483,6 @@ hinic_pf_to_mgmt_sync(struct hinic_hwdev *hwdev,
 	return err;
 }
 
-static int hinic_get_mgmt_channel_status(void *hwdev)
-{
-	struct hinic_hwif *hwif = ((struct hinic_hwdev *)hwdev)->hwif;
-	u32 val;
-
-	if (hinic_func_type((struct hinic_hwdev *)hwdev) == TYPE_VF)
-		return false;
-
-	val = hinic_hwif_read_reg(hwif, HINIC_ICPL_RESERVD_ADDR);
-
-	return HINIC_GET_MGMT_CHANNEL_STATUS(val, MGMT_CHANNEL_STATUS);
-}
-
 int hinic_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd,
 			   void *buf_in, u16 in_size,
 			   void *buf_out, u16 *out_size, u32 timeout)
@@ -484,10 +492,6 @@ int hinic_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd,
 	if (!hwdev || in_size > HINIC_MSG_TO_MGMT_MAX_LEN)
 		return -EINVAL;
 
-	/* If status is hot upgrading, don't send message to mgmt */
-	if (hinic_get_mgmt_channel_status(hwdev))
-		return -EPERM;
-
 	if (hinic_func_type(hwdev) == TYPE_VF) {
 		rc = hinic_mbox_to_pf(hwdev, mod, cmd, buf_in, in_size,
 					buf_out, out_size, timeout);
@@ -500,8 +504,7 @@ int hinic_msg_to_mgmt_sync(void *hwdev, enum hinic_mod_type mod, u8 cmd,
 }
 
 int hinic_msg_to_mgmt_no_ack(void *hwdev, enum hinic_mod_type mod, u8 cmd,
-		     void *buf_in, u16 in_size, __rte_unused void *buf_out,
-		     __rte_unused u16 *out_size)
+			     void *buf_in, u16 in_size)
 {
 	struct hinic_msg_pf_to_mgmt *pf_to_mgmt =
 				((struct hinic_hwdev *)hwdev)->pf_to_mgmt;
@@ -526,19 +529,21 @@ int hinic_msg_to_mgmt_no_ack(void *hwdev, enum hinic_mod_type mod, u8 cmd,
 }
 
 static bool check_mgmt_seq_id_and_seg_len(struct hinic_recv_msg *recv_msg,
-					  u8 seq_id, u8 seg_len)
+					  u8 seq_id, u8 seg_len, u16 msg_id)
 {
 	if (seq_id > HINIC_SEQ_ID_MAX_VAL || seg_len > HINIC_MSG_SEG_LEN)
 		return false;
 
 	if (seq_id == 0) {
-		recv_msg->sed_id = seq_id;
+		recv_msg->seq_id = seq_id;
+		recv_msg->msg_id = msg_id;
 	} else {
-		if (seq_id != recv_msg->sed_id + 1) {
-			recv_msg->sed_id = 0;
+		if ((seq_id != recv_msg->seq_id + 1) ||
+			msg_id != recv_msg->msg_id) {
+			recv_msg->seq_id = 0;
 			return false;
 		}
-		recv_msg->sed_id = seq_id;
+		recv_msg->seq_id = seq_id;
 	}
 
 	return true;
@@ -611,16 +616,21 @@ static int recv_mgmt_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
 	u8 *dest_msg;
 	u8 seq_id, seq_len;
 	u32 msg_buf_max = MAX_PF_MGMT_BUF_SIZE;
+	u8 front_id;
+	u16 msg_id;
 
 	seq_id = HINIC_MSG_HEADER_GET(msg_header, SEQID);
 	seq_len = HINIC_MSG_HEADER_GET(msg_header, SEG_LEN);
+	front_id = recv_msg->seq_id;
+	msg_id = HINIC_MSG_HEADER_GET(msg_header, MSG_ID);
 
-	if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len)) {
+	if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len, msg_id)) {
 		PMD_DRV_LOG(ERR,
 			"Mgmt msg sequence and segment check fail, "
-			"func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x",
+			"func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x "
+			"front msg_id: %d, cur msg_id: %d",
 			hinic_global_func_id(pf_to_mgmt->hwdev),
-			recv_msg->sed_id, seq_id, seq_len);
+			front_id, seq_id, seq_len, recv_msg->msg_id, msg_id);
 		return HINIC_ERROR;
 	}
 
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.h b/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.h
index cc18843bf8..5099a3a8d6 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_mgmt.h
@@ -34,6 +34,8 @@
 #define HINIC_MSG_HEADER_P2P_IDX_MASK				0xF
 #define HINIC_MSG_HEADER_MSG_ID_MASK				0x3FF
 
+#define HINIC_DEV_BUSY_ACTIVE_FW				0xFE
+
 #define HINIC_MSG_HEADER_GET(val, member)			\
 		(((val) >> HINIC_MSG_HEADER_##member##_SHIFT) & \
 		HINIC_MSG_HEADER_##member##_MASK)
@@ -67,7 +69,7 @@ struct hinic_recv_msg {
 	u8			cmd;
 	u16			msg_id;
 	int			async_mgmt_to_pf;
-	u8			sed_id;
+	u8			seq_id;
 };
 
 #define HINIC_COMM_SELF_CMD_MAX 8
@@ -99,8 +101,7 @@ struct hinic_msg_pf_to_mgmt {
 };
 
 int hinic_msg_to_mgmt_no_ack(void *hwdev, enum hinic_mod_type mod, u8 cmd,
-			     void *buf_in, u16 in_size, void *buf_out,
-			     u16 *out_size);
+			     void *buf_in, u16 in_size);
 
 int hinic_comm_pf_to_mgmt_init(struct hinic_hwdev *hwdev);
 
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c b/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c
index 2dc431e288..610f56d617 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c
@@ -18,7 +18,6 @@
 			buf_in, in_size,			\
 			buf_out, out_size, 0)
 
-
 #define TCAM_SET	0x1
 #define TCAM_CLEAR	0x2
 
@@ -396,9 +395,8 @@ int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add)
 	vlan_info.func_id = func_id;
 	vlan_info.vlan_id = vlan_id;
 
-	err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info,
-				     sizeof(vlan_info), &vlan_info,
-				     &out_size);
+	err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info, sizeof(vlan_info),
+				     &vlan_info, &out_size);
 	if (err || !out_size || vlan_info.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR,
 			"Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n",
@@ -485,8 +483,8 @@ int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
 	vlan_cfg.vlan_rx_offload = en;
 
 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
-					&vlan_cfg, sizeof(vlan_cfg),
-					&vlan_cfg, &out_size);
+				     &vlan_cfg, sizeof(vlan_cfg),
+				     &vlan_cfg, &out_size);
 	if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR,
 			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
@@ -642,7 +640,7 @@ int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
 		PMD_DRV_LOG(ERR,
 			"Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
 			err, port_msg.mgmt_msg_head.status, out_size);
-		return err;
+		return -EIO;
 	}
 
 	port_info->autoneg_cap = port_msg.autoneg_cap;
@@ -1258,7 +1256,6 @@ int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
 		PMD_DRV_LOG(ERR,
 			"Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
 			err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
-
 		return -EIO;
 	}
 
@@ -1413,8 +1410,7 @@ int hinic_set_anti_attack(void *hwdev, bool enable)
 	rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
 
 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
-				     &rate, sizeof(rate), &rate,
-				     &out_size);
+				     &rate, sizeof(rate), &rate, &out_size);
 	if (err || !out_size || rate.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
 			(enable ? "enable" : "disable"), err,
@@ -1518,10 +1514,9 @@ int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
 				     sizeof(fast_recycled_mode),
 				     &fast_recycled_mode, &out_size, 0);
 	if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
-		PMD_DRV_LOG(ERR,
-			"Failed to set recycle mode, ret = %d",
-			fast_recycled_mode.mgmt_msg_head.status);
-		return -EFAULT;
+		PMD_DRV_LOG(ERR, "Failed to set recycle mode, err: %d, status: 0x%x, out size: 0x%x",
+			err, fast_recycled_mode.mgmt_msg_head.status, out_size);
+		return -EIO;
 	}
 
 	return 0;
@@ -1652,44 +1647,6 @@ int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
 	return 0;
 }
 
-/**
- * hinic_set_xsfp_tx_status - Enable or disable the fiber in
- * tx direction when set link up or down.
- *
- * @param hwdev
- *   The hardware interface of a nic device.
- * @param enable
- *   Enable or Disable.
- *
- * @return
- *   0 on success.
- *   negative error value otherwise.
- */
-int hinic_set_xsfp_tx_status(void *hwdev, bool enable)
-{
-	struct hinic_set_xsfp_status xsfp_status;
-	u16 out_size = sizeof(struct hinic_set_xsfp_status);
-	int err;
-
-	memset(&xsfp_status, 0, sizeof(xsfp_status));
-	xsfp_status.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
-	xsfp_status.port_id = hinic_global_func_id(hwdev);
-	xsfp_status.xsfp_tx_dis = ((enable == 0) ? 1 : 0);
-
-	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_XSFP_STATUS,
-		&xsfp_status, sizeof(struct hinic_set_xsfp_status),
-		&xsfp_status, &out_size);
-	if (err || !out_size || xsfp_status.mgmt_msg_head.status) {
-		PMD_DRV_LOG(ERR,
-			"Failed to %s port xsfp status, err: %d, status: 0x%x, out size: 0x%x\n",
-			enable ? "Disable" : "Enable", err,
-			xsfp_status.mgmt_msg_head.status, out_size);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
 /**
  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
  * fake failed when device start.
@@ -1746,12 +1703,11 @@ int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
 
 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
 				     HINIC_PORT_CMD_GET_VF_COS, &vf_cos,
-				     sizeof(vf_cos), &vf_cos,
-				     &out_size, 0);
+				     sizeof(vf_cos), &vf_cos, &out_size, 0);
 	if (err || !out_size || vf_cos.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x",
 			err, vf_cos.mgmt_msg_head.status, out_size);
-		return -EFAULT;
+		return -EIO;
 	}
 	*cos_id = vf_cos.state.default_cos;
 
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.h b/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.h
index b9e037ec2d..bf39b0272b 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.h
@@ -827,8 +827,6 @@ int hinic_set_link_status_follow(void *hwdev,
 
 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised);
 
-int hinic_set_xsfp_tx_status(void *hwdev, bool enable);
-
 int hinic_flush_qp_res(void *hwdev);
 
 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz);
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_nicio.c b/dpdk/drivers/net/hinic/base/hinic_pmd_nicio.c
index f6cc03341b..9d9f2a7a56 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_nicio.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_nicio.c
@@ -471,6 +471,8 @@ static int
 hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz)
 {
 	struct hinic_root_ctxt root_ctxt;
+	u16 out_size = sizeof(root_ctxt);
+	int err;
 
 	memset(&root_ctxt, 0, sizeof(root_ctxt));
 	root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
@@ -483,10 +485,18 @@ hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz)
 	root_ctxt.rx_buf_sz = get_hw_rx_buf_size(rx_buf_sz);
 	root_ctxt.sq_depth  = (u16)ilog2(sq_depth);
 
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
-				      HINIC_MGMT_CMD_VAT_SET,
-				      &root_ctxt, sizeof(root_ctxt),
-				      NULL, NULL, 0);
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+				     HINIC_MGMT_CMD_VAT_SET,
+				     &root_ctxt, sizeof(root_ctxt),
+				     &root_ctxt, &out_size, 0);
+	if (err || !out_size || root_ctxt.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR,
+			"Set root context failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, root_ctxt.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /**
@@ -499,6 +509,8 @@ hinic_set_root_ctxt(void *hwdev, u16 rq_depth, u16 sq_depth, int rx_buf_sz)
 static int hinic_clean_root_ctxt(void *hwdev)
 {
 	struct hinic_root_ctxt root_ctxt;
+	u16 out_size = sizeof(root_ctxt);
+	int err;
 
 	memset(&root_ctxt, 0, sizeof(root_ctxt));
 	root_ctxt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
@@ -511,10 +523,18 @@ static int hinic_clean_root_ctxt(void *hwdev)
 	root_ctxt.rx_buf_sz = 0;
 	root_ctxt.sq_depth  = 0;
 
-	return hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
-				      HINIC_MGMT_CMD_VAT_SET,
-				      &root_ctxt, sizeof(root_ctxt),
-				      NULL, NULL, 0);
+	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
+				     HINIC_MGMT_CMD_VAT_SET,
+				     &root_ctxt, sizeof(root_ctxt),
+				     &root_ctxt, &out_size, 0);
+	if (err || !out_size || root_ctxt.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR,
+			"Clean root context failed, err: %d, status: 0x%x, out_size: 0x%x",
+			err, root_ctxt.mgmt_msg_head.status, out_size);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /* init qps ctxt and set sq ci attr and arm all sq and set vat page_size */
@@ -533,6 +553,15 @@ int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
 		return err;
 	}
 
+	if (hwdev->cmdqs->status & HINIC_CMDQ_SET_FAIL) {
+		err = hinic_reinit_cmdq_ctxts(hwdev);
+		if (err) {
+			PMD_DRV_LOG(ERR, "Reinit cmdq context failed when dev start, err: %d",
+				err);
+			return err;
+		}
+	}
+
 	err = init_qp_ctxts(nic_io);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Init QP ctxts failed, rc: %d", err);
@@ -728,16 +757,12 @@ void hinic_update_rq_local_ci(struct hinic_hwdev *hwdev, u16 q_id, int wqe_cnt)
 
 static int hinic_alloc_nicio(struct hinic_hwdev *hwdev)
 {
-	int err;
-	u16 max_qps, num_qp;
 	struct hinic_nic_io *nic_io = hwdev->nic_io;
+	struct rte_pci_device *pdev = hwdev->pcidev_hdl;
+	u16 max_qps, num_qp;
+	int err;
 
 	max_qps = hinic_func_max_qnum(hwdev);
-	if ((max_qps & (max_qps - 1))) {
-		PMD_DRV_LOG(ERR, "wrong number of max_qps: %d",
-			max_qps);
-		return -EINVAL;
-	}
 
 	nic_io->max_qps = max_qps;
 	nic_io->num_qps = max_qps;
@@ -751,10 +776,10 @@ static int hinic_alloc_nicio(struct hinic_hwdev *hwdev)
 		goto alloc_qps_err;
 	}
 
-	nic_io->ci_vaddr_base =
-		dma_zalloc_coherent(hwdev,
+	nic_io->ci_vaddr_base = dma_zalloc_coherent(hwdev,
 				    CI_TABLE_SIZE(num_qp, HINIC_PAGE_SIZE),
-				    &nic_io->ci_dma_base, GFP_KERNEL);
+				    &nic_io->ci_dma_base,
+				    pdev->device.numa_node);
 	if (!nic_io->ci_vaddr_base) {
 		PMD_DRV_LOG(ERR, "Failed to allocate ci area");
 		err = -ENOMEM;
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_wq.c b/dpdk/drivers/net/hinic/base/hinic_pmd_wq.c
index 04c81f9bc8..345248c3ea 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_wq.c
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_wq.c
@@ -15,13 +15,14 @@ static void free_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
 	wq->queue_buf_vaddr = 0;
 }
 
-static int alloc_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
+static int alloc_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
+			unsigned int socket_id)
 {
 	dma_addr_t dma_addr = 0;
 
 	wq->queue_buf_vaddr = (u64)(u64 *)
 		dma_zalloc_coherent_aligned256k(hwdev, wq->wq_buf_size,
-						&dma_addr, GFP_KERNEL);
+						&dma_addr, socket_id);
 	if (!wq->queue_buf_vaddr) {
 		PMD_DRV_LOG(ERR, "Failed to allocate wq page");
 		return -ENOMEM;
@@ -40,7 +41,7 @@ static int alloc_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
 }
 
 int hinic_wq_allocate(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
-		      u32 wqebb_shift, u16 q_depth)
+		      u32 wqebb_shift, u16 q_depth, unsigned int socket_id)
 {
 	int err;
 
@@ -60,7 +61,7 @@ int hinic_wq_allocate(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
 		return -EINVAL;
 	}
 
-	err = alloc_wq_pages(hwdev, wq);
+	err = alloc_wq_pages(hwdev, wq, socket_id);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Failed to allocate wq pages");
 		return err;
@@ -114,7 +115,7 @@ int hinic_cmdq_alloc(struct hinic_wq *wq, struct hinic_hwdev *hwdev,
 		wq[i].wq_buf_size = wq_buf_size;
 		wq[i].q_depth = q_depth;
 
-		err = alloc_wq_pages(hwdev, &wq[i]);
+		err = alloc_wq_pages(hwdev, &wq[i], SOCKET_ID_ANY);
 		if (err) {
 			PMD_DRV_LOG(ERR, "Failed to alloc CMDQ blocks");
 			goto cmdq_block_err;
diff --git a/dpdk/drivers/net/hinic/base/hinic_pmd_wq.h b/dpdk/drivers/net/hinic/base/hinic_pmd_wq.h
index 53ecc225c8..354d0338de 100644
--- a/dpdk/drivers/net/hinic/base/hinic_pmd_wq.h
+++ b/dpdk/drivers/net/hinic/base/hinic_pmd_wq.h
@@ -122,7 +122,7 @@ void hinic_cmdq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
 		     int cmdq_blocks);
 
 int hinic_wq_allocate(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
-		      u32 wqebb_shift, u16 q_depth);
+		      u32 wqebb_shift, u16 q_depth, unsigned int socket_id);
 
 void hinic_wq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq);
 
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_ethdev.c b/dpdk/drivers/net/hinic/hinic_pmd_ethdev.c
index 803a39e2da..a0499da7d4 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_ethdev.c
+++ b/dpdk/drivers/net/hinic/hinic_pmd_ethdev.c
@@ -57,6 +57,7 @@
 #define HINIC_DEFAULT_BURST_SIZE	32
 #define HINIC_DEFAULT_NB_QUEUES		1
 #define HINIC_DEFAULT_RING_SIZE		1024
+#define HINIC_MAX_LRO_SIZE		65536
 
 /*
  * vlan_id is a 12 bit number.
@@ -439,7 +440,7 @@ static int hinic_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 	nic_dev->rxqs[queue_idx] = rxq;
 
 	/* alloc rx sq hw wqepage*/
-	rc = hinic_create_rq(hwdev, queue_idx, rq_depth);
+	rc = hinic_create_rq(hwdev, queue_idx, rq_depth, socket_id);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Create rxq[%d] failed, dev_name: %s, rq_depth: %d",
 			    queue_idx, dev->data->name, rq_depth);
@@ -466,6 +467,7 @@ static int hinic_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 	rxq->q_depth = rq_depth;
 	rxq->buf_len = (u16)buf_size;
 	rxq->rx_free_thresh = rx_free_thresh;
+	rxq->socket_id = socket_id;
 
 	/* the last point cant do mbuf rearm in bulk */
 	rxq->rxinfo_align_end = rxq->q_depth - rxq->rx_free_thresh;
@@ -593,7 +595,7 @@ static int hinic_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 	nic_dev->txqs[queue_idx] = txq;
 
 	/* alloc tx sq hw wqepage */
-	rc = hinic_create_sq(hwdev, queue_idx, sq_depth);
+	rc = hinic_create_sq(hwdev, queue_idx, sq_depth, socket_id);
 	if (rc) {
 		PMD_DRV_LOG(ERR, "Create txq[%d] failed, dev_name: %s, sq_depth: %d",
 			    queue_idx, dev->data->name, sq_depth);
@@ -612,6 +614,7 @@ static int hinic_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 	txq->sq_bot_sge_addr = HINIC_GET_WQ_TAIL(txq) -
 					sizeof(struct hinic_sq_bufdesc);
 	txq->cos = nic_dev->default_cos;
+	txq->socket_id = socket_id;
 
 	/* alloc software txinfo */
 	rc = hinic_setup_tx_resources(txq);
@@ -733,6 +736,7 @@ hinic_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 	info->max_mac_addrs  = HINIC_MAX_UC_MAC_ADDRS;
 	info->min_mtu = HINIC_MIN_MTU_SIZE;
 	info->max_mtu = HINIC_MAX_MTU_SIZE;
+	info->max_lro_pkt_size = HINIC_MAX_LRO_SIZE;
 
 	hinic_get_speed_capa(dev, &info->speed_capa);
 	info->rx_queue_offload_capa = 0;
@@ -808,12 +812,10 @@ static int hinic_config_rx_mode(struct hinic_nic_dev *nic_dev, u32 rx_mode_ctrl)
 	return 0;
 }
 
-
 static int hinic_rxtx_configure(struct rte_eth_dev *dev)
 {
-	int err;
 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
-	bool lro_en;
+	int err;
 
 	/* rx configure, if rss enable, need to init default configuration */
 	err = hinic_rx_configure(dev);
@@ -830,18 +832,6 @@ static int hinic_rxtx_configure(struct rte_eth_dev *dev)
 		goto set_rx_mode_fail;
 	}
 
-	/* config lro */
-	lro_en = dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_TCP_LRO ?
-			true : false;
-
-	err = hinic_set_rx_lro(nic_dev->hwdev, lro_en, lro_en,
-				HINIC_LRO_WQE_NUM_DEFAULT);
-	if (err) {
-		PMD_DRV_LOG(ERR, "%s lro failed, err: %d",
-			lro_en ? "Enable" : "Disable", err);
-		goto set_rx_mode_fail;
-	}
-
 	return HINIC_OK;
 
 set_rx_mode_fail:
@@ -951,13 +941,6 @@ static int hinic_dev_set_link_up(struct rte_eth_dev *dev)
 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
 	int ret;
 
-	ret = hinic_set_xsfp_tx_status(nic_dev->hwdev, true);
-	if (ret) {
-		PMD_DRV_LOG(ERR, "Enable port tx xsfp failed, dev_name: %s, port_id: %d",
-			    nic_dev->proc_dev_name, dev->data->port_id);
-		return ret;
-	}
-
 	/* link status follow phy port status, up will open pma */
 	ret = hinic_set_port_enable(nic_dev->hwdev, true);
 	if (ret)
@@ -981,13 +964,6 @@ static int hinic_dev_set_link_down(struct rte_eth_dev *dev)
 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
 	int ret;
 
-	ret = hinic_set_xsfp_tx_status(nic_dev->hwdev, false);
-	if (ret) {
-		PMD_DRV_LOG(ERR, "Disable port tx xsfp failed, dev_name: %s, port_id: %d",
-			    nic_dev->proc_dev_name, dev->data->port_id);
-		return ret;
-	}
-
 	/* link status follow phy port status, up will close pma */
 	ret = hinic_set_port_enable(nic_dev->hwdev, false);
 	if (ret)
@@ -1279,14 +1255,25 @@ static void hinic_disable_interrupt(struct rte_eth_dev *dev)
 
 static int hinic_set_dev_promiscuous(struct hinic_nic_dev *nic_dev, bool enable)
 {
-	u32 rx_mode_ctrl = nic_dev->rx_mode_status;
+	u32 rx_mode_ctrl;
+	int err;
+
+	err = hinic_mutex_lock(&nic_dev->rx_mode_mutex);
+	if (err)
+		return err;
+
+	rx_mode_ctrl = nic_dev->rx_mode_status;
 
 	if (enable)
 		rx_mode_ctrl |= HINIC_RX_MODE_PROMISC;
 	else
 		rx_mode_ctrl &= (~HINIC_RX_MODE_PROMISC);
 
-	return hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
+	err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
+
+	(void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex);
+
+	return err;
 }
 
 /**
@@ -1320,6 +1307,8 @@ hinic_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 		return err;
 	}
 
+	dev->data->rx_mbuf_alloc_failed = 0;
+
 	/* rx queue stats */
 	q_num = (nic_dev->num_rq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
 			nic_dev->num_rq : RTE_ETHDEV_QUEUE_STAT_CNTRS;
@@ -1700,12 +1689,6 @@ static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 			  nic_dev->proc_dev_name, dev->data->port_id);
 	}
 
-	if (mask & ETH_VLAN_EXTEND_MASK) {
-		PMD_DRV_LOG(ERR, "Don't support vlan qinq, device: %s, port_id: %d",
-			  nic_dev->proc_dev_name, dev->data->port_id);
-		return -ENOTSUP;
-	}
-
 	return 0;
 }
 
@@ -1730,14 +1713,25 @@ static void hinic_remove_all_vlanid(struct rte_eth_dev *eth_dev)
 static int hinic_set_dev_allmulticast(struct hinic_nic_dev *nic_dev,
 				bool enable)
 {
-	u32 rx_mode_ctrl = nic_dev->rx_mode_status;
+	u32 rx_mode_ctrl;
+	int err;
+
+	err = hinic_mutex_lock(&nic_dev->rx_mode_mutex);
+	if (err)
+		return err;
+
+	rx_mode_ctrl = nic_dev->rx_mode_status;
 
 	if (enable)
 		rx_mode_ctrl |= HINIC_RX_MODE_MC_ALL;
 	else
 		rx_mode_ctrl &= (~HINIC_RX_MODE_MC_ALL);
 
-	return hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
+	err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
+
+	(void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex);
+
+	return err;
 }
 
 /**
@@ -2490,26 +2484,53 @@ static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev)
 					up_pgid, up_bw, up_strict);
 }
 
+static int hinic_pf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
+{
+	u8 default_cos = 0;
+	u8 valid_cos_bitmap;
+	u8 i;
+
+	valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.valid_cos_bitmap;
+	if (!valid_cos_bitmap) {
+		PMD_DRV_LOG(ERR, "PF has none cos to support\n");
+		return -EFAULT;
+	}
+
+	for (i = 0; i < NR_MAX_COS; i++) {
+		if (valid_cos_bitmap & BIT(i))
+			default_cos = i; /* Find max cos id as default cos */
+	}
+
+	*cos_id = default_cos;
+
+	return 0;
+}
+
 static int hinic_init_default_cos(struct hinic_nic_dev *nic_dev)
 {
 	u8 cos_id = 0;
 	int err;
 
 	if (!HINIC_IS_VF(nic_dev->hwdev)) {
-		nic_dev->default_cos =
-				(hinic_global_func_id(nic_dev->hwdev) +
-						DEFAULT_BASE_COS) % NR_MAX_COS;
+		err = hinic_pf_get_default_cos(nic_dev->hwdev, &cos_id);
+		if (err) {
+			PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d",
+				    err);
+			return HINIC_ERROR;
+		}
 	} else {
 		err = hinic_vf_get_default_cos(nic_dev->hwdev, &cos_id);
 		if (err) {
 			PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d",
-					err);
+				    err);
 			return HINIC_ERROR;
 		}
-
-		nic_dev->default_cos = cos_id;
 	}
 
+	nic_dev->default_cos = cos_id;
+
+	PMD_DRV_LOG(INFO, "Default cos %d", nic_dev->default_cos);
+
 	return 0;
 }
 
@@ -3044,6 +3065,8 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev)
 	}
 	hinic_set_bit(HINIC_DEV_INTR_EN, &nic_dev->dev_status);
 
+	hinic_mutex_init(&nic_dev->rx_mode_mutex, NULL);
+
 	/* initialize filter info */
 	filter_info = &nic_dev->filter;
 	memset(filter_info, 0, sizeof(struct hinic_filter_info));
@@ -3115,6 +3138,8 @@ static int hinic_dev_uninit(struct rte_eth_dev *dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
+	hinic_mutex_destroy(&nic_dev->rx_mode_mutex);
+
 	hinic_dev_close(dev);
 
 	dev->dev_ops = NULL;
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_ethdev.h b/dpdk/drivers/net/hinic/hinic_pmd_ethdev.h
index 3e3f3b3607..b7dc9640fb 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_ethdev.h
+++ b/dpdk/drivers/net/hinic/hinic_pmd_ethdev.h
@@ -171,6 +171,7 @@ struct hinic_nic_dev {
 	unsigned int flags;
 	struct nic_service_cap nic_cap;
 	u32 rx_mode_status;	/* promisc or allmulticast */
+	pthread_mutex_t rx_mode_mutex;
 	unsigned long dev_status;
 
 	char proc_dev_name[HINIC_DEV_NAME_LEN];
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_flow.c b/dpdk/drivers/net/hinic/hinic_pmd_flow.c
index 49c9d8768c..f820be4e93 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_flow.c
+++ b/dpdk/drivers/net/hinic/hinic_pmd_flow.c
@@ -683,6 +683,7 @@ static int hinic_ntuple_item_check_end(const struct rte_flow_item *item,
 			item, "Not supported by ntuple filter");
 		return -rte_errno;
 	}
+
 	return 0;
 }
 
@@ -1934,6 +1935,8 @@ hinic_add_del_ethertype_filter(struct rte_eth_dev *dev,
 		ethertype_filter.pkt_proto = filter->ether_type;
 		i = hinic_ethertype_filter_lookup(filter_info,
 						&ethertype_filter);
+		if (i < 0)
+			return -EINVAL;
 
 		if ((filter_info->type_mask & (1 << i))) {
 			filter_info->pkt_filters[i].enable = FALSE;
@@ -2112,6 +2115,12 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
 		if (!ret) {
 			ntuple_filter_ptr = rte_zmalloc("hinic_ntuple_filter",
 				sizeof(struct hinic_ntuple_filter_ele), 0);
+			if (ntuple_filter_ptr == NULL) {
+				PMD_DRV_LOG(ERR, "Failed to allocate ntuple_filter_ptr");
+				(void)hinic_add_del_ntuple_filter(dev,
+							&ntuple_filter, FALSE);
+				goto out;
+			}
 			rte_memcpy(&ntuple_filter_ptr->filter_info,
 				   &ntuple_filter,
 				   sizeof(struct rte_eth_ntuple_filter));
@@ -2138,6 +2147,12 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
 			ethertype_filter_ptr =
 				rte_zmalloc("hinic_ethertype_filter",
 				sizeof(struct hinic_ethertype_filter_ele), 0);
+			if (ethertype_filter_ptr == NULL) {
+				PMD_DRV_LOG(ERR, "Failed to allocate ethertype_filter_ptr");
+				(void)hinic_add_del_ethertype_filter(dev,
+						&ethertype_filter, FALSE);
+				goto out;
+			}
 			rte_memcpy(&ethertype_filter_ptr->filter_info,
 				&ethertype_filter,
 				sizeof(struct rte_eth_ethertype_filter));
@@ -2162,6 +2177,12 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev,
 		if (!ret) {
 			fdir_rule_ptr = rte_zmalloc("hinic_fdir_rule",
 				sizeof(struct hinic_fdir_rule_ele), 0);
+			if (fdir_rule_ptr == NULL) {
+				PMD_DRV_LOG(ERR, "Failed to allocate fdir_rule_ptr");
+				hinic_add_del_fdir_filter(dev,
+						&fdir_rule, FALSE);
+				goto out;
+			}
 			rte_memcpy(&fdir_rule_ptr->filter_info, &fdir_rule,
 				sizeof(struct hinic_fdir_rule));
 			TAILQ_INSERT_TAIL(&nic_dev->filter_fdir_rule_list,
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_rx.c b/dpdk/drivers/net/hinic/hinic_pmd_rx.c
index f865f2f470..8572780c62 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_rx.c
+++ b/dpdk/drivers/net/hinic/hinic_pmd_rx.c
@@ -209,7 +209,8 @@ void hinic_get_func_rx_buf_size(struct hinic_nic_dev *nic_dev)
 	nic_dev->hwdev->nic_io->rq_buf_size = buf_size;
 }
 
-int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id, u16 rq_depth)
+int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id,
+			u16 rq_depth, unsigned int socket_id)
 {
 	int err;
 	struct hinic_nic_io *nic_io = hwdev->nic_io;
@@ -223,17 +224,15 @@ int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id, u16 rq_depth)
 	nic_io->rq_depth = rq_depth;
 
 	err = hinic_wq_allocate(hwdev, &nic_io->rq_wq[q_id],
-				HINIC_RQ_WQEBB_SHIFT, nic_io->rq_depth);
+			HINIC_RQ_WQEBB_SHIFT, nic_io->rq_depth, socket_id);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Failed to allocate WQ for RQ");
 		return err;
 	}
 	rq->wq = &nic_io->rq_wq[q_id];
 
-	rq->pi_virt_addr =
-		(volatile u16 *)dma_zalloc_coherent(hwdev, HINIC_PAGE_SIZE,
-						    &rq->pi_dma_addr,
-						    GFP_KERNEL);
+	rq->pi_virt_addr = (volatile u16 *)dma_zalloc_coherent(hwdev,
+			HINIC_PAGE_SIZE, &rq->pi_dma_addr, socket_id);
 	if (!rq->pi_virt_addr) {
 		PMD_DRV_LOG(ERR, "Failed to allocate rq pi virt addr");
 		err = -ENOMEM;
@@ -305,15 +304,13 @@ void hinic_rxq_stats_reset(struct hinic_rxq *rxq)
 	memset(rxq_stats, 0, sizeof(*rxq_stats));
 }
 
-static int hinic_rx_alloc_cqe(struct hinic_rxq *rxq)
+static int hinic_rx_alloc_cqe(struct hinic_rxq *rxq, unsigned int socket_id)
 {
 	size_t cqe_mem_size;
 
 	cqe_mem_size = sizeof(struct hinic_rq_cqe) * rxq->q_depth;
-	rxq->cqe_start_vaddr =
-		dma_zalloc_coherent(rxq->nic_dev->hwdev,
-				    cqe_mem_size, &rxq->cqe_start_paddr,
-				    GFP_KERNEL);
+	rxq->cqe_start_vaddr = dma_zalloc_coherent(rxq->nic_dev->hwdev,
+				cqe_mem_size, &rxq->cqe_start_paddr, socket_id);
 	if (!rxq->cqe_start_vaddr) {
 		PMD_DRV_LOG(ERR, "Allocate cqe dma memory failed");
 		return -ENOMEM;
@@ -369,11 +366,12 @@ int hinic_setup_rx_resources(struct hinic_rxq *rxq)
 	int err, pkts;
 
 	rx_info_sz = rxq->q_depth * sizeof(*rxq->rx_info);
-	rxq->rx_info = kzalloc_aligned(rx_info_sz, GFP_KERNEL);
+	rxq->rx_info = rte_zmalloc_socket("rx_info", rx_info_sz,
+				RTE_CACHE_LINE_SIZE, rxq->socket_id);
 	if (!rxq->rx_info)
 		return -ENOMEM;
 
-	err = hinic_rx_alloc_cqe(rxq);
+	err = hinic_rx_alloc_cqe(rxq, rxq->socket_id);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Allocate rx cqe failed");
 		goto rx_cqe_err;
@@ -392,7 +390,7 @@ int hinic_setup_rx_resources(struct hinic_rxq *rxq)
 	hinic_rx_free_cqe(rxq);
 
 rx_cqe_err:
-	kfree(rxq->rx_info);
+	rte_free(rxq->rx_info);
 	rxq->rx_info = NULL;
 
 	return err;
@@ -404,7 +402,7 @@ void hinic_free_rx_resources(struct hinic_rxq *rxq)
 		return;
 
 	hinic_rx_free_cqe(rxq);
-	kfree(rxq->rx_info);
+	rte_free(rxq->rx_info);
 	rxq->rx_info = NULL;
 }
 
@@ -415,7 +413,8 @@ void hinic_free_all_rx_resources(struct rte_eth_dev *eth_dev)
 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
 
 	for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
-		eth_dev->data->rx_queues[q_id] = NULL;
+		if (eth_dev->data->rx_queues != NULL)
+			eth_dev->data->rx_queues[q_id] = NULL;
 
 		if (nic_dev->rxqs[q_id] == NULL)
 			continue;
@@ -658,6 +657,10 @@ int hinic_rx_configure(struct rte_eth_dev *dev)
 	struct rte_eth_rss_conf rss_conf =
 		dev->data->dev_conf.rx_adv_conf.rss_conf;
 	int err;
+	bool lro_en;
+	int max_lro_size;
+	int lro_wqe_num;
+	int buf_size;
 
 	if (nic_dev->flags & ETH_MQ_RX_RSS_FLAG) {
 		if (rss_conf.rss_hf == 0) {
@@ -683,15 +686,42 @@ int hinic_rx_configure(struct rte_eth_dev *dev)
 	if (err)
 		goto rx_csum_ofl_err;
 
+	/* config lro */
+	lro_en = dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_TCP_LRO ?
+			true : false;
+	max_lro_size = dev->data->dev_conf.rxmode.max_lro_pkt_size;
+	buf_size = nic_dev->hwdev->nic_io->rq_buf_size;
+	lro_wqe_num = max_lro_size / buf_size ? (max_lro_size / buf_size) : 1;
+
+	err = hinic_set_rx_lro(nic_dev->hwdev, lro_en, lro_en, lro_wqe_num);
+	if (err) {
+		PMD_DRV_LOG(ERR, "%s %s lro failed, err: %d, max_lro_size: %d",
+				dev->data->name, lro_en ? "Enable" : "Disable",
+				err, max_lro_size);
+		goto set_rx_lro_err;
+	}
+
 	return 0;
 
+set_rx_lro_err:
 rx_csum_ofl_err:
 rss_config_err:
+
 	hinic_destroy_num_qps(nic_dev);
 
 	return HINIC_ERROR;
 }
 
+static void hinic_rx_remove_lro(struct hinic_nic_dev *nic_dev)
+{
+	int err;
+
+	err = hinic_set_rx_lro(nic_dev->hwdev, false, false, 0);
+	if (err)
+		PMD_DRV_LOG(ERR, "%s disable LRO failed",
+			    nic_dev->proc_dev_name);
+}
+
 void hinic_rx_remove_configure(struct rte_eth_dev *dev)
 {
 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
@@ -700,6 +730,8 @@ void hinic_rx_remove_configure(struct rte_eth_dev *dev)
 		hinic_rss_deinit(nic_dev);
 		hinic_destroy_num_qps(nic_dev);
 	}
+
+	hinic_rx_remove_lro(nic_dev);
 }
 
 void hinic_free_all_rx_mbufs(struct hinic_rxq *rxq)
@@ -958,7 +990,7 @@ u16 hinic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
 	volatile struct hinic_rq_cqe *rx_cqe;
 	u16 rx_buf_len, pkts = 0;
 	u16 sw_ci, ci_mask, wqebb_cnt = 0;
-	u32 pkt_len, status, vlan_len;
+	u32 pkt_len, status, vlan_len, lro_num;
 	u64 rx_bytes = 0;
 	struct hinic_rq_cqe cqe;
 	u32 offload_type, rss_hash;
@@ -1026,6 +1058,13 @@ u16 hinic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
 		rxm->ol_flags |= hinic_rx_rss_hash(offload_type, rss_hash,
 						   &rxm->hash.rss);
 
+		/* lro offload */
+		lro_num = HINIC_GET_RX_NUM_LRO(cqe.status);
+		if (unlikely(lro_num != 0)) {
+			rxm->ol_flags |= PKT_RX_LRO;
+			rxm->tso_segsz = pkt_len / lro_num;
+		}
+
 		/* 6. clear done bit */
 		rx_cqe->status = 0;
 
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_rx.h b/dpdk/drivers/net/hinic/hinic_pmd_rx.h
index 1a80f95af4..8a45f2d9fc 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_rx.h
+++ b/dpdk/drivers/net/hinic/hinic_pmd_rx.h
@@ -35,7 +35,11 @@ struct hinic_rq_cqe {
 	u32 rss_hash;
 
 	u32 rsvd[4];
+#if defined(RTE_ARCH_ARM64)
 } __rte_cache_aligned;
+#else
+};
+#endif
 
 struct hinic_rq_cqe_sect {
 	struct hinic_sge	sge;
@@ -82,6 +86,8 @@ struct hinic_rxq {
 	u16 rx_free_thresh;
 	u16 rxinfo_align_end;
 
+	u32 socket_id;
+
 	unsigned long status;
 	struct hinic_rxq_stats rxq_stats;
 
@@ -121,7 +127,8 @@ void hinic_rx_remove_configure(struct rte_eth_dev *dev);
 
 void hinic_get_func_rx_buf_size(struct hinic_nic_dev *nic_dev);
 
-int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id, u16 rq_depth);
+int hinic_create_rq(struct hinic_hwdev *hwdev, u16 q_id,
+			u16 rq_depth, unsigned int socket_id);
 
 void hinic_destroy_rq(struct hinic_hwdev *hwdev, u16 q_id);
 
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_tx.c b/dpdk/drivers/net/hinic/hinic_pmd_tx.c
index 985540a935..05b23d9924 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_tx.c
+++ b/dpdk/drivers/net/hinic/hinic_pmd_tx.c
@@ -312,6 +312,8 @@ static inline struct rte_mbuf *hinic_copy_tx_mbuf(struct hinic_nic_dev *nic_dev,
 		mbuf = mbuf->next;
 	}
 
+	dst_mbuf->pkt_len = dst_mbuf->data_len;
+
 	return dst_mbuf;
 }
 
@@ -421,7 +423,7 @@ static inline bool hinic_is_tso_sge_valid(struct rte_mbuf *mbuf,
 					  *poff_info,
 					  struct hinic_wqe_info *sqe_info)
 {
-	u32 total_len, limit_len, checked_len, left_len;
+	u32 total_len, limit_len, checked_len, left_len, adjust_mss;
 	u32 i, first_mss_sges, left_sges;
 	struct rte_mbuf *mbuf_head, *mbuf_pre;
 
@@ -431,7 +433,9 @@ static inline bool hinic_is_tso_sge_valid(struct rte_mbuf *mbuf,
 	/* tso sge number validation */
 	if (unlikely(left_sges >= HINIC_NONTSO_PKT_MAX_SGE)) {
 		checked_len = 0;
-		limit_len = mbuf->tso_segsz + poff_info->payload_offset;
+		adjust_mss = mbuf->tso_segsz >= TX_MSS_MIN ?
+				mbuf->tso_segsz : TX_MSS_MIN;
+		limit_len = adjust_mss + poff_info->payload_offset;
 		first_mss_sges = HINIC_NONTSO_PKT_MAX_SGE;
 
 		/* each continues 17 mbufs segmust do one check */
@@ -445,7 +449,7 @@ static inline bool hinic_is_tso_sge_valid(struct rte_mbuf *mbuf,
 				mbuf_pre = mbuf;
 				mbuf = mbuf->next;
 				if (total_len >= limit_len) {
-					limit_len = mbuf_head->tso_segsz;
+					limit_len = adjust_mss;
 					break;
 				}
 			}
@@ -1185,7 +1189,8 @@ void hinic_free_all_tx_resources(struct rte_eth_dev *eth_dev)
 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
 
 	for (q_id = 0; q_id < nic_dev->num_sq; q_id++) {
-		eth_dev->data->tx_queues[q_id] = NULL;
+		if (eth_dev->data->tx_queues != NULL)
+			eth_dev->data->tx_queues[q_id] = NULL;
 
 		if (nic_dev->txqs[q_id] == NULL)
 			continue;
@@ -1216,7 +1221,8 @@ int hinic_setup_tx_resources(struct hinic_txq *txq)
 	u64 tx_info_sz;
 
 	tx_info_sz = txq->q_depth * sizeof(*txq->tx_info);
-	txq->tx_info = kzalloc_aligned(tx_info_sz, GFP_KERNEL);
+	txq->tx_info = rte_zmalloc_socket("tx_info", tx_info_sz,
+			RTE_CACHE_LINE_SIZE, txq->socket_id);
 	if (!txq->tx_info)
 		return -ENOMEM;
 
@@ -1228,11 +1234,12 @@ void hinic_free_tx_resources(struct hinic_txq *txq)
 	if (txq->tx_info == NULL)
 		return;
 
-	kfree(txq->tx_info);
+	rte_free(txq->tx_info);
 	txq->tx_info = NULL;
 }
 
-int hinic_create_sq(struct hinic_hwdev *hwdev, u16 q_id, u16 sq_depth)
+int hinic_create_sq(struct hinic_hwdev *hwdev, u16 q_id,
+			u16 sq_depth, unsigned int socket_id)
 {
 	int err;
 	struct hinic_nic_io *nic_io = hwdev->nic_io;
@@ -1246,7 +1253,8 @@ int hinic_create_sq(struct hinic_hwdev *hwdev, u16 q_id, u16 sq_depth)
 
 	/* alloc wq */
 	err = hinic_wq_allocate(nic_io->hwdev, &nic_io->sq_wq[q_id],
-				HINIC_SQ_WQEBB_SHIFT, nic_io->sq_depth);
+				HINIC_SQ_WQEBB_SHIFT, nic_io->sq_depth,
+				socket_id);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Failed to allocate WQ for SQ");
 		return err;
diff --git a/dpdk/drivers/net/hinic/hinic_pmd_tx.h b/dpdk/drivers/net/hinic/hinic_pmd_tx.h
index a1ca580b1b..dabbc6c1d8 100644
--- a/dpdk/drivers/net/hinic/hinic_pmd_tx.h
+++ b/dpdk/drivers/net/hinic/hinic_pmd_tx.h
@@ -114,6 +114,7 @@ struct hinic_txq {
 	u16 q_id;
 	u16 q_depth;
 	u32 cos;
+	u32 socket_id;
 
 	/* cacheline1 */
 	struct hinic_txq_stats txq_stats;
@@ -137,7 +138,8 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats);
 
 void hinic_txq_stats_reset(struct hinic_txq *txq);
 
-int hinic_create_sq(struct hinic_hwdev *hwdev, u16 q_id, u16 sq_depth);
+int hinic_create_sq(struct hinic_hwdev *hwdev, u16 q_id,
+			u16 sq_depth, unsigned int socket_id);
 
 void hinic_destroy_sq(struct hinic_hwdev *hwdev, u16 q_id);
 
diff --git a/dpdk/drivers/net/hns3/hns3_cmd.c b/dpdk/drivers/net/hns3/hns3_cmd.c
index 65a5af8e4f..dc2473a0f7 100644
--- a/dpdk/drivers/net/hns3/hns3_cmd.c
+++ b/dpdk/drivers/net/hns3/hns3_cmd.c
@@ -215,12 +215,12 @@ hns3_cmd_csq_clean(struct hns3_hw *hw)
 	head = hns3_read_dev(hw, HNS3_CMDQ_TX_HEAD_REG);
 
 	if (!is_valid_csq_clean_head(csq, head)) {
-		struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 		hns3_err(hw, "wrong cmd head (%u, %u-%u)", head,
 			    csq->next_to_use, csq->next_to_clean);
-		rte_atomic16_set(&hw->reset.disable_cmd, 1);
-
-		hns3_schedule_delayed_reset(hns);
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+			rte_atomic16_set(&hw->reset.disable_cmd, 1);
+			hns3_schedule_delayed_reset(HNS3_DEV_HW_TO_ADAPTER(hw));
+		}
 
 		return -EIO;
 	}
@@ -289,7 +289,7 @@ hns3_cmd_convert_err_code(uint16_t desc_ret)
 	case HNS3_CMD_INVALID:
 		return -EBADR;
 	default:
-		return -EIO;
+		return -EREMOTEIO;
 	}
 }
 
@@ -349,11 +349,23 @@ static int hns3_cmd_poll_reply(struct hns3_hw *hw)
 
 /*
  * hns3_cmd_send - send command to command queue
- * @hw: pointer to the hw struct
- * @desc: prefilled descriptor for describing the command
- * @num : the number of descriptors to be sent
  *
- * This is the main send command for command queue, it
+ * @param hw
+ *   pointer to the hw struct
+ * @param desc
+ *   prefilled descriptor for describing the command
+ * @param num
+ *   the number of descriptors to be sent
+ * @return
+ *   - -EBUSY if detect device is in resetting
+ *   - -EIO   if detect cmd csq corrupted (due to reset) or
+ *            there is reset pending
+ *   - -ENOMEM/-ETIME/...(Non-Zero) if other error case
+ *   - Zero   if operation completed successfully
+ *
+ * Note -BUSY/-EIO only used in reset case
+ *
+ * Note this is the main send command for command queue, it
  * sends the queue, cleans the queue, etc
  */
 int
@@ -517,7 +529,7 @@ hns3_cmd_init(struct hns3_hw *hw)
 	return 0;
 
 err_cmd_init:
-	hns3_cmd_uninit(hw);
+	rte_atomic16_set(&hw->reset.disable_cmd, 1);
 	return ret;
 }
 
@@ -541,9 +553,21 @@ hns3_cmd_destroy_queue(struct hns3_hw *hw)
 void
 hns3_cmd_uninit(struct hns3_hw *hw)
 {
+	rte_atomic16_set(&hw->reset.disable_cmd, 1);
+
+	/*
+	 * A delay is added to ensure that the register cleanup operations
+	 * will not be performed concurrently with the firmware command and
+	 * ensure that all the reserved commands are executed.
+	 * Concurrency may occur in two scenarios: asynchronous command and
+	 * timeout command. If the command fails to be executed due to busy
+	 * scheduling, the command will be processed in the next scheduling
+	 * of the firmware.
+	 */
+	rte_delay_ms(HNS3_CMDQ_CLEAR_WAIT_TIME);
+
 	rte_spinlock_lock(&hw->cmq.csq.lock);
 	rte_spinlock_lock(&hw->cmq.crq.lock);
-	rte_atomic16_set(&hw->reset.disable_cmd, 1);
 	hns3_cmd_clear_regs(hw);
 	rte_spinlock_unlock(&hw->cmq.crq.lock);
 	rte_spinlock_unlock(&hw->cmq.csq.lock);
diff --git a/dpdk/drivers/net/hns3/hns3_cmd.h b/dpdk/drivers/net/hns3/hns3_cmd.h
index be0ecbe86b..5a7b7a44e0 100644
--- a/dpdk/drivers/net/hns3/hns3_cmd.h
+++ b/dpdk/drivers/net/hns3/hns3_cmd.h
@@ -6,6 +6,7 @@
 #define _HNS3_CMD_H_
 
 #define HNS3_CMDQ_TX_TIMEOUT		30000
+#define HNS3_CMDQ_CLEAR_WAIT_TIME	200
 #define HNS3_CMDQ_RX_INVLD_B		0
 #define HNS3_CMDQ_RX_OUTVLD_B		1
 #define HNS3_CMD_DESC_ALIGNMENT		4096
@@ -79,6 +80,7 @@ enum hns3_opcode_type {
 	HNS3_OPC_GBL_RST_STATUS         = 0x0021,
 	HNS3_OPC_QUERY_FUNC_STATUS      = 0x0022,
 	HNS3_OPC_QUERY_PF_RSRC          = 0x0023,
+	HNS3_OPC_QUERY_VF_RSRC          = 0x0024,
 	HNS3_OPC_GET_CFG_PARAM          = 0x0025,
 	HNS3_OPC_PF_RST_DONE            = 0x0026,
 
@@ -206,9 +208,16 @@ enum hns3_opcode_type {
 	HNS3_OPC_FD_AD_OP               = 0x1204,
 	HNS3_OPC_FD_COUNTER_OP          = 0x1205,
 
+	/* Clear hardware state command */
+	HNS3_OPC_CLEAR_HW_STATE         = 0x700B,
+
 	/* SFP command */
 	HNS3_OPC_SFP_GET_SPEED          = 0x7104,
 
+	/* Interrupts commands */
+	HNS3_OPC_ADD_RING_TO_VECTOR	= 0x1503,
+	HNS3_OPC_DEL_RING_TO_VECTOR	= 0x1504,
+
 	/* Error INT commands */
 	HNS3_QUERY_MSIX_INT_STS_BD_NUM          = 0x1513,
 	HNS3_QUERY_CLEAR_ALL_MPF_MSIX_INT       = 0x1514,
@@ -333,8 +342,9 @@ struct hns3_func_status_cmd {
 	uint8_t rsv[2];
 };
 
-#define HNS3_PF_VEC_NUM_S		0
-#define HNS3_PF_VEC_NUM_M		GENMASK(7, 0)
+#define HNS3_VEC_NUM_S		0
+#define HNS3_VEC_NUM_M		GENMASK(7, 0)
+#define HNS3_MIN_VECTOR_NUM	2 /* one for msi-x, another for IO */
 struct hns3_pf_res_cmd {
 	uint16_t tqp_num;
 	uint16_t buf_size;
@@ -347,6 +357,15 @@ struct hns3_pf_res_cmd {
 	uint32_t rsv[2];
 };
 
+struct hns3_vf_res_cmd {
+	uint16_t tqp_num;
+	uint16_t reserved;
+	uint16_t msixcap_localid_ba_nic;
+	uint16_t msixcap_localid_ba_rocee;
+	uint16_t vf_intr_vector_number;
+	uint16_t rsv[7];
+};
+
 #define HNS3_UMV_SPC_ALC_B	0
 struct hns3_umv_spc_alc_cmd {
 	uint8_t allocate;
@@ -673,6 +692,36 @@ struct hns3_tqp_map_cmd {
 	uint8_t rsv[18];
 };
 
+enum hns3_ring_type {
+	HNS3_RING_TYPE_TX,
+	HNS3_RING_TYPE_RX
+};
+
+enum hns3_int_gl_idx {
+	HNS3_RING_GL_RX,
+	HNS3_RING_GL_TX,
+	HNS3_RING_GL_IMMEDIATE = 3
+};
+
+#define HNS3_RING_GL_IDX_S	0
+#define HNS3_RING_GL_IDX_M	GENMASK(1, 0)
+
+#define HNS3_VECTOR_ELEMENTS_PER_CMD	10
+
+#define HNS3_INT_TYPE_S		0
+#define HNS3_INT_TYPE_M		GENMASK(1, 0)
+#define HNS3_TQP_ID_S		2
+#define HNS3_TQP_ID_M		GENMASK(12, 2)
+#define HNS3_INT_GL_IDX_S	13
+#define HNS3_INT_GL_IDX_M	GENMASK(14, 13)
+struct hns3_ctrl_vector_chain_cmd {
+	uint8_t int_vector_id;
+	uint8_t int_cause_num;
+	uint16_t tqp_type_and_id[HNS3_VECTOR_ELEMENTS_PER_CMD];
+	uint8_t vfid;
+	uint8_t rsv;
+};
+
 struct hns3_config_max_frm_size_cmd {
 	uint16_t max_frm_size;
 	uint8_t min_frm_size;
diff --git a/dpdk/drivers/net/hns3/hns3_dcb.c b/dpdk/drivers/net/hns3/hns3_dcb.c
index 19235dfb92..62d8930c15 100644
--- a/dpdk/drivers/net/hns3/hns3_dcb.c
+++ b/dpdk/drivers/net/hns3/hns3_dcb.c
@@ -337,7 +337,7 @@ hns3_dcb_get_shapping_para(uint8_t ir_b, uint8_t ir_u, uint8_t ir_s,
 	return shapping_para;
 }
 
-static int
+int
 hns3_dcb_port_shaper_cfg(struct hns3_hw *hw)
 {
 	struct hns3_port_shapping_cmd *shap_cfg_cmd;
@@ -578,17 +578,48 @@ hns3_dcb_pri_shaper_cfg(struct hns3_hw *hw)
 }
 
 void
-hns3_tc_queue_mapping_cfg(struct hns3_hw *hw)
+hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q)
+{
+	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
+	uint16_t rx_qnum_per_tc;
+	int i;
+
+	rx_qnum_per_tc = nb_rx_q / hw->num_tc;
+	rx_qnum_per_tc = RTE_MIN(hw->rss_size_max, rx_qnum_per_tc);
+	if (hw->alloc_rss_size != rx_qnum_per_tc) {
+		hns3_info(hw, "rss size changes from %u to %u",
+			  hw->alloc_rss_size, rx_qnum_per_tc);
+		hw->alloc_rss_size = rx_qnum_per_tc;
+	}
+	hw->used_rx_queues = hw->num_tc * hw->alloc_rss_size;
+
+	/*
+	 * When rss size is changed, we need to update rss redirection table
+	 * maintained by driver. Besides, during the entire reset process, we
+	 * need to ensure that the rss table information are not overwritten
+	 * and configured directly to the hardware in the RESET_STAGE_RESTORE
+	 * stage of the reset process.
+	 */
+	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+		for (i = 0; i < HNS3_RSS_IND_TBL_SIZE; i++)
+			rss_cfg->rss_indirection_tbl[i] =
+							i % hw->alloc_rss_size;
+	}
+}
+
+void
+hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue)
 {
 	struct hns3_tc_queue_info *tc_queue;
 	uint8_t i;
 
+	hw->tx_qnum_per_tc = nb_queue / hw->num_tc;
 	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
 		tc_queue = &hw->tc_queue[i];
 		if (hw->hw_tc_map & BIT(i) && i < hw->num_tc) {
 			tc_queue->enable = true;
-			tc_queue->tqp_offset = i * hw->alloc_rss_size;
-			tc_queue->tqp_count = hw->alloc_rss_size;
+			tc_queue->tqp_offset = i * hw->tx_qnum_per_tc;
+			tc_queue->tqp_count = hw->tx_qnum_per_tc;
 			tc_queue->tc = i;
 		} else {
 			/* Set to default queue if TC is disable */
@@ -598,30 +629,22 @@ hns3_tc_queue_mapping_cfg(struct hns3_hw *hw)
 			tc_queue->tc = 0;
 		}
 	}
+	hw->used_tx_queues = hw->num_tc * hw->tx_qnum_per_tc;
 }
 
 static void
-hns3_dcb_update_tc_queue_mapping(struct hns3_hw *hw, uint16_t queue_num)
+hns3_dcb_update_tc_queue_mapping(struct hns3_hw *hw, uint16_t nb_rx_q,
+				 uint16_t nb_tx_q)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct hns3_pf *pf = &hns->pf;
-	uint16_t tqpnum_per_tc;
-	uint16_t alloc_tqps;
 
-	alloc_tqps = RTE_MIN(hw->tqps_num, queue_num);
-	hw->num_tc = RTE_MIN(alloc_tqps, hw->dcb_info.num_tc);
-	tqpnum_per_tc = RTE_MIN(hw->rss_size_max, alloc_tqps / hw->num_tc);
+	hw->num_tc = hw->dcb_info.num_tc;
+	hns3_set_rss_size(hw, nb_rx_q);
+	hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
 
-	if (hw->alloc_rss_size != tqpnum_per_tc) {
-		PMD_INIT_LOG(INFO, "rss size changes from %d to %d",
-			     hw->alloc_rss_size, tqpnum_per_tc);
-		hw->alloc_rss_size = tqpnum_per_tc;
-	}
-	hw->alloc_tqps = hw->num_tc * hw->alloc_rss_size;
-
-	hns3_tc_queue_mapping_cfg(hw);
-
-	memcpy(pf->prio_tc, hw->dcb_info.prio_tc, HNS3_MAX_USER_PRIO);
+	if (!hns->is_vf)
+		memcpy(pf->prio_tc, hw->dcb_info.prio_tc, HNS3_MAX_USER_PRIO);
 }
 
 int
@@ -1235,6 +1258,8 @@ hns3_dcb_cfg_validate(struct hns3_adapter *hns, uint8_t *tc, bool *changed)
 {
 	struct rte_eth_dcb_rx_conf *dcb_rx_conf;
 	struct hns3_hw *hw = &hns->hw;
+	uint16_t nb_rx_q = hw->data->nb_rx_queues;
+	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	uint8_t max_tc = 0;
 	uint8_t pfc_en;
 	int i;
@@ -1260,6 +1285,10 @@ hns3_dcb_cfg_validate(struct hns3_adapter *hns, uint8_t *tc, bool *changed)
 	pfc_en = RTE_LEN2MASK((uint8_t)dcb_rx_conf->nb_tcs, uint8_t);
 	if (hw->dcb_info.pfc_en != pfc_en)
 		*changed = true;
+
+	/* tx/rx queue number is reconfigured. */
+	if (nb_rx_q != hw->used_rx_queues || nb_tx_q != hw->used_tx_queues)
+		*changed = true;
 }
 
 static void
@@ -1309,20 +1338,35 @@ hns3_dcb_info_cfg(struct hns3_adapter *hns)
 	for (i = 0; i < HNS3_MAX_USER_PRIO; i++)
 		hw->dcb_info.prio_tc[i] = dcb_rx_conf->dcb_tc[i];
 
-	hns3_dcb_update_tc_queue_mapping(hw, hw->data->nb_rx_queues);
+	hns3_dcb_update_tc_queue_mapping(hw, hw->data->nb_rx_queues,
+					 hw->data->nb_tx_queues);
 }
 
-static void
+static int
 hns3_dcb_info_update(struct hns3_adapter *hns, uint8_t num_tc)
 {
 	struct hns3_pf *pf = &hns->pf;
 	struct hns3_hw *hw = &hns->hw;
+	uint16_t nb_rx_q = hw->data->nb_rx_queues;
+	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	uint8_t bit_map = 0;
 	uint8_t i;
 
 	if (pf->tx_sch_mode != HNS3_FLAG_TC_BASE_SCH_MODE &&
 	    hw->dcb_info.num_pg != 1)
-		return;
+		return -EINVAL;
+
+	if (nb_rx_q < num_tc) {
+		hns3_err(hw, "number of Rx queues(%d) is less than tcs(%d).",
+			 nb_rx_q, num_tc);
+		return -EINVAL;
+	}
+
+	if (nb_tx_q < num_tc) {
+		hns3_err(hw, "number of Tx queues(%d) is less than tcs(%d).",
+			 nb_tx_q, num_tc);
+		return -EINVAL;
+	}
 
 	/* Currently not support uncontinuous tc */
 	hw->dcb_info.num_tc = num_tc;
@@ -1333,10 +1377,10 @@ hns3_dcb_info_update(struct hns3_adapter *hns, uint8_t num_tc)
 		bit_map = 1;
 		hw->dcb_info.num_tc = 1;
 	}
-
 	hw->hw_tc_map = bit_map;
-
 	hns3_dcb_info_cfg(hns);
+
+	return 0;
 }
 
 static int
@@ -1422,10 +1466,15 @@ hns3_dcb_configure(struct hns3_adapter *hns)
 
 	hns3_dcb_cfg_validate(hns, &num_tc, &map_changed);
 	if (map_changed || rte_atomic16_read(&hw->reset.resetting)) {
-		hns3_dcb_info_update(hns, num_tc);
+		ret = hns3_dcb_info_update(hns, num_tc);
+		if (ret) {
+			hns3_err(hw, "dcb info update failed: %d", ret);
+			return ret;
+		}
+
 		ret = hns3_dcb_hw_configure(hns);
 		if (ret) {
-			hns3_err(hw, "dcb sw configure fails: %d", ret);
+			hns3_err(hw, "dcb sw configure failed: %d", ret);
 			return ret;
 		}
 	}
@@ -1479,7 +1528,8 @@ hns3_dcb_init(struct hns3_hw *hw)
 			hns3_err(hw, "dcb info init failed: %d", ret);
 			return ret;
 		}
-		hns3_dcb_update_tc_queue_mapping(hw, hw->tqps_num);
+		hns3_dcb_update_tc_queue_mapping(hw, hw->tqps_num,
+						 hw->tqps_num);
 	}
 
 	/*
@@ -1502,10 +1552,11 @@ static int
 hns3_update_queue_map_configure(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	uint16_t queue_num = hw->data->nb_rx_queues;
+	uint16_t nb_rx_q = hw->data->nb_rx_queues;
+	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	int ret;
 
-	hns3_dcb_update_tc_queue_mapping(hw, queue_num);
+	hns3_dcb_update_tc_queue_mapping(hw, nb_rx_q, nb_tx_q);
 	ret = hns3_q_to_qs_map(hw);
 	if (ret) {
 		hns3_err(hw, "failed to map nq to qs! ret = %d", ret);
diff --git a/dpdk/drivers/net/hns3/hns3_dcb.h b/dpdk/drivers/net/hns3/hns3_dcb.h
index 9ec4e704b3..fe67d3a466 100644
--- a/dpdk/drivers/net/hns3/hns3_dcb.h
+++ b/dpdk/drivers/net/hns3/hns3_dcb.h
@@ -24,16 +24,19 @@ enum hns3_shap_bucket {
 struct hns3_priority_weight_cmd {
 	uint8_t pri_id;
 	uint8_t dwrr;
+	uint8_t rsvd[22];
 };
 
 struct hns3_qs_weight_cmd {
 	uint16_t qs_id;
 	uint8_t dwrr;
+	uint8_t rsvd[21];
 };
 
 struct hns3_pg_weight_cmd {
 	uint8_t pg_id;
 	uint8_t dwrr;
+	uint8_t rsvd[22];
 };
 
 struct hns3_ets_tc_weight_cmd {
@@ -48,6 +51,7 @@ struct hns3_qs_to_pri_link_cmd {
 	uint8_t priority;
 #define HNS3_DCB_QS_PRI_LINK_VLD_MSK	BIT(0)
 	uint8_t link_vld;
+	uint8_t rsvd1[18];
 };
 
 struct hns3_nq_to_qs_link_cmd {
@@ -55,6 +59,7 @@ struct hns3_nq_to_qs_link_cmd {
 	uint16_t rsvd;
 #define HNS3_DCB_Q_QS_LINK_VLD_MSK	BIT(10)
 	uint16_t qset_id;
+	uint8_t rsvd1[18];
 };
 
 #define HNS3_DCB_SHAP_IR_B_MSK  GENMASK(7, 0)
@@ -72,12 +77,14 @@ struct hns3_pri_shapping_cmd {
 	uint8_t pri_id;
 	uint8_t rsvd[3];
 	uint32_t pri_shapping_para;
+	uint32_t rsvd1[4];
 };
 
 struct hns3_pg_shapping_cmd {
 	uint8_t pg_id;
 	uint8_t rsvd[3];
 	uint32_t pg_shapping_para;
+	uint32_t rsvd1[4];
 };
 
 #define HNS3_BP_GRP_NUM		32
@@ -90,16 +97,18 @@ struct hns3_bp_to_qs_map_cmd {
 	uint8_t rsvd[2];
 	uint8_t qs_group_id;
 	uint32_t qs_bit_map;
-	uint32_t rsvd1;
+	uint32_t rsvd1[4];
 };
 
 struct hns3_pfc_en_cmd {
 	uint8_t tx_rx_en_bitmap;
 	uint8_t pri_en_bitmap;
+	uint8_t rsvd[22];
 };
 
 struct hns3_port_shapping_cmd {
 	uint32_t port_shapping_para;
+	uint32_t rsvd[5];
 };
 
 struct hns3_cfg_pause_param_cmd {
@@ -117,6 +126,7 @@ struct hns3_pg_to_pri_link_cmd {
 	uint8_t pg_id;
 	uint8_t rsvd1[3];
 	uint8_t pri_bit_map;
+	uint8_t rsvd2[19];
 };
 
 enum hns3_shaper_level {
@@ -159,8 +169,11 @@ hns3_fc_enable(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf);
 int
 hns3_dcb_pfc_enable(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf);
 
-void hns3_tc_queue_mapping_cfg(struct hns3_hw *hw);
+void hns3_set_rss_size(struct hns3_hw *hw, uint16_t nb_rx_q);
+
+void hns3_tc_queue_mapping_cfg(struct hns3_hw *hw, uint16_t nb_queue);
 
 int hns3_dcb_cfg_update(struct hns3_adapter *hns);
+int hns3_dcb_port_shaper_cfg(struct hns3_hw *hw);
 
 #endif /* _HNS3_DCB_H_ */
diff --git a/dpdk/drivers/net/hns3/hns3_ethdev.c b/dpdk/drivers/net/hns3/hns3_ethdev.c
index 72315718a8..66be58dc26 100644
--- a/dpdk/drivers/net/hns3/hns3_ethdev.c
+++ b/dpdk/drivers/net/hns3/hns3_ethdev.c
@@ -35,9 +35,7 @@
 #define HNS3_DEFAULT_PORT_CONF_QUEUES_NUM	1
 
 #define HNS3_SERVICE_INTERVAL		1000000 /* us */
-#define HNS3_PORT_BASE_VLAN_DISABLE	0
-#define HNS3_PORT_BASE_VLAN_ENABLE	1
-#define HNS3_INVLID_PVID		0xFFFF
+#define HNS3_INVALID_PVID		0xFFFF
 
 #define HNS3_FILTER_TYPE_VF		0
 #define HNS3_FILTER_TYPE_PORT		1
@@ -77,6 +75,12 @@ static enum hns3_reset_level hns3_get_reset_level(struct hns3_adapter *hns,
 static int hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 static int hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid,
 				    int on);
+static int hns3_update_speed_duplex(struct rte_eth_dev *eth_dev);
+
+static int hns3_add_mc_addr(struct hns3_hw *hw,
+			    struct rte_ether_addr *mac_addr);
+static int hns3_remove_mc_addr(struct hns3_hw *hw,
+			    struct rte_ether_addr *mac_addr);
 
 static void
 hns3_pf_disable_irq0(struct hns3_hw *hw)
@@ -218,6 +222,8 @@ hns3_interrupt_handler(void *param)
 		hns3_schedule_reset(hns);
 	} else if (event_cause == HNS3_VECTOR0_EVENT_RST)
 		hns3_schedule_reset(hns);
+	else if (event_cause == HNS3_VECTOR0_EVENT_MBX)
+		hns3_dev_handle_mbx_msg(hw);
 	else
 		hns3_err(hw, "Received unknown event");
 
@@ -303,15 +309,14 @@ static int
 hns3_restore_vlan_table(struct hns3_adapter *hns)
 {
 	struct hns3_user_vlan_table *vlan_entry;
+	struct hns3_hw *hw = &hns->hw;
 	struct hns3_pf *pf = &hns->pf;
 	uint16_t vlan_id;
 	int ret = 0;
 
-	if (pf->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_ENABLE) {
-		ret = hns3_vlan_pvid_configure(hns, pf->port_base_vlan_cfg.pvid,
-					       1);
-		return ret;
-	}
+	if (hw->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_ENABLE)
+		return hns3_vlan_pvid_configure(hns,
+						hw->port_base_vlan_cfg.pvid, 1);
 
 	LIST_FOREACH(vlan_entry, &pf->vlan_list, next) {
 		if (vlan_entry->hd_tbl_status) {
@@ -328,13 +333,14 @@ hns3_restore_vlan_table(struct hns3_adapter *hns)
 static int
 hns3_vlan_filter_configure(struct hns3_adapter *hns, uint16_t vlan_id, int on)
 {
-	struct hns3_pf *pf = &hns->pf;
+	struct hns3_hw *hw = &hns->hw;
 	bool writen_to_tbl = false;
 	int ret = 0;
 
 	/*
-	 * When vlan filter is enabled, hardware regards vlan id 0 as the entry
-	 * for normal packet, deleting vlan id 0 is not allowed.
+	 * When vlan filter is enabled, hardware regards packets without vlan
+	 * as packets with vlan 0. So, to receive packets without vlan, vlan id
+	 * 0 is not allowed to be removed by rte_eth_dev_vlan_filter.
 	 */
 	if (on == 0 && vlan_id == 0)
 		return 0;
@@ -346,12 +352,12 @@ hns3_vlan_filter_configure(struct hns3_adapter *hns, uint16_t vlan_id, int on)
 	 * vlan list. The vlan id in vlan list will be writen in vlan filter
 	 * table until port base vlan disabled
 	 */
-	if (pf->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_DISABLE) {
+	if (hw->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_DISABLE) {
 		ret = hns3_set_port_vlan_filter(hns, vlan_id, on);
 		writen_to_tbl = true;
 	}
 
-	if (ret == 0 && vlan_id) {
+	if (ret == 0) {
 		if (on)
 			hns3_add_dev_vlan_table(hns, vlan_id, writen_to_tbl);
 		else
@@ -500,11 +506,10 @@ static int
 hns3_en_hw_strip_rxvtag(struct hns3_adapter *hns, bool enable)
 {
 	struct hns3_rx_vtag_cfg rxvlan_cfg;
-	struct hns3_pf *pf = &hns->pf;
 	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
-	if (pf->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_DISABLE) {
+	if (hw->port_base_vlan_cfg.state == HNS3_PORT_BASE_VLAN_DISABLE) {
 		rxvlan_cfg.strip_tag1_en = false;
 		rxvlan_cfg.strip_tag2_en = enable;
 	} else {
@@ -550,7 +555,7 @@ hns3_set_vlan_filter_ctrl(struct hns3_hw *hw, uint8_t vlan_type,
 }
 
 static int
-hns3_enable_vlan_filter(struct hns3_adapter *hns, bool enable)
+hns3_vlan_filter_init(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	int ret;
@@ -558,14 +563,29 @@ hns3_enable_vlan_filter(struct hns3_adapter *hns, bool enable)
 	ret = hns3_set_vlan_filter_ctrl(hw, HNS3_FILTER_TYPE_VF,
 					HNS3_FILTER_FE_EGRESS, false, 0);
 	if (ret) {
-		hns3_err(hw, "hns3 enable filter fail, ret =%d", ret);
+		hns3_err(hw, "failed to init vf vlan filter, ret = %d", ret);
 		return ret;
 	}
 
+	ret = hns3_set_vlan_filter_ctrl(hw, HNS3_FILTER_TYPE_PORT,
+					HNS3_FILTER_FE_INGRESS, false, 0);
+	if (ret)
+		hns3_err(hw, "failed to init port vlan filter, ret = %d", ret);
+
+	return ret;
+}
+
+static int
+hns3_enable_vlan_filter(struct hns3_adapter *hns, bool enable)
+{
+	struct hns3_hw *hw = &hns->hw;
+	int ret;
+
 	ret = hns3_set_vlan_filter_ctrl(hw, HNS3_FILTER_TYPE_PORT,
 					HNS3_FILTER_FE_INGRESS, enable, 0);
 	if (ret)
-		hns3_err(hw, "hns3 enable filter fail, ret =%d", ret);
+		hns3_err(hw, "failed to %s port vlan filter, ret = %d",
+			 enable ? "enable" : "disable", ret);
 
 	return ret;
 }
@@ -583,6 +603,23 @@ hns3_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	rte_spinlock_lock(&hw->lock);
 	rxmode = &dev->data->dev_conf.rxmode;
 	tmp_mask = (unsigned int)mask;
+	if (tmp_mask & ETH_VLAN_FILTER_MASK) {
+		/* ignore vlan filter configuration during promiscuous mode */
+		if (!dev->data->promiscuous) {
+			/* Enable or disable VLAN filter */
+			enable = rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER ?
+				 true : false;
+
+			ret = hns3_enable_vlan_filter(hns, enable);
+			if (ret) {
+				rte_spinlock_unlock(&hw->lock);
+				hns3_err(hw, "failed to %s rx filter, ret = %d",
+					 enable ? "enable" : "disable", ret);
+				return ret;
+			}
+		}
+	}
+
 	if (tmp_mask & ETH_VLAN_STRIP_MASK) {
 		/* Enable or disable VLAN stripping */
 		enable = rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP ?
@@ -591,7 +628,8 @@ hns3_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 		ret = hns3_en_hw_strip_rxvtag(hns, enable);
 		if (ret) {
 			rte_spinlock_unlock(&hw->lock);
-			hns3_err(hw, "failed to enable rx strip, ret =%d", ret);
+			hns3_err(hw, "failed to %s rx strip, ret = %d",
+				 enable ? "enable" : "disable", ret);
 			return ret;
 		}
 	}
@@ -683,16 +721,6 @@ hns3_vlan_txvlan_cfg(struct hns3_adapter *hns, uint16_t port_base_vlan_state,
 	return ret;
 }
 
-static void
-hns3_store_port_base_vlan_info(struct hns3_adapter *hns, uint16_t pvid, int on)
-{
-	struct hns3_pf *pf = &hns->pf;
-
-	pf->port_base_vlan_cfg.state = on ?
-	    HNS3_PORT_BASE_VLAN_ENABLE : HNS3_PORT_BASE_VLAN_DISABLE;
-
-	pf->port_base_vlan_cfg.pvid = pvid;
-}
 
 static void
 hns3_rm_all_vlan_table(struct hns3_adapter *hns, bool is_del_list)
@@ -701,10 +729,10 @@ hns3_rm_all_vlan_table(struct hns3_adapter *hns, bool is_del_list)
 	struct hns3_pf *pf = &hns->pf;
 
 	LIST_FOREACH(vlan_entry, &pf->vlan_list, next) {
-		if (vlan_entry->hd_tbl_status)
+		if (vlan_entry->hd_tbl_status) {
 			hns3_set_port_vlan_filter(hns, vlan_entry->vlan_id, 0);
-
-		vlan_entry->hd_tbl_status = false;
+			vlan_entry->hd_tbl_status = false;
+		}
 	}
 
 	if (is_del_list) {
@@ -724,10 +752,10 @@ hns3_add_all_vlan_table(struct hns3_adapter *hns)
 	struct hns3_pf *pf = &hns->pf;
 
 	LIST_FOREACH(vlan_entry, &pf->vlan_list, next) {
-		if (!vlan_entry->hd_tbl_status)
+		if (!vlan_entry->hd_tbl_status) {
 			hns3_set_port_vlan_filter(hns, vlan_entry->vlan_id, 1);
-
-		vlan_entry->hd_tbl_status = true;
+			vlan_entry->hd_tbl_status = true;
+		}
 	}
 }
 
@@ -735,13 +763,12 @@ static void
 hns3_remove_all_vlan_table(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	struct hns3_pf *pf = &hns->pf;
 	int ret;
 
 	hns3_rm_all_vlan_table(hns, true);
-	if (pf->port_base_vlan_cfg.pvid != HNS3_INVLID_PVID) {
+	if (hw->port_base_vlan_cfg.pvid != HNS3_INVALID_PVID) {
 		ret = hns3_set_port_vlan_filter(hns,
-						pf->port_base_vlan_cfg.pvid, 0);
+						hw->port_base_vlan_cfg.pvid, 0);
 		if (ret) {
 			hns3_err(hw, "Failed to remove all vlan table, ret =%d",
 				 ret);
@@ -752,63 +779,66 @@ hns3_remove_all_vlan_table(struct hns3_adapter *hns)
 
 static int
 hns3_update_vlan_filter_entries(struct hns3_adapter *hns,
-				uint16_t port_base_vlan_state,
-				uint16_t new_pvid, uint16_t old_pvid)
+			uint16_t port_base_vlan_state, uint16_t new_pvid)
 {
-	struct hns3_pf *pf = &hns->pf;
 	struct hns3_hw *hw = &hns->hw;
-	int ret = 0;
+	uint16_t old_pvid;
+	int ret;
 
 	if (port_base_vlan_state == HNS3_PORT_BASE_VLAN_ENABLE) {
-		if (old_pvid != HNS3_INVLID_PVID && old_pvid != 0) {
+		old_pvid = hw->port_base_vlan_cfg.pvid;
+		if (old_pvid != HNS3_INVALID_PVID) {
 			ret = hns3_set_port_vlan_filter(hns, old_pvid, 0);
 			if (ret) {
-				hns3_err(hw,
-					 "Failed to clear clear old pvid filter, ret =%d",
-					 ret);
+				hns3_err(hw, "failed to remove old pvid %u, "
+						"ret = %d", old_pvid, ret);
 				return ret;
 			}
 		}
 
 		hns3_rm_all_vlan_table(hns, false);
-		return hns3_set_port_vlan_filter(hns, new_pvid, 1);
-	}
-
-	if (new_pvid != 0) {
+		ret = hns3_set_port_vlan_filter(hns, new_pvid, 1);
+		if (ret) {
+			hns3_err(hw, "failed to add new pvid %u, ret = %d",
+					new_pvid, ret);
+			return ret;
+		}
+	} else {
 		ret = hns3_set_port_vlan_filter(hns, new_pvid, 0);
 		if (ret) {
-			hns3_err(hw, "Failed to set port vlan filter, ret =%d",
-				 ret);
+			hns3_err(hw, "failed to remove pvid %u, ret = %d",
+					new_pvid, ret);
 			return ret;
 		}
-	}
 
-	if (new_pvid == pf->port_base_vlan_cfg.pvid)
 		hns3_add_all_vlan_table(hns);
-
-	return ret;
+	}
+	return 0;
 }
 
 static int
-hns3_en_rx_strip_all(struct hns3_adapter *hns, int on)
+hns3_en_pvid_strip(struct hns3_adapter *hns, int on)
 {
+	struct hns3_rx_vtag_cfg *old_cfg = &hns->pf.vtag_config.rx_vcfg;
 	struct hns3_rx_vtag_cfg rx_vlan_cfg;
-	struct hns3_hw *hw = &hns->hw;
 	bool rx_strip_en;
 	int ret;
 
-	rx_strip_en = on ? true : false;
-	rx_vlan_cfg.strip_tag1_en = rx_strip_en;
-	rx_vlan_cfg.strip_tag2_en = rx_strip_en;
+	rx_strip_en = old_cfg->rx_vlan_offload_en ? true : false;
+	if (on) {
+		rx_vlan_cfg.strip_tag1_en = rx_strip_en;
+		rx_vlan_cfg.strip_tag2_en = true;
+	} else {
+		rx_vlan_cfg.strip_tag1_en = false;
+		rx_vlan_cfg.strip_tag2_en = rx_strip_en;
+	}
 	rx_vlan_cfg.vlan1_vlan_prionly = false;
 	rx_vlan_cfg.vlan2_vlan_prionly = false;
-	rx_vlan_cfg.rx_vlan_offload_en = rx_strip_en;
+	rx_vlan_cfg.rx_vlan_offload_en = old_cfg->rx_vlan_offload_en;
 
 	ret = hns3_set_vlan_rx_offload_cfg(hns, &rx_vlan_cfg);
-	if (ret) {
-		hns3_err(hw, "enable strip rx failed, ret =%d", ret);
+	if (ret)
 		return ret;
-	}
 
 	hns3_update_rx_offload_cfg(hns, &rx_vlan_cfg);
 	return ret;
@@ -817,17 +847,15 @@ hns3_en_rx_strip_all(struct hns3_adapter *hns, int on)
 static int
 hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid, int on)
 {
-	struct hns3_pf *pf = &hns->pf;
 	struct hns3_hw *hw = &hns->hw;
 	uint16_t port_base_vlan_state;
-	uint16_t old_pvid;
 	int ret;
 
-	if (on == 0 && pvid != pf->port_base_vlan_cfg.pvid) {
-		if (pf->port_base_vlan_cfg.pvid != HNS3_INVLID_PVID)
+	if (on == 0 && pvid != hw->port_base_vlan_cfg.pvid) {
+		if (hw->port_base_vlan_cfg.pvid != HNS3_INVALID_PVID)
 			hns3_warn(hw, "Invalid operation! As current pvid set "
 				  "is %u, disable pvid %u is invalid",
-				  pf->port_base_vlan_cfg.pvid, pvid);
+				  hw->port_base_vlan_cfg.pvid, pvid);
 		return 0;
 	}
 
@@ -835,29 +863,30 @@ hns3_vlan_pvid_configure(struct hns3_adapter *hns, uint16_t pvid, int on)
 				    HNS3_PORT_BASE_VLAN_DISABLE;
 	ret = hns3_vlan_txvlan_cfg(hns, port_base_vlan_state, pvid);
 	if (ret) {
-		hns3_err(hw, "Failed to config tx vlan, ret =%d", ret);
+		hns3_err(hw, "failed to config tx vlan for pvid, ret = %d",
+			 ret);
 		return ret;
 	}
 
-	ret = hns3_en_rx_strip_all(hns, on);
+	ret = hns3_en_pvid_strip(hns, on);
 	if (ret) {
-		hns3_err(hw, "Failed to config rx vlan strip, ret =%d", ret);
+		hns3_err(hw, "failed to config rx vlan strip for pvid, "
+			 "ret = %d", ret);
 		return ret;
 	}
 
-	if (pvid == HNS3_INVLID_PVID)
+	if (pvid == HNS3_INVALID_PVID)
 		goto out;
-	old_pvid = pf->port_base_vlan_cfg.pvid;
-	ret = hns3_update_vlan_filter_entries(hns, port_base_vlan_state, pvid,
-					      old_pvid);
+	ret = hns3_update_vlan_filter_entries(hns, port_base_vlan_state, pvid);
 	if (ret) {
-		hns3_err(hw, "Failed to update vlan filter entries, ret =%d",
+		hns3_err(hw, "failed to update vlan filter entries, ret = %d",
 			 ret);
 		return ret;
 	}
 
 out:
-	hns3_store_port_base_vlan_info(hns, pvid, on);
+	hw->port_base_vlan_cfg.state = port_base_vlan_state;
+	hw->port_base_vlan_cfg.pvid = on ? pvid : HNS3_INVALID_PVID;
 	return ret;
 }
 
@@ -866,22 +895,37 @@ hns3_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, int on)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
+	bool pvid_en_state_change;
+	uint16_t pvid_state;
 	int ret;
 
+	if (pvid > RTE_ETHER_MAX_VLAN_ID) {
+		hns3_err(hw, "Invalid vlan_id = %u > %d", pvid,
+			 RTE_ETHER_MAX_VLAN_ID);
+		return -EINVAL;
+	}
+
+	/*
+	 * If PVID configuration state change, should refresh the PVID
+	 * configuration state in struct hns3_tx_queue/hns3_rx_queue.
+	 */
+	pvid_state = hw->port_base_vlan_cfg.state;
+	if ((on && pvid_state == HNS3_PORT_BASE_VLAN_ENABLE) ||
+	    (!on && pvid_state == HNS3_PORT_BASE_VLAN_DISABLE))
+		pvid_en_state_change = false;
+	else
+		pvid_en_state_change = true;
+
 	rte_spinlock_lock(&hw->lock);
 	ret = hns3_vlan_pvid_configure(hns, pvid, on);
 	rte_spinlock_unlock(&hw->lock);
-	return ret;
-}
+	if (ret)
+		return ret;
 
-static void
-init_port_base_vlan_info(struct hns3_hw *hw)
-{
-	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
-	struct hns3_pf *pf = &hns->pf;
+	if (pvid_en_state_change)
+		hns3_update_all_queues_pvid_state(hw);
 
-	pf->port_base_vlan_cfg.state = HNS3_PORT_BASE_VLAN_DISABLE;
-	pf->port_base_vlan_cfg.pvid = HNS3_INVLID_PVID;
+	return 0;
 }
 
 static int
@@ -890,7 +934,13 @@ hns3_default_vlan_config(struct hns3_adapter *hns)
 	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
-	ret = hns3_set_port_vlan_filter(hns, 0, 1);
+	/*
+	 * When vlan filter is enabled, hardware regards packets without vlan
+	 * as packets with vlan 0. Therefore, if vlan 0 is not in the vlan
+	 * table, packets without vlan won't be received. So, add vlan 0 as
+	 * the default vlan.
+	 */
+	ret = hns3_vlan_filter_configure(hns, 0, 1);
 	if (ret)
 		hns3_err(hw, "default vlan 0 config failed, ret =%d", ret);
 	return ret;
@@ -909,10 +959,12 @@ hns3_init_vlan_config(struct hns3_adapter *hns)
 	 * ensure that the hardware configuration remains unchanged before and
 	 * after reset.
 	 */
-	if (rte_atomic16_read(&hw->reset.resetting) == 0)
-		init_port_base_vlan_info(hw);
+	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
+		hw->port_base_vlan_cfg.state = HNS3_PORT_BASE_VLAN_DISABLE;
+		hw->port_base_vlan_cfg.pvid = HNS3_INVALID_PVID;
+	}
 
-	ret = hns3_enable_vlan_filter(hns, true);
+	ret = hns3_vlan_filter_init(hns);
 	if (ret) {
 		hns3_err(hw, "vlan init fail in pf, ret =%d", ret);
 		return ret;
@@ -932,7 +984,7 @@ hns3_init_vlan_config(struct hns3_adapter *hns)
 	 * and hns3_restore_vlan_conf later.
 	 */
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
-		ret = hns3_vlan_pvid_configure(hns, HNS3_INVLID_PVID, 0);
+		ret = hns3_vlan_pvid_configure(hns, HNS3_INVALID_PVID, 0);
 		if (ret) {
 			hns3_err(hw, "pvid set fail in pf, ret =%d", ret);
 			return ret;
@@ -954,17 +1006,31 @@ hns3_restore_vlan_conf(struct hns3_adapter *hns)
 {
 	struct hns3_pf *pf = &hns->pf;
 	struct hns3_hw *hw = &hns->hw;
+	uint64_t offloads;
+	bool enable;
 	int ret;
 
+	if (!hw->data->promiscuous) {
+		/* restore vlan filter states */
+		offloads = hw->data->dev_conf.rxmode.offloads;
+		enable = offloads & DEV_RX_OFFLOAD_VLAN_FILTER ? true : false;
+		ret = hns3_enable_vlan_filter(hns, enable);
+		if (ret) {
+			hns3_err(hw, "failed to restore vlan rx filter conf, "
+				 "ret = %d", ret);
+			return ret;
+		}
+	}
+
 	ret = hns3_set_vlan_rx_offload_cfg(hns, &pf->vtag_config.rx_vcfg);
 	if (ret) {
-		hns3_err(hw, "hns3 restore vlan rx conf fail, ret =%d", ret);
+		hns3_err(hw, "failed to restore vlan rx conf, ret = %d", ret);
 		return ret;
 	}
 
 	ret = hns3_set_vlan_tx_offload_cfg(hns, &pf->vtag_config.tx_vcfg);
 	if (ret)
-		hns3_err(hw, "hns3 restore vlan tx conf fail, ret =%d", ret);
+		hns3_err(hw, "failed to restore vlan tx conf, ret = %d", ret);
 
 	return ret;
 }
@@ -976,6 +1042,7 @@ hns3_dev_configure_vlan(struct rte_eth_dev *dev)
 	struct rte_eth_dev_data *data = dev->data;
 	struct rte_eth_txmode *txmode;
 	struct hns3_hw *hw = &hns->hw;
+	int mask;
 	int ret;
 
 	txmode = &data->dev_conf.txmode;
@@ -989,17 +1056,26 @@ hns3_dev_configure_vlan(struct rte_eth_dev *dev)
 			  txmode->hw_vlan_reject_untagged);
 
 	/* Apply vlan offload setting */
-	ret = hns3_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK;
+	ret = hns3_vlan_offload_set(dev, mask);
 	if (ret) {
-		hns3_err(hw, "dev config vlan Strip failed, ret =%d", ret);
+		hns3_err(hw, "dev config rx vlan offload failed, ret = %d",
+			 ret);
 		return ret;
 	}
 
+	/*
+	 * If pvid config is not set in rte_eth_conf, driver needn't to set
+	 * VLAN pvid related configuration to hardware.
+	 */
+	if (txmode->pvid == 0 && txmode->hw_vlan_insert_pvid == 0)
+		return 0;
+
 	/* Apply pvid setting */
 	ret = hns3_vlan_pvid_set(dev, txmode->pvid,
 				 txmode->hw_vlan_insert_pvid);
 	if (ret)
-		hns3_err(hw, "dev config vlan pvid(%d) failed, ret =%d",
+		hns3_err(hw, "dev config vlan pvid(%d) failed, ret = %d",
 			 txmode->pvid, ret);
 
 	return ret;
@@ -1335,7 +1411,7 @@ hns3_add_uc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
 	struct hns3_mac_vlan_tbl_entry_cmd req;
 	struct hns3_pf *pf = &hns->pf;
-	struct hns3_cmd_desc desc;
+	struct hns3_cmd_desc desc[3];
 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
 	uint16_t egress_port = 0;
 	uint8_t vf_id;
@@ -1370,7 +1446,7 @@ hns3_add_uc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	 * it if the entry is inexistent. Repeated unicast entry
 	 * is not allowed in the mac vlan table.
 	 */
-	ret = hns3_lookup_mac_vlan_tbl(hw, &req, &desc, false);
+	ret = hns3_lookup_mac_vlan_tbl(hw, &req, desc, false);
 	if (ret == -ENOENT) {
 		if (!hns3_is_umv_space_full(hw)) {
 			ret = hns3_add_mac_vlan_tbl(hw, &req, NULL);
@@ -1398,6 +1474,53 @@ hns3_add_uc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	return ret;
 }
 
+static int
+hns3_add_mc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	int ret;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		/* Check if there are duplicate addresses */
+		if (rte_is_same_ether_addr(addr, mac_addr)) {
+			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_err(hw, "failed to add mc mac addr, same addrs"
+				 "(%s) is added by the set_mc_mac_addr_list "
+				 "API", mac_str);
+			return -EINVAL;
+		}
+	}
+
+	ret = hns3_add_mc_addr(hw, mac_addr);
+	if (ret) {
+		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add mc mac addr(%s), ret = %d",
+			 mac_str, ret);
+	}
+	return ret;
+}
+
+static int
+hns3_remove_mc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	ret = hns3_remove_mc_addr(hw, mac_addr);
+	if (ret) {
+		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to remove mc mac addr(%s), ret = %d",
+			 mac_str, ret);
+	}
+	return ret;
+}
+
 static int
 hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
 		  uint32_t idx, __attribute__ ((unused)) uint32_t pool)
@@ -1407,12 +1530,27 @@ hns3_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
 	int ret;
 
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_add_uc_addr_common(hw, mac_addr);
+
+	/*
+	 * In hns3 network engine adding UC and MC mac address with different
+	 * commands with firmware. We need to determine whether the input
+	 * address is a UC or a MC address to call different commands.
+	 * By the way, it is recommended calling the API function named
+	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
+	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
+	 * may affect the specifications of UC mac addresses.
+	 */
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hns3_add_mc_addr_common(hw, mac_addr);
+	else
+		ret = hns3_add_uc_addr_common(hw, mac_addr);
+
 	if (ret) {
 		rte_spinlock_unlock(&hw->lock);
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Failed to add mac addr(%s): %d", mac_str, ret);
+		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
+			 ret);
 		return ret;
 	}
 
@@ -1434,7 +1572,7 @@ hns3_remove_uc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	if (!rte_is_valid_assigned_ether_addr(mac_addr)) {
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Remove unicast mac addr err! addr(%s) invalid",
+		hns3_err(hw, "remove unicast mac addr err! addr(%s) invalid",
 			 mac_str);
 		return -EINVAL;
 	}
@@ -1461,18 +1599,18 @@ hns3_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
 	int ret;
 
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_remove_uc_addr_common(hw, mac_addr);
+
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hns3_remove_mc_addr_common(hw, mac_addr);
+	else
+		ret = hns3_remove_uc_addr_common(hw, mac_addr);
+	rte_spinlock_unlock(&hw->lock);
 	if (ret) {
-		rte_spinlock_unlock(&hw->lock);
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Failed to remove mac addr(%s): %d", mac_str, ret);
-		return;
+		hns3_err(hw, "failed to remove mac addr(%s), ret = %d", mac_str,
+			 ret);
 	}
-
-	if (idx == 0)
-		hw->mac.default_addr_setted = false;
-	rte_spinlock_unlock(&hw->lock);
 }
 
 static int
@@ -1573,19 +1711,22 @@ hns3_configure_all_mac_addr(struct hns3_adapter *hns, bool del)
 
 	for (i = 0; i < HNS3_UC_MACADDR_NUM; i++) {
 		addr = &hw->data->mac_addrs[i];
-		if (!rte_is_valid_assigned_ether_addr(addr))
+		if (rte_is_zero_ether_addr(addr))
 			continue;
-		if (del)
-			ret = hns3_remove_uc_addr_common(hw, addr);
+		if (rte_is_multicast_ether_addr(addr))
+			ret = del ? hns3_remove_mc_addr(hw, addr) :
+			      hns3_add_mc_addr(hw, addr);
 		else
-			ret = hns3_add_uc_addr_common(hw, addr);
+			ret = del ? hns3_remove_uc_addr_common(hw, addr) :
+			      hns3_add_uc_addr_common(hw, addr);
+
 		if (ret) {
 			err = ret;
 			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 					      addr);
-			hns3_dbg(hw,
-				 "Failed to %s mac addr(%s). ret:%d i:%d",
-				 del ? "remove" : "restore", mac_str, ret, i);
+			hns3_err(hw, "failed to %s mac addr(%s) index:%d "
+				 "ret = %d.", del ? "remove" : "restore",
+				 mac_str, i, ret);
 		}
 	}
 	return err;
@@ -1632,7 +1773,7 @@ hns3_add_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 	if (!rte_is_multicast_ether_addr(mac_addr)) {
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Failed to add mc mac addr, addr(%s) invalid",
+		hns3_err(hw, "failed to add mc mac addr, addr(%s) invalid",
 			 mac_str);
 		return -EINVAL;
 	}
@@ -1661,7 +1802,7 @@ hns3_add_mc_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
 			hns3_err(hw, "mc mac vlan table is full");
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Failed to add mc mac addr(%s): %d", mac_str, ret);
+		hns3_err(hw, "failed to add mc mac addr(%s): %d", mac_str, ret);
 	}
 
 	return ret;
@@ -1726,7 +1867,7 @@ hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
 	uint32_t j;
 
 	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
-		hns3_err(hw, "Failed to set mc mac addr, nb_mc_addr(%d) "
+		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%d) "
 			 "invalid. valid range: 0~%d",
 			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
 		return -EINVAL;
@@ -1739,7 +1880,7 @@ hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
 			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 					      addr);
 			hns3_err(hw,
-				 "Failed to set mc mac addr, addr(%s) invalid.",
+				 "failed to set mc mac addr, addr(%s) invalid.",
 				 mac_str);
 			return -EINVAL;
 		}
@@ -1750,12 +1891,30 @@ hns3_set_mc_addr_chk_param(struct hns3_hw *hw,
 				rte_ether_format_addr(mac_str,
 						      RTE_ETHER_ADDR_FMT_SIZE,
 						      addr);
-				hns3_err(hw, "Failed to set mc mac addr, "
+				hns3_err(hw, "failed to set mc mac addr, "
 					 "addrs invalid. two same addrs(%s).",
 					 mac_str);
 				return -EINVAL;
 			}
 		}
+
+		/*
+		 * Check if there are duplicate addresses between mac_addrs
+		 * and mc_addr_set
+		 */
+		for (j = 0; j < HNS3_UC_MACADDR_NUM; j++) {
+			if (rte_is_same_ether_addr(addr,
+						   &hw->data->mac_addrs[j])) {
+				rte_ether_format_addr(mac_str,
+						      RTE_ETHER_ADDR_FMT_SIZE,
+						      addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. addrs(%s) has already "
+					 "configured in mac_addr add API",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
 	}
 
 	return 0;
@@ -2021,37 +2180,143 @@ hns3_check_dcb_cfg(struct rte_eth_dev *dev)
 	return hns3_check_mq_mode(dev);
 }
 
+static int
+hns3_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id, bool mmap,
+			   enum hns3_ring_type queue_type, uint16_t queue_id)
+{
+	struct hns3_cmd_desc desc;
+	struct hns3_ctrl_vector_chain_cmd *req =
+		(struct hns3_ctrl_vector_chain_cmd *)desc.data;
+	enum hns3_cmd_status status;
+	enum hns3_opcode_type op;
+	uint16_t tqp_type_and_id = 0;
+	const char *op_str;
+	uint16_t type;
+	uint16_t gl;
+
+	op = mmap ? HNS3_OPC_ADD_RING_TO_VECTOR : HNS3_OPC_DEL_RING_TO_VECTOR;
+	hns3_cmd_setup_basic_desc(&desc, op, false);
+	req->int_vector_id = vector_id;
+
+	if (queue_type == HNS3_RING_TYPE_RX)
+		gl = HNS3_RING_GL_RX;
+	else
+		gl = HNS3_RING_GL_TX;
+
+	type = queue_type;
+
+	hns3_set_field(tqp_type_and_id, HNS3_INT_TYPE_M, HNS3_INT_TYPE_S,
+		       type);
+	hns3_set_field(tqp_type_and_id, HNS3_TQP_ID_M, HNS3_TQP_ID_S, queue_id);
+	hns3_set_field(tqp_type_and_id, HNS3_INT_GL_IDX_M, HNS3_INT_GL_IDX_S,
+		       gl);
+	req->tqp_type_and_id[0] = rte_cpu_to_le_16(tqp_type_and_id);
+	req->int_cause_num = 1;
+	op_str = mmap ? "Map" : "Unmap";
+	status = hns3_cmd_send(hw, &desc, 1);
+	if (status) {
+		hns3_err(hw, "%s TQP %d fail, vector_id is %d, status is %d.",
+			 op_str, queue_id, req->int_vector_id, status);
+		return status;
+	}
+
+	return 0;
+}
+
+static int
+hns3_init_ring_with_vector(struct hns3_hw *hw)
+{
+	uint8_t vec;
+	int ret;
+	int i;
+
+	/*
+	 * In hns3 network engine, vector 0 is always the misc interrupt of this
+	 * function, vector 1~N can be used respectively for the queues of the
+	 * function. Tx and Rx queues with the same number share the interrupt
+	 * vector. In the initialization clearing the all hardware mapping
+	 * relationship configurations between queues and interrupt vectors is
+	 * needed, so some error caused by the residual configurations, such as
+	 * the unexpected Tx interrupt, can be avoid. Because of the hardware
+	 * constraints in hns3 hardware engine, we have to implement clearing
+	 * the mapping relationship configurations by binding all queues to the
+	 * last interrupt vector and reserving the last interrupt vector. This
+	 * method results in a decrease of the maximum queues when upper
+	 * applications call the rte_eth_dev_configure API function to enable
+	 * Rx interrupt.
+	 */
+	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
+	/* vec - 1: the last interrupt is reserved */
+	hw->intr_tqps_num = vec > hw->tqps_num ? hw->tqps_num : vec - 1;
+	for (i = 0; i < hw->intr_tqps_num; i++) {
+		/*
+		 * Set gap limiter and rate limiter configuration of queue's
+		 * interrupt.
+		 */
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
+
+		ret = hns3_bind_ring_with_vector(hw, vec, false,
+						 HNS3_RING_TYPE_TX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "PF fail to unbind TX ring(%d) with "
+					  "vector: %d, ret=%d", i, vec, ret);
+			return ret;
+		}
+
+		ret = hns3_bind_ring_with_vector(hw, vec, false,
+						 HNS3_RING_TYPE_RX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "PF fail to unbind RX ring(%d) with "
+					  "vector: %d, ret=%d", i, vec, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int
 hns3_dev_configure(struct rte_eth_dev *dev)
 {
-	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
+	struct hns3_adapter *hns = dev->data->dev_private;
 	struct rte_eth_conf *conf = &dev->data->dev_conf;
 	enum rte_eth_rx_mq_mode mq_mode = conf->rxmode.mq_mode;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
 	uint16_t nb_rx_q = dev->data->nb_rx_queues;
 	uint16_t nb_tx_q = dev->data->nb_tx_queues;
 	struct rte_eth_rss_conf rss_conf;
+	uint32_t max_rx_pkt_len;
 	uint16_t mtu;
 	int ret;
 
 	/*
-	 * Hardware does not support where the number of rx and tx queues is
-	 * not equal in hip08.
+	 * Hardware does not support individually enable/disable/reset the Tx or
+	 * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
+	 * and Rx queues at the same time. When the numbers of Tx queues
+	 * allocated by upper applications are not equal to the numbers of Rx
+	 * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
+	 * of Tx/Rx queues. otherwise, network engine can not work as usual. But
+	 * these fake queues are imperceptible, and can not be used by upper
+	 * applications.
 	 */
-	if (nb_rx_q != nb_tx_q) {
-		hns3_err(hw,
-			 "nb_rx_queues(%u) not equal with nb_tx_queues(%u)! "
-			 "Hardware does not support this configuration!",
-			 nb_rx_q, nb_tx_q);
-		return -EINVAL;
+	ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+	if (ret) {
+		hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
+		return ret;
 	}
 
+	hw->adapter_state = HNS3_NIC_CONFIGURING;
 	if (conf->link_speeds & ETH_LINK_SPEED_FIXED) {
 		hns3_err(hw, "setting link speed/duplex not supported");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto cfg_err;
 	}
 
-	hw->adapter_state = HNS3_NIC_CONFIGURING;
 	if ((uint32_t)mq_mode & ETH_MQ_RX_DCB_FLAG) {
 		ret = hns3_check_dcb_cfg(dev);
 		if (ret)
@@ -2060,7 +2325,9 @@ hns3_dev_configure(struct rte_eth_dev *dev)
 
 	/* When RSS is not configured, redirect the packet queue 0 */
 	if ((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG) {
+		conf->rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
 		rss_conf = conf->rx_adv_conf.rss_conf;
+		hw->rss_dis_flag = false;
 		if (rss_conf.rss_key == NULL) {
 			rss_conf.rss_key = rss_cfg->key;
 			rss_conf.rss_key_len = HNS3_RSS_KEY_SIZE;
@@ -2076,12 +2343,18 @@ hns3_dev_configure(struct rte_eth_dev *dev)
 	 * according to the maximum RX packet length.
 	 */
 	if (conf->rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
-		/*
-		 * Security of max_rx_pkt_len is guaranteed in dpdk frame.
-		 * Maximum value of max_rx_pkt_len is HNS3_MAX_FRAME_LEN, so it
-		 * can safely assign to "uint16_t" type variable.
-		 */
-		mtu = (uint16_t)HNS3_PKTLEN_TO_MTU(conf->rxmode.max_rx_pkt_len);
+		max_rx_pkt_len = conf->rxmode.max_rx_pkt_len;
+		if (max_rx_pkt_len > HNS3_MAX_FRAME_LEN ||
+		    max_rx_pkt_len <= HNS3_DEFAULT_FRAME_LEN) {
+			hns3_err(hw, "maximum Rx packet length must be greater "
+				 "than %u and less than %u when jumbo frame enabled.",
+				 (uint16_t)HNS3_DEFAULT_FRAME_LEN,
+				 (uint16_t)HNS3_MAX_FRAME_LEN);
+			ret = -EINVAL;
+			goto cfg_err;
+		}
+
+		mtu = (uint16_t)HNS3_PKTLEN_TO_MTU(max_rx_pkt_len);
 		ret = hns3_dev_mtu_set(dev, mtu);
 		if (ret)
 			goto cfg_err;
@@ -2097,7 +2370,9 @@ hns3_dev_configure(struct rte_eth_dev *dev)
 	return 0;
 
 cfg_err:
+	(void)hns3_set_fake_rx_or_tx_queues(dev, 0, 0);
 	hw->adapter_state = HNS3_NIC_INITIALIZED;
+
 	return ret;
 }
 
@@ -2152,7 +2427,7 @@ hns3_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	}
 
 	rte_spinlock_lock(&hw->lock);
-	is_jumbo_frame = frame_size > RTE_ETHER_MAX_LEN ? true : false;
+	is_jumbo_frame = frame_size > HNS3_DEFAULT_FRAME_LEN ? true : false;
 	frame_size = RTE_MAX(frame_size, HNS3_DEFAULT_FRAME_LEN);
 
 	/*
@@ -2184,11 +2459,19 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 {
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
+	uint16_t queue_num = hw->tqps_num;
+
+	/*
+	 * In interrupt mode, 'max_rx_queues' is set based on the number of
+	 * MSI-X interrupt resources of the hardware.
+	 */
+	if (hw->data->dev_conf.intr_conf.rxq == 1)
+		queue_num = hw->intr_tqps_num;
 
-	info->max_rx_queues = hw->tqps_num;
+	info->max_rx_queues = queue_num;
 	info->max_tx_queues = hw->tqps_num;
 	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = hw->rx_buf_len;
+	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
 	info->max_mac_addrs = HNS3_UC_MACADDR_NUM;
 	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
 	info->rx_offload_capa = (DEV_RX_OFFLOAD_IPV4_CKSUM |
@@ -2200,11 +2483,9 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_RX_OFFLOAD_KEEP_CRC |
 				 DEV_RX_OFFLOAD_SCATTER |
 				 DEV_RX_OFFLOAD_VLAN_STRIP |
-				 DEV_RX_OFFLOAD_QINQ_STRIP |
 				 DEV_RX_OFFLOAD_VLAN_FILTER |
-				 DEV_RX_OFFLOAD_VLAN_EXTEND |
-				 DEV_RX_OFFLOAD_JUMBO_FRAME);
-	info->tx_queue_offload_capa = DEV_TX_OFFLOAD_MBUF_FAST_FREE;
+				 DEV_RX_OFFLOAD_JUMBO_FRAME |
+				 DEV_RX_OFFLOAD_RSS_HASH);
 	info->tx_offload_capa = (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
 				 DEV_TX_OFFLOAD_IPV4_CKSUM |
 				 DEV_TX_OFFLOAD_TCP_CKSUM |
@@ -2213,7 +2494,7 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_TX_OFFLOAD_VLAN_INSERT |
 				 DEV_TX_OFFLOAD_QINQ_INSERT |
 				 DEV_TX_OFFLOAD_MULTI_SEGS |
-				 info->tx_queue_offload_capa);
+				 DEV_TX_OFFLOAD_MBUF_FAST_FREE);
 
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
@@ -2227,6 +2508,17 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 		.nb_align = HNS3_ALIGN_RING_DESC,
 	};
 
+	info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
+		/*
+		 * If there are no available Rx buffer descriptors, incoming
+		 * packets are always dropped by hardware based on hns3 network
+		 * engine.
+		 */
+		.rx_drop_en = 1,
+		.offloads = 0,
+	};
+
 	info->vmdq_queue_num = 0;
 
 	info->reta_size = HNS3_RSS_IND_TBL_SIZE;
@@ -2268,6 +2560,11 @@ hns3_dev_link_update(struct rte_eth_dev *eth_dev,
 	struct hns3_mac *mac = &hw->mac;
 	struct rte_eth_link new_link;
 
+	if (!hns3_is_reset_pending(hns)) {
+		hns3_update_speed_duplex(eth_dev);
+		hns3_update_link_status(hw);
+	}
+
 	memset(&new_link, 0, sizeof(new_link));
 	switch (mac->link_speed) {
 	case ETH_SPEED_NUM_10M:
@@ -2358,6 +2655,7 @@ hns3_query_pf_resource(struct hns3_hw *hw)
 	hw->total_tqps_num = rte_le_to_cpu_16(req->tqp_num);
 	pf->pkt_buf_size = rte_le_to_cpu_16(req->buf_size) << HNS3_BUF_UNIT_S;
 	hw->tqps_num = RTE_MIN(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
+	pf->func_num = rte_le_to_cpu_16(req->pf_own_fun_number);
 
 	if (req->tx_buf_size)
 		pf->tx_buf_size =
@@ -2377,7 +2675,7 @@ hns3_query_pf_resource(struct hns3_hw *hw)
 
 	hw->num_msi =
 	    hns3_get_field(rte_le_to_cpu_16(req->pf_intr_vector_number),
-			   HNS3_PF_VEC_NUM_M, HNS3_PF_VEC_NUM_S);
+			   HNS3_VEC_NUM_M, HNS3_VEC_NUM_S);
 
 	return 0;
 }
@@ -2534,7 +2832,7 @@ hns3_get_board_configuration(struct hns3_hw *hw)
 
 	hw->mac.media_type = cfg.media_type;
 	hw->rss_size_max = cfg.rss_size_max;
-	hw->rx_buf_len = cfg.rx_buf_len;
+	hw->rss_dis_flag = false;
 	memcpy(hw->mac.mac_addr, cfg.mac_addr, RTE_ETHER_ADDR_LEN);
 	hw->mac.phy_addr = cfg.phy_addr;
 	hw->mac.default_addr_setted = false;
@@ -2634,6 +2932,7 @@ hns3_map_tqp(struct hns3_hw *hw)
 	uint16_t tqps_num = hw->total_tqps_num;
 	uint16_t func_id;
 	uint16_t tqp_id;
+	bool is_pf;
 	int num;
 	int ret;
 	int i;
@@ -2645,10 +2944,11 @@ hns3_map_tqp(struct hns3_hw *hw)
 	tqp_id = 0;
 	num = DIV_ROUND_UP(hw->total_tqps_num, HNS3_MAX_TQP_NUM_PER_FUNC);
 	for (func_id = 0; func_id < num; func_id++) {
+		is_pf = func_id == 0 ? true : false;
 		for (i = 0;
 		     i < HNS3_MAX_TQP_NUM_PER_FUNC && tqp_id < tqps_num; i++) {
 			ret = hns3_map_tqps_to_func(hw, func_id, tqp_id++, i,
-						    true);
+						    is_pf);
 			if (ret)
 				return ret;
 		}
@@ -3415,6 +3715,7 @@ hns3_get_mac_ethertype_cmd_status(uint16_t cmdq_resp, uint8_t resp_code)
 			     "add mac ethertype failed for undefined, code=%d.",
 			     resp_code);
 		return_status = -EIO;
+		break;
 	}
 
 	return return_status;
@@ -3521,7 +3822,7 @@ hns3_cmd_set_promisc_mode(struct hns3_hw *hw, struct hns3_promisc_param *param)
 
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret)
-		PMD_INIT_LOG(ERR, "Set promisc mode fail, status is %d", ret);
+		PMD_INIT_LOG(ERR, "Set promisc mode fail, ret = %d", ret);
 
 	return ret;
 }
@@ -3549,19 +3850,104 @@ hns3_set_promisc_mode(struct hns3_hw *hw, bool en_uc_pmc, bool en_mc_pmc)
 	return 0;
 }
 
+static int
+hns3_promisc_init(struct hns3_hw *hw)
+{
+	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	struct hns3_pf *pf = &hns->pf;
+	struct hns3_promisc_param param;
+	uint16_t func_id;
+	int ret;
+
+	ret = hns3_set_promisc_mode(hw, false, false);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "failed to set promisc mode, ret = %d", ret);
+		return ret;
+	}
+
+	/*
+	 * In current version VFs are not supported when PF is driven by DPDK
+	 * driver. After PF has been taken over by DPDK, the original VF will
+	 * be invalid. So, there is a possibility of entry residues. It should
+	 * clear VFs's promisc mode to avoid unnecessary bandwidth usage
+	 * during init.
+	 */
+	/* func_id 0 is denoted PF, the VFs start from 1 */
+	for (func_id = 1; func_id < pf->func_num; func_id++) {
+		hns3_promisc_param_init(&param, false, false, false, func_id);
+		ret = hns3_cmd_set_promisc_mode(hw, &param);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "failed to clear vf:%d promisc mode,"
+					" ret = %d", func_id, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void
+hns3_promisc_uninit(struct hns3_hw *hw)
+{
+	struct hns3_promisc_param param;
+	uint16_t func_id;
+	int ret;
+
+	func_id = 0;
+
+	/*
+	 * In current version VFs are not supported when PF is driven by
+	 * DPDK driver, and VFs' promisc mode status has been cleared during
+	 * init and their status will not change. So just clear PF's promisc
+	 * mode status during uninit.
+	 */
+	hns3_promisc_param_init(&param, false, false, false, func_id);
+	ret = hns3_cmd_set_promisc_mode(hw, &param);
+	if (ret)
+		PMD_INIT_LOG(ERR, "failed to clear promisc status during"
+				" uninit, ret = %d", ret);
+}
+
 static int
 hns3_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
+	bool allmulti = dev->data->all_multicast ? true : false;
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	bool en_mc_pmc = (dev->data->all_multicast == 1) ? true : false;
+	uint64_t offloads;
+	int err;
 	int ret = 0;
 
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_set_promisc_mode(hw, true, en_mc_pmc);
+	ret = hns3_set_promisc_mode(hw, true, true);
+	if (ret) {
+		rte_spinlock_unlock(&hw->lock);
+		hns3_err(hw, "failed to enable promiscuous mode, ret = %d",
+			 ret);
+		return ret;
+	}
+
+	/*
+	 * When promiscuous mode was enabled, disable the vlan filter to let
+	 * all packets coming in in the receiving direction.
+	 */
+	offloads = dev->data->dev_conf.rxmode.offloads;
+	if (offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
+		ret = hns3_enable_vlan_filter(hns, false);
+		if (ret) {
+			hns3_err(hw, "failed to enable promiscuous mode due to "
+				     "failure to disable vlan filter, ret = %d",
+				 ret);
+			err = hns3_set_promisc_mode(hw, false, allmulti);
+			if (err)
+				hns3_err(hw, "failed to restore promiscuous "
+					 "status after disable vlan filter "
+					 "failed during enabling promiscuous "
+					 "mode, ret = %d", ret);
+		}
+	}
+
 	rte_spinlock_unlock(&hw->lock);
-	if (ret)
-		hns3_err(hw, "Failed to enable promiscuous mode: %d", ret);
 
 	return ret;
 }
@@ -3569,17 +3955,39 @@ hns3_dev_promiscuous_enable(struct rte_eth_dev *dev)
 static int
 hns3_dev_promiscuous_disable(struct rte_eth_dev *dev)
 {
+	bool allmulti = dev->data->all_multicast ? true : false;
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	bool en_mc_pmc = (dev->data->all_multicast == 1) ? true : false;
+	uint64_t offloads;
+	int err;
 	int ret = 0;
 
 	/* If now in all_multicast mode, must remain in all_multicast mode. */
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_set_promisc_mode(hw, false, en_mc_pmc);
+	ret = hns3_set_promisc_mode(hw, false, allmulti);
+	if (ret) {
+		rte_spinlock_unlock(&hw->lock);
+		hns3_err(hw, "failed to disable promiscuous mode, ret = %d",
+			 ret);
+		return ret;
+	}
+	/* when promiscuous mode was disabled, restore the vlan filter status */
+	offloads = dev->data->dev_conf.rxmode.offloads;
+	if (offloads & DEV_RX_OFFLOAD_VLAN_FILTER) {
+		ret = hns3_enable_vlan_filter(hns, true);
+		if (ret) {
+			hns3_err(hw, "failed to disable promiscuous mode due to"
+				 " failure to restore vlan filter, ret = %d",
+				 ret);
+			err = hns3_set_promisc_mode(hw, true, true);
+			if (err)
+				hns3_err(hw, "failed to restore promiscuous "
+					 "status after enabling vlan filter "
+					 "failed during disabling promiscuous "
+					 "mode, ret = %d", ret);
+		}
+	}
 	rte_spinlock_unlock(&hw->lock);
-	if (ret)
-		hns3_err(hw, "Failed to disable promiscuous mode: %d", ret);
 
 	return ret;
 }
@@ -3589,14 +3997,17 @@ hns3_dev_allmulticast_enable(struct rte_eth_dev *dev)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	bool en_uc_pmc = (dev->data->promiscuous == 1) ? true : false;
 	int ret = 0;
 
+	if (dev->data->promiscuous)
+		return 0;
+
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_set_promisc_mode(hw, en_uc_pmc, true);
+	ret = hns3_set_promisc_mode(hw, false, true);
 	rte_spinlock_unlock(&hw->lock);
 	if (ret)
-		hns3_err(hw, "Failed to enable allmulticast mode: %d", ret);
+		hns3_err(hw, "failed to enable allmulticast mode, ret = %d",
+			 ret);
 
 	return ret;
 }
@@ -3606,18 +4017,18 @@ hns3_dev_allmulticast_disable(struct rte_eth_dev *dev)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
-	bool en_uc_pmc = (dev->data->promiscuous == 1) ? true : false;
 	int ret = 0;
 
 	/* If now in promiscuous mode, must remain in all_multicast mode. */
-	if (dev->data->promiscuous == 1)
+	if (dev->data->promiscuous)
 		return 0;
 
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_set_promisc_mode(hw, en_uc_pmc, false);
+	ret = hns3_set_promisc_mode(hw, false, false);
 	rte_spinlock_unlock(&hw->lock);
 	if (ret)
-		hns3_err(hw, "Failed to disable allmulticast mode: %d", ret);
+		hns3_err(hw, "failed to disable allmulticast mode, ret = %d",
+			 ret);
 
 	return ret;
 }
@@ -3626,13 +4037,22 @@ static int
 hns3_dev_promisc_restore(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	bool en_mc_pmc;
-	bool en_uc_pmc;
+	bool allmulti = hw->data->all_multicast ? true : false;
+	int ret;
 
-	en_uc_pmc = (hw->data->promiscuous == 1) ? true : false;
-	en_mc_pmc = (hw->data->all_multicast == 1) ? true : false;
+	if (hw->data->promiscuous) {
+		ret = hns3_set_promisc_mode(hw, true, true);
+		if (ret)
+			hns3_err(hw, "failed to restore promiscuous mode, "
+				 "ret = %d", ret);
+		return ret;
+	}
 
-	return hns3_set_promisc_mode(hw, en_uc_pmc, en_mc_pmc);
+	ret = hns3_set_promisc_mode(hw, false, allmulti);
+	if (ret)
+		hns3_err(hw, "failed to restore allmulticast mode, ret = %d",
+			 ret);
+	return ret;
 }
 
 static int
@@ -3671,6 +4091,7 @@ static int
 hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex)
 {
 	struct hns3_mac *mac = &hw->mac;
+	uint32_t cur_speed = mac->link_speed;
 	int ret;
 
 	duplex = hns3_check_speed_dup(duplex, speed);
@@ -3682,6 +4103,13 @@ hns3_cfg_mac_speed_dup(struct hns3_hw *hw, uint32_t speed, uint8_t duplex)
 		return ret;
 
 	mac->link_speed = speed;
+	ret = hns3_dcb_port_shaper_cfg(hw);
+	if (ret) {
+		hns3_err(hw, "failed to configure port shaper, ret = %d.", ret);
+		mac->link_speed = cur_speed;
+		return ret;
+	}
+
 	mac->link_duplex = duplex;
 
 	return 0;
@@ -3763,7 +4191,7 @@ hns3_get_mac_link_status(struct hns3_hw *hw)
 	ret = hns3_cmd_send(hw, &desc, 1);
 	if (ret) {
 		hns3_err(hw, "get link status cmd failed %d", ret);
-		return ret;
+		return ETH_LINK_DOWN;
 	}
 
 	req = (struct hns3_link_status_cmd *)desc.data;
@@ -3772,14 +4200,16 @@ hns3_get_mac_link_status(struct hns3_hw *hw)
 	return !!link_status;
 }
 
-static void
+void
 hns3_update_link_status(struct hns3_hw *hw)
 {
 	int state;
 
 	state = hns3_get_mac_link_status(hw);
-	if (state != hw->mac.link_status)
+	if (state != hw->mac.link_status) {
 		hw->mac.link_status = state;
+		hns3_warn(hw, "Link status change to %s!", state ? "up" : "down");
+	}
 }
 
 static void
@@ -3828,9 +4258,10 @@ hns3_init_hardware(struct hns3_adapter *hns)
 		goto err_mac_init;
 	}
 
-	ret = hns3_set_promisc_mode(hw, false, false);
+	ret = hns3_promisc_init(hw);
 	if (ret) {
-		PMD_INIT_LOG(ERR, "Failed to set promisc mode: %d", ret);
+		PMD_INIT_LOG(ERR, "Failed to init promisc: %d",
+			     ret);
 		goto err_mac_init;
 	}
 
@@ -3863,6 +4294,19 @@ hns3_init_hardware(struct hns3_adapter *hns)
 		PMD_INIT_LOG(ERR, "Failed to config gro: %d", ret);
 		goto err_mac_init;
 	}
+
+	/*
+	 * In the initialization clearing the all hardware mapping relationship
+	 * configurations between queues and interrupt vectors is needed, so
+	 * some error caused by the residual configurations, such as the
+	 * unexpected interrupt, can be avoid.
+	 */
+	ret = hns3_init_ring_with_vector(hw);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to init ring intr vector: %d", ret);
+		goto err_mac_init;
+	}
+
 	return 0;
 
 err_mac_init:
@@ -3870,6 +4314,21 @@ hns3_init_hardware(struct hns3_adapter *hns)
 	return ret;
 }
 
+static int
+hns3_clear_hw(struct hns3_hw *hw)
+{
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CLEAR_HW_STATE, false);
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret && ret != -EOPNOTSUPP)
+		return ret;
+
+	return 0;
+}
+
 static int
 hns3_init_pf(struct rte_eth_dev *eth_dev)
 {
@@ -3900,6 +4359,18 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 		goto err_cmd_init;
 	}
 
+	/*
+	 * To ensure that the hardware environment is clean during
+	 * initialization, the driver actively clear the hardware environment
+	 * during initialization, including PF and corresponding VFs' vlan, mac,
+	 * flow table configurations, etc.
+	 */
+	ret = hns3_clear_hw(hw);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "failed to clear hardware: %d", ret);
+		goto err_cmd_init;
+	}
+
 	ret = rte_intr_callback_register(&pci_dev->intr_handle,
 					 hns3_interrupt_handler,
 					 eth_dev);
@@ -3953,13 +4424,10 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 	rte_intr_disable(&pci_dev->intr_handle);
 	hns3_intr_unregister(&pci_dev->intr_handle, hns3_interrupt_handler,
 			     eth_dev);
-
 err_intr_callback_register:
-	hns3_cmd_uninit(hw);
-
 err_cmd_init:
+	hns3_cmd_uninit(hw);
 	hns3_cmd_destroy_queue(hw);
-
 err_cmd_init_queue:
 	hw->io_base = NULL;
 
@@ -3978,6 +4446,7 @@ hns3_uninit_pf(struct rte_eth_dev *eth_dev)
 
 	hns3_enable_hw_error_intr(hns, false);
 	hns3_rss_uninit(hns);
+	hns3_promisc_uninit(hw);
 	hns3_fdir_filter_uninit(hns);
 	hns3_uninit_umv_space(hw);
 	hns3_pf_disable_irq0(hw);
@@ -4020,15 +4489,116 @@ hns3_do_start(struct hns3_adapter *hns, bool reset_queue)
 }
 
 static int
-hns3_dev_start(struct rte_eth_dev *eth_dev)
+hns3_map_rx_interrupt(struct rte_eth_dev *dev)
 {
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t intr_vector;
+	uint8_t base = 0;
+	uint8_t vec = 0;
+	uint16_t q_id;
 	int ret;
 
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	/* disable uio/vfio intr/eventfd mapping */
+	rte_intr_disable(intr_handle);
+
+	/* check and configure queue intr-vector mapping */
+	if (rte_intr_cap_multiple(intr_handle) ||
+	    !RTE_ETH_DEV_SRIOV(dev).active) {
+		intr_vector = hw->used_rx_queues;
+		/* creates event fd for each intr vector when MSIX is used */
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -EINVAL;
+	}
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    hw->used_rx_queues * sizeof(int), 0);
+		if (intr_handle->intr_vec == NULL) {
+			hns3_err(hw, "Failed to allocate %d rx_queues"
+				     " intr_vec", hw->used_rx_queues);
+			ret = -ENOMEM;
+			goto alloc_intr_vec_error;
+		}
+	}
+
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hns3_bind_ring_with_vector(hw, vec, true,
+							 HNS3_RING_TYPE_RX,
+							 q_id);
+			if (ret)
+				goto bind_vector_error;
+			intr_handle->intr_vec[q_id] = vec;
+			if (vec < base + intr_handle->nb_efd - 1)
+				vec++;
+		}
+	}
+	rte_intr_enable(intr_handle);
+	return 0;
+
+bind_vector_error:
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
+	return ret;
+alloc_intr_vec_error:
+	rte_intr_efd_disable(intr_handle);
+	return ret;
+}
+
+static int
+hns3_restore_rx_interrupt(struct hns3_hw *hw)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	uint16_t q_id;
+	int ret;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hns3_bind_ring_with_vector(hw,
+					intr_handle->intr_vec[q_id], true,
+					HNS3_RING_TYPE_RX, q_id);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void
+hns3_restore_filter(struct rte_eth_dev *dev)
+{
+	hns3_restore_rss_filter(dev);
+}
+
+static int
+hns3_dev_start(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	int ret = 0;
+
 	PMD_INIT_FUNC_TRACE();
 	if (rte_atomic16_read(&hw->reset.resetting))
 		return -EBUSY;
+
 	rte_spinlock_lock(&hw->lock);
 	hw->adapter_state = HNS3_NIC_STARTING;
 
@@ -4039,10 +4609,29 @@ hns3_dev_start(struct rte_eth_dev *eth_dev)
 		return ret;
 	}
 
+	ret = hns3_map_rx_interrupt(dev);
+	if (ret) {
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
+
 	hw->adapter_state = HNS3_NIC_STARTED;
 	rte_spinlock_unlock(&hw->lock);
-	hns3_set_rxtx_function(eth_dev);
-	hns3_mp_req_start_rxtx(eth_dev);
+
+	hns3_set_rxtx_function(dev);
+	hns3_mp_req_start_rxtx(dev);
+	rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, dev);
+
+	hns3_restore_filter(dev);
+
+	/* Enable interrupt of all rx queues before enabling queues */
+	hns3_dev_all_rx_queue_intr_enable(hw, true);
+	/*
+	 * When finished the initialization, enable queues to receive/transmit
+	 * packets.
+	 */
+	hns3_enable_all_queues(hw, true);
 
 	hns3_info(hw, "hns3 dev start successful!");
 	return 0;
@@ -4070,27 +4659,65 @@ hns3_do_stop(struct hns3_adapter *hns)
 }
 
 static void
-hns3_dev_stop(struct rte_eth_dev *eth_dev)
+hns3_unmap_rx_interrupt(struct rte_eth_dev *dev)
 {
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint8_t base = 0;
+	uint8_t vec = 0;
+	uint16_t q_id;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return;
+
+	/* unmap the ring with vector */
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			(void)hns3_bind_ring_with_vector(hw, vec, false,
+							 HNS3_RING_TYPE_RX,
+							 q_id);
+			if (vec < base + intr_handle->nb_efd - 1)
+				vec++;
+		}
+	}
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
+}
+
+static void
+hns3_dev_stop(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
 
 	PMD_INIT_FUNC_TRACE();
 
 	hw->adapter_state = HNS3_NIC_STOPPING;
-	hns3_set_rxtx_function(eth_dev);
+	hns3_set_rxtx_function(dev);
 	rte_wmb();
 	/* Disable datapath on secondary process. */
-	hns3_mp_req_stop_rxtx(eth_dev);
+	hns3_mp_req_stop_rxtx(dev);
 	/* Prevent crashes when queues are still in use. */
 	rte_delay_ms(hw->tqps_num);
 
 	rte_spinlock_lock(&hw->lock);
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
 		hns3_do_stop(hns);
+		hns3_unmap_rx_interrupt(dev);
 		hns3_dev_release_mbufs(hns);
 		hw->adapter_state = HNS3_NIC_CONFIGURED;
 	}
+	rte_eal_alarm_cancel(hns3_service_handler, dev);
 	rte_spinlock_unlock(&hw->lock);
 }
 
@@ -4112,7 +4739,6 @@ hns3_dev_close(struct rte_eth_dev *eth_dev)
 	hw->adapter_state = HNS3_NIC_CLOSING;
 	hns3_reset_abort(hns);
 	hw->adapter_state = HNS3_NIC_CLOSED;
-	rte_eal_alarm_cancel(hns3_service_handler, eth_dev);
 
 	hns3_configure_all_mc_mac_addr(hns, true);
 	hns3_remove_all_vlan_table(hns);
@@ -4297,15 +4923,13 @@ hns3_get_dcb_info(struct rte_eth_dev *dev, struct rte_eth_dcb_info *dcb_info)
 	for (i = 0; i < dcb_info->nb_tcs; i++)
 		dcb_info->tc_bws[i] = hw->dcb_info.pg_info[0].tc_dwrr[i];
 
-	for (i = 0; i < HNS3_MAX_TC_NUM; i++) {
-		dcb_info->tc_queue.tc_rxq[0][i].base =
-					hw->tc_queue[i].tqp_offset;
+	for (i = 0; i < hw->num_tc; i++) {
+		dcb_info->tc_queue.tc_rxq[0][i].base = hw->alloc_rss_size * i;
 		dcb_info->tc_queue.tc_txq[0][i].base =
-					hw->tc_queue[i].tqp_offset;
-		dcb_info->tc_queue.tc_rxq[0][i].nb_queue =
-					hw->tc_queue[i].tqp_count;
+						hw->tc_queue[i].tqp_offset;
+		dcb_info->tc_queue.tc_rxq[0][i].nb_queue = hw->alloc_rss_size;
 		dcb_info->tc_queue.tc_txq[0][i].nb_queue =
-					hw->tc_queue[i].tqp_count;
+						hw->tc_queue[i].tqp_count;
 	}
 	rte_spinlock_unlock(&hw->lock);
 
@@ -4327,31 +4951,24 @@ hns3_reinit_dev(struct hns3_adapter *hns)
 	ret = hns3_reset_all_queues(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to reset all queues: %d", ret);
-		goto err_init;
+		return ret;
 	}
 
 	ret = hns3_init_hardware(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to init hardware: %d", ret);
-		goto err_init;
+		return ret;
 	}
 
 	ret = hns3_enable_hw_error_intr(hns, true);
 	if (ret) {
 		hns3_err(hw, "fail to enable hw error interrupts: %d",
 			     ret);
-		goto err_mac_init;
+		return ret;
 	}
 	hns3_info(hw, "Reset done, driver initialization finished.");
 
 	return 0;
-
-err_mac_init:
-	hns3_uninit_umv_space(hw);
-err_init:
-	hns3_cmd_uninit(hw);
-
-	return ret;
 }
 
 static bool
@@ -4573,7 +5190,8 @@ hns3_stop_service(struct hns3_adapter *hns)
 	struct rte_eth_dev *eth_dev;
 
 	eth_dev = &rte_eth_devices[hw->data->port_id];
-	rte_eal_alarm_cancel(hns3_service_handler, eth_dev);
+	if (hw->adapter_state == HNS3_NIC_STARTED)
+		rte_eal_alarm_cancel(hns3_service_handler, eth_dev);
 	hw->mac.link_status = ETH_LINK_DOWN;
 
 	hns3_set_rxtx_function(eth_dev);
@@ -4614,7 +5232,18 @@ hns3_start_service(struct hns3_adapter *hns)
 	eth_dev = &rte_eth_devices[hw->data->port_id];
 	hns3_set_rxtx_function(eth_dev);
 	hns3_mp_req_start_rxtx(eth_dev);
-	hns3_service_handler(eth_dev);
+	if (hw->adapter_state == HNS3_NIC_STARTED) {
+		hns3_service_handler(eth_dev);
+
+		/* Enable interrupt of all rx queues before enabling queues */
+		hns3_dev_all_rx_queue_intr_enable(hw, true);
+		/*
+		 * When finished the initialization, enable queues to receive
+		 * and transmit packets.
+		 */
+		hns3_enable_all_queues(hw, true);
+	}
+
 	return 0;
 }
 
@@ -4648,6 +5277,10 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+	ret = hns3_restore_rx_interrupt(hw);
+	if (ret)
+		goto err_promisc;
+
 	if (hns->hw.adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3_do_start(hns, false);
 		if (ret)
@@ -4748,6 +5381,8 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.tx_queue_setup         = hns3_tx_queue_setup,
 	.rx_queue_release       = hns3_dev_rx_queue_release,
 	.tx_queue_release       = hns3_dev_tx_queue_release,
+	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
 	.dev_configure          = hns3_dev_configure,
 	.flow_ctrl_get          = hns3_flow_ctrl_get,
 	.flow_ctrl_set          = hns3_flow_ctrl_set,
@@ -4787,6 +5422,8 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)
 	struct rte_device *dev = eth_dev->device;
 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev);
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *eth_addr;
 	struct hns3_hw *hw = &hns->hw;
 	uint16_t device_id = pci_dev->id.device_id;
 	int ret;
@@ -4806,12 +5443,25 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)
 	hns3_set_rxtx_function(eth_dev);
 	eth_dev->dev_ops = &hns3_eth_dev_ops;
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-		hns3_mp_init_secondary();
+		ret = hns3_mp_init_secondary();
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Failed to init for secondary "
+				     "process, ret = %d", ret);
+			goto err_mp_init_secondary;
+		}
+
 		hw->secondary_cnt++;
 		return 0;
 	}
 
-	hns3_mp_init_primary();
+	ret = hns3_mp_init_primary();
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "Failed to init for primary process, ret = %d",
+			     ret);
+		goto err_mp_init_primary;
+	}
+
 	hw->adapter_state = HNS3_NIC_UNINITIALIZED;
 
 	if (device_id == HNS3_DEV_ID_25GE_RDMA ||
@@ -4852,6 +5502,15 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)
 		goto err_rte_zmalloc;
 	}
 
+	eth_addr = (struct rte_ether_addr *)hw->mac.mac_addr;
+	if (!rte_is_valid_assigned_ether_addr(eth_addr)) {
+		rte_eth_random_addr(hw->mac.mac_addr);
+		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				(struct rte_ether_addr *)hw->mac.mac_addr);
+		hns3_warn(hw, "default mac_addr from firmware is an invalid "
+			  "unicast address, using random MAC address %s",
+			  mac_str);
+	}
 	rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.mac_addr,
 			    &eth_dev->data->mac_addrs[0]);
 
@@ -4870,7 +5529,6 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)
 		hns3_notify_reset_ready(hw, false);
 	}
 
-	rte_eal_alarm_set(HNS3_SERVICE_INTERVAL, hns3_service_handler, eth_dev);
 	hns3_info(hw, "hns3 dev initialization successful!");
 	return 0;
 
@@ -4879,7 +5537,12 @@ hns3_dev_init(struct rte_eth_dev *eth_dev)
 
 err_init_pf:
 	rte_free(hw->reset.wait_data);
+
 err_init_reset:
+	hns3_mp_uninit_primary();
+
+err_mp_init_primary:
+err_mp_init_secondary:
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
@@ -4897,8 +5560,11 @@ hns3_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	PMD_INIT_FUNC_TRACE();
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return -EPERM;
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->process_private);
+		eth_dev->process_private = NULL;
+		return 0;
+	}
 
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
diff --git a/dpdk/drivers/net/hns3/hns3_ethdev.h b/dpdk/drivers/net/hns3/hns3_ethdev.h
index e9a3fe4107..8ba22dc424 100644
--- a/dpdk/drivers/net/hns3/hns3_ethdev.h
+++ b/dpdk/drivers/net/hns3/hns3_ethdev.h
@@ -145,7 +145,7 @@ enum hns3_media_type {
 
 struct hns3_mac {
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
-	bool default_addr_setted; /* whether default addr(mac_addr) is setted */
+	bool default_addr_setted; /* whether default addr(mac_addr) is set */
 	uint8_t media_type;
 	uint8_t phy_addr;
 	uint8_t link_duplex  : 1; /* ETH_LINK_[HALF/FULL]_DUPLEX */
@@ -154,6 +154,19 @@ struct hns3_mac {
 	uint32_t link_speed;      /* ETH_SPEED_NUM_ */
 };
 
+struct hns3_fake_queue_data {
+	void **rx_queues; /* Array of pointers to fake RX queues. */
+	void **tx_queues; /* Array of pointers to fake TX queues. */
+	uint16_t nb_fake_rx_queues; /* Number of fake RX queues. */
+	uint16_t nb_fake_tx_queues; /* Number of fake TX queues. */
+};
+
+#define HNS3_PORT_BASE_VLAN_DISABLE	0
+#define HNS3_PORT_BASE_VLAN_ENABLE	1
+struct hns3_port_base_vlan_config {
+	uint16_t state;
+	uint16_t pvid;
+};
 
 /* Primary process maintains driver state in main thread.
  *
@@ -243,6 +256,13 @@ enum hns3_reset_level {
 	 * Kernel PF driver use mailbox to inform DPDK VF to do reset, the value
 	 * of the reset level and the one defined in kernel driver should be
 	 * same.
+	 *
+	 * According to the protocol of PCIe, FLR to a PF resets the PF state as
+	 * well as the SR-IOV extended capability including VF Enable which
+	 * means that VFs no longer exist.
+	 *
+	 * In PF FLR, the register state of VF is not reliable, VF's driver
+	 * should not access the registers of the VF device.
 	 */
 	HNS3_VF_FULL_RESET = 3,
 	HNS3_FLR_RESET,     /* A VF perform FLR reset */
@@ -348,8 +368,8 @@ struct hns3_hw {
 	uint16_t num_msi;
 	uint16_t total_tqps_num;    /* total task queue pairs of this PF */
 	uint16_t tqps_num;          /* num task queue pairs of this function */
+	uint16_t intr_tqps_num;     /* num queue pairs mapping interrupt */
 	uint16_t rss_size_max;      /* HW defined max RSS task queue */
-	uint16_t rx_buf_len;
 	uint16_t num_tx_desc;       /* desc num of per tx queue */
 	uint16_t num_rx_desc;       /* desc num of per rx queue */
 
@@ -358,6 +378,7 @@ struct hns3_hw {
 
 	/* The configuration info of RSS */
 	struct hns3_rss_conf rss_info;
+	bool rss_dis_flag; /* disable rss flag. true: disable, false: enable */
 
 	uint8_t num_tc;             /* Total number of enabled TCs */
 	uint8_t hw_tc_map;
@@ -366,10 +387,18 @@ struct hns3_hw {
 	struct hns3_dcb_info dcb_info;
 	enum hns3_fc_status current_fc_status; /* current flow control status */
 	struct hns3_tc_queue_info tc_queue[HNS3_MAX_TC_NUM];
-	uint16_t alloc_tqps;
-	uint16_t alloc_rss_size;    /* Queue number per TC */
+	uint16_t used_rx_queues;
+	uint16_t used_tx_queues;
+
+	/* Config max queue numbers between rx and tx queues from user */
+	uint16_t cfg_max_queues;
+	struct hns3_fake_queue_data fkq_data;     /* fake queue data */
+	uint16_t alloc_rss_size;    /* RX queue number per TC */
+	uint16_t tx_qnum_per_tc;    /* TX queue number per TC */
 
 	uint32_t flag;
+
+	struct hns3_port_base_vlan_config port_base_vlan_cfg;
 	/*
 	 * PMD setup and configuration is not thread safe. Since it is not
 	 * performance sensitive, it is better to guarantee thread-safety
@@ -399,11 +428,6 @@ struct hns3_user_vlan_table {
 	uint16_t vlan_id;
 };
 
-struct hns3_port_base_vlan_config {
-	uint16_t state;
-	uint16_t pvid;
-};
-
 /* Vlan tag configuration for RX direction */
 struct hns3_rx_vtag_cfg {
 	uint8_t rx_vlan_offload_en; /* Whether enable rx vlan offload */
@@ -453,6 +477,7 @@ struct hns3_mp_param {
 struct hns3_pf {
 	struct hns3_adapter *adapter;
 	bool is_main_pf;
+	uint16_t func_num; /* num functions of this pf, include pf and vfs */
 
 	uint32_t pkt_buf_size; /* Total pf buf size for tx/rx */
 	uint32_t tx_buf_size; /* Tx buffer size for each TC */
@@ -478,7 +503,6 @@ struct hns3_pf {
 	bool support_sfp_query;
 
 	struct hns3_vtag_cfg vtag_config;
-	struct hns3_port_base_vlan_config port_base_vlan_cfg;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
 
 	struct hns3_fdir_info fdir; /* flow director info */
@@ -528,6 +552,8 @@ struct hns3_adapter {
 #define hns3_get_bit(origin, shift) \
 	hns3_get_field((origin), (0x1UL << (shift)), (shift))
 
+#define hns3_gen_field_val(mask, shift, val) (((val) << (shift)) & (mask))
+
 /*
  * upper_32_bits - return bits 32-63 of a number
  * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress
@@ -555,14 +581,39 @@ struct hns3_adapter {
 	type __max2 = (y);                      \
 	__max1 > __max2 ? __max1 : __max2; })
 
+/*
+ * Because hardware always access register in little-endian mode based on hns3
+ * network engine, so driver should also call rte_cpu_to_le_32 to convert data
+ * in little-endian mode before writing register and call rte_le_to_cpu_32 to
+ * convert data after reading from register.
+ *
+ * Here the driver encapsulates the data conversion operation in the register
+ * read/write operation function as below:
+ *   hns3_write_reg
+ *   hns3_write_reg_opt
+ *   hns3_read_reg
+ * Therefore, when calling these functions, conversion is not required again.
+ */
 static inline void hns3_write_reg(void *base, uint32_t reg, uint32_t value)
 {
-	rte_write32(value, (volatile void *)((char *)base + reg));
+	rte_write32(rte_cpu_to_le_32(value),
+		    (volatile void *)((char *)base + reg));
+}
+
+/*
+ * The optimized function for writing registers used in the '.rx_pkt_burst' and
+ * '.tx_pkt_burst' ops implementation function.
+ */
+static inline void hns3_write_reg_opt(volatile void *addr, uint32_t value)
+{
+	rte_io_wmb();
+	rte_write32_relaxed(rte_cpu_to_le_32(value), addr);
 }
 
 static inline uint32_t hns3_read_reg(void *base, uint32_t reg)
 {
-	return rte_read32((volatile void *)((char *)base + reg));
+	uint32_t read_val = rte_read32((volatile void *)((char *)base + reg));
+	return rte_le_to_cpu_32(read_val);
 }
 
 #define hns3_write_dev(a, reg, value) \
@@ -631,6 +682,7 @@ int hns3_dev_filter_ctrl(struct rte_eth_dev *dev,
 			 enum rte_filter_op filter_op, void *arg);
 bool hns3_is_reset_pending(struct hns3_adapter *hns);
 bool hns3vf_is_reset_pending(struct hns3_adapter *hns);
+void hns3_update_link_status(struct hns3_hw *hw);
 
 static inline bool
 is_reset_pending(struct hns3_adapter *hns)
diff --git a/dpdk/drivers/net/hns3/hns3_ethdev_vf.c b/dpdk/drivers/net/hns3/hns3_ethdev_vf.c
index b1736e73ab..c936114075 100644
--- a/dpdk/drivers/net/hns3/hns3_ethdev_vf.c
+++ b/dpdk/drivers/net/hns3/hns3_ethdev_vf.c
@@ -59,13 +59,23 @@ static enum hns3_reset_level hns3vf_get_reset_level(struct hns3_hw *hw,
 static int hns3vf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
 static int hns3vf_dev_configure_vlan(struct rte_eth_dev *dev);
 
+static int hns3vf_add_mc_mac_addr(struct hns3_hw *hw,
+				  struct rte_ether_addr *mac_addr);
+static int hns3vf_remove_mc_mac_addr(struct hns3_hw *hw,
+				     struct rte_ether_addr *mac_addr);
 /* set PCI bus mastering */
-static void
+static int
 hns3vf_set_bus_master(const struct rte_pci_device *device, bool op)
 {
 	uint16_t reg;
+	int ret;
 
-	rte_pci_read_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	ret = rte_pci_read_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+			     PCI_COMMAND);
+		return ret;
+	}
 
 	if (op)
 		/* set the master bit */
@@ -73,7 +83,7 @@ hns3vf_set_bus_master(const struct rte_pci_device *device, bool op)
 	else
 		reg &= ~(PCI_COMMAND_MASTER);
 
-	rte_pci_write_config(device, &reg, sizeof(reg), PCI_COMMAND);
+	return rte_pci_write_config(device, &reg, sizeof(reg), PCI_COMMAND);
 }
 
 /**
@@ -90,16 +100,34 @@ hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)
 	uint8_t pos;
 	uint8_t id;
 	int ttl;
+	int ret;
+
+	ret = rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", PCI_STATUS);
+		return 0;
+	}
 
-	rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);
 	if (!(status & PCI_STATUS_CAP_LIST))
 		return 0;
 
 	ttl = MAX_PCIE_CAPABILITY;
-	rte_pci_read_config(device, &pos, sizeof(pos), PCI_CAPABILITY_LIST);
+	ret = rte_pci_read_config(device, &pos, sizeof(pos),
+				  PCI_CAPABILITY_LIST);
+	if (ret < 0) {
+		PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+			     PCI_CAPABILITY_LIST);
+		return 0;
+	}
+
 	while (ttl-- && pos >= PCI_STD_HEADER_SIZEOF) {
-		rte_pci_read_config(device, &id, sizeof(id),
-				    (pos + PCI_CAP_LIST_ID));
+		ret = rte_pci_read_config(device, &id, sizeof(id),
+					  (pos + PCI_CAP_LIST_ID));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_CAP_LIST_ID));
+			break;
+		}
 
 		if (id == 0xFF)
 			break;
@@ -107,8 +135,13 @@ hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)
 		if (id == cap)
 			return (int)pos;
 
-		rte_pci_read_config(device, &pos, sizeof(pos),
-				    (pos + PCI_CAP_LIST_NEXT));
+		ret = rte_pci_read_config(device, &pos, sizeof(pos),
+					  (pos + PCI_CAP_LIST_NEXT));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_CAP_LIST_NEXT));
+			break;
+		}
 	}
 	return 0;
 }
@@ -118,22 +151,103 @@ hns3vf_enable_msix(const struct rte_pci_device *device, bool op)
 {
 	uint16_t control;
 	int pos;
+	int ret;
 
 	pos = hns3vf_find_pci_capability(device, PCI_CAP_ID_MSIX);
 	if (pos) {
-		rte_pci_read_config(device, &control, sizeof(control),
+		ret = rte_pci_read_config(device, &control, sizeof(control),
 				    (pos + PCI_MSIX_FLAGS));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x",
+				     (pos + PCI_MSIX_FLAGS));
+			return -ENXIO;
+		}
+
 		if (op)
 			control |= PCI_MSIX_FLAGS_ENABLE;
 		else
 			control &= ~PCI_MSIX_FLAGS_ENABLE;
-		rte_pci_write_config(device, &control, sizeof(control),
-				     (pos + PCI_MSIX_FLAGS));
+		ret = rte_pci_write_config(device, &control, sizeof(control),
+					  (pos + PCI_MSIX_FLAGS));
+		if (ret < 0) {
+			PMD_INIT_LOG(ERR, "failed to write PCI offset 0x%x",
+				    (pos + PCI_MSIX_FLAGS));
+		}
 		return 0;
 	}
 	return -1;
 }
 
+static int
+hns3vf_add_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
+{
+	/* mac address was checked by upper level interface */
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_UNICAST,
+				HNS3_MBX_MAC_VLAN_UC_ADD, mac_addr->addr_bytes,
+				RTE_ETHER_ADDR_LEN, false, NULL, 0);
+	if (ret) {
+		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add uc mac addr(%s), ret = %d",
+			 mac_str, ret);
+	}
+	return ret;
+}
+
+static int
+hns3vf_remove_uc_mac_addr(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
+{
+	/* mac address was checked by upper level interface */
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	int ret;
+
+	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_UNICAST,
+				HNS3_MBX_MAC_VLAN_UC_REMOVE,
+				mac_addr->addr_bytes, RTE_ETHER_ADDR_LEN,
+				false, NULL, 0);
+	if (ret) {
+		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add uc mac addr(%s), ret = %d",
+			 mac_str, ret);
+	}
+	return ret;
+}
+
+static int
+hns3vf_add_mc_addr_common(struct hns3_hw *hw, struct rte_ether_addr *mac_addr)
+{
+	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
+	struct rte_ether_addr *addr;
+	int ret;
+	int i;
+
+	for (i = 0; i < hw->mc_addrs_num; i++) {
+		addr = &hw->mc_addrs[i];
+		/* Check if there are duplicate addresses */
+		if (rte_is_same_ether_addr(addr, mac_addr)) {
+			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_err(hw, "failed to add mc mac addr, same addrs"
+				 "(%s) is added by the set_mc_mac_addr_list "
+				 "API", mac_str);
+			return -EINVAL;
+		}
+	}
+
+	ret = hns3vf_add_mc_mac_addr(hw, mac_addr);
+	if (ret) {
+		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+				      mac_addr);
+		hns3_err(hw, "failed to add mc mac addr(%s), ret = %d",
+			 mac_str, ret);
+	}
+	return ret;
+}
+
 static int
 hns3vf_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
 		    __attribute__ ((unused)) uint32_t idx,
@@ -144,14 +258,26 @@ hns3vf_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
 	int ret;
 
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_UNICAST,
-				HNS3_MBX_MAC_VLAN_UC_ADD, mac_addr->addr_bytes,
-				RTE_ETHER_ADDR_LEN, false, NULL, 0);
+
+	/*
+	 * In hns3 network engine adding UC and MC mac address with different
+	 * commands with firmware. We need to determine whether the input
+	 * address is a UC or a MC address to call different commands.
+	 * By the way, it is recommended calling the API function named
+	 * rte_eth_dev_set_mc_addr_list to set the MC mac address, because
+	 * using the rte_eth_dev_mac_addr_add API function to set MC mac address
+	 * may affect the specifications of UC mac addresses.
+	 */
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hns3vf_add_mc_addr_common(hw, mac_addr);
+	else
+		ret = hns3vf_add_uc_mac_addr(hw, mac_addr);
+
 	rte_spinlock_unlock(&hw->lock);
 	if (ret) {
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Failed to add mac addr(%s) for vf: %d", mac_str,
+		hns3_err(hw, "failed to add mac addr(%s), ret = %d", mac_str,
 			 ret);
 	}
 
@@ -168,15 +294,17 @@ hns3vf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t idx)
 	int ret;
 
 	rte_spinlock_lock(&hw->lock);
-	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_UNICAST,
-				HNS3_MBX_MAC_VLAN_UC_REMOVE,
-				mac_addr->addr_bytes, RTE_ETHER_ADDR_LEN, false,
-				NULL, 0);
+
+	if (rte_is_multicast_ether_addr(mac_addr))
+		ret = hns3vf_remove_mc_mac_addr(hw, mac_addr);
+	else
+		ret = hns3vf_remove_uc_mac_addr(hw, mac_addr);
+
 	rte_spinlock_unlock(&hw->lock);
 	if (ret) {
 		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 				      mac_addr);
-		hns3_err(hw, "Failed to remove mac addr(%s) for vf: %d",
+		hns3_err(hw, "failed to remove mac addr(%s), ret = %d",
 			 mac_str, ret);
 	}
 }
@@ -228,39 +356,39 @@ hns3vf_configure_mac_addr(struct hns3_adapter *hns, bool del)
 {
 	struct hns3_hw *hw = &hns->hw;
 	struct rte_ether_addr *addr;
-	enum hns3_mbx_mac_vlan_subcode opcode;
 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int ret = 0;
+	int err = 0;
+	int ret;
 	int i;
 
-	if (del)
-		opcode = HNS3_MBX_MAC_VLAN_UC_REMOVE;
-	else
-		opcode = HNS3_MBX_MAC_VLAN_UC_ADD;
 	for (i = 0; i < HNS3_VF_UC_MACADDR_NUM; i++) {
 		addr = &hw->data->mac_addrs[i];
-		if (!rte_is_valid_assigned_ether_addr(addr))
+		if (rte_is_zero_ether_addr(addr))
 			continue;
-		rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE, addr);
-		hns3_dbg(hw, "rm mac addr: %s", mac_str);
-		ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_UNICAST, opcode,
-					addr->addr_bytes, RTE_ETHER_ADDR_LEN,
-					false, NULL, 0);
+		if (rte_is_multicast_ether_addr(addr))
+			ret = del ? hns3vf_remove_mc_mac_addr(hw, addr) :
+			      hns3vf_add_mc_mac_addr(hw, addr);
+		else
+			ret = del ? hns3vf_remove_uc_mac_addr(hw, addr) :
+			      hns3vf_add_uc_mac_addr(hw, addr);
+
 		if (ret) {
-			hns3_err(hw, "Failed to remove mac addr for vf: %d",
-				 ret);
-			break;
+			err = ret;
+			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
+					      addr);
+			hns3_err(hw, "failed to %s mac addr(%s) index:%d "
+				 "ret = %d.", del ? "remove" : "restore",
+				 mac_str, i, ret);
 		}
 	}
-	return ret;
+	return err;
 }
 
 static int
-hns3vf_add_mc_mac_addr(struct hns3_adapter *hns,
+hns3vf_add_mc_mac_addr(struct hns3_hw *hw,
 		       struct rte_ether_addr *mac_addr)
 {
 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
 	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_MULTICAST,
@@ -279,11 +407,10 @@ hns3vf_add_mc_mac_addr(struct hns3_adapter *hns,
 }
 
 static int
-hns3vf_remove_mc_mac_addr(struct hns3_adapter *hns,
+hns3vf_remove_mc_mac_addr(struct hns3_hw *hw,
 			  struct rte_ether_addr *mac_addr)
 {
 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
 	ret = hns3_send_mbx_msg(hw, HNS3_MBX_SET_MULTICAST,
@@ -302,45 +429,92 @@ hns3vf_remove_mc_mac_addr(struct hns3_adapter *hns,
 }
 
 static int
-hns3vf_set_mc_mac_addr_list(struct rte_eth_dev *dev,
-			    struct rte_ether_addr *mc_addr_set,
-			    uint32_t nb_mc_addr)
+hns3vf_set_mc_addr_chk_param(struct hns3_hw *hw,
+			     struct rte_ether_addr *mc_addr_set,
+			     uint32_t nb_mc_addr)
 {
-	struct hns3_adapter *hns = dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
-	struct rte_ether_addr *addr;
 	char mac_str[RTE_ETHER_ADDR_FMT_SIZE];
-	int cur_addr_num;
-	int set_addr_num;
-	int num;
-	int ret;
-	int i;
+	struct rte_ether_addr *addr;
+	uint32_t i;
+	uint32_t j;
 
 	if (nb_mc_addr > HNS3_MC_MACADDR_NUM) {
-		hns3_err(hw, "Failed to set mc mac addr, nb_mc_addr(%d) "
+		hns3_err(hw, "failed to set mc mac addr, nb_mc_addr(%d) "
 			 "invalid. valid range: 0~%d",
 			 nb_mc_addr, HNS3_MC_MACADDR_NUM);
 		return -EINVAL;
 	}
 
-	set_addr_num = (int)nb_mc_addr;
-	for (i = 0; i < set_addr_num; i++) {
+	/* Check if input mac addresses are valid */
+	for (i = 0; i < nb_mc_addr; i++) {
 		addr = &mc_addr_set[i];
 		if (!rte_is_multicast_ether_addr(addr)) {
 			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
 					      addr);
 			hns3_err(hw,
-				 "Failed to set mc mac addr, addr(%s) invalid.",
+				 "failed to set mc mac addr, addr(%s) invalid.",
 				 mac_str);
 			return -EINVAL;
 		}
+
+		/* Check if there are duplicate addresses */
+		for (j = i + 1; j < nb_mc_addr; j++) {
+			if (rte_is_same_ether_addr(addr, &mc_addr_set[j])) {
+				rte_ether_format_addr(mac_str,
+						      RTE_ETHER_ADDR_FMT_SIZE,
+						      addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. two same addrs(%s).",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
+
+		/*
+		 * Check if there are duplicate addresses between mac_addrs
+		 * and mc_addr_set
+		 */
+		for (j = 0; j < HNS3_VF_UC_MACADDR_NUM; j++) {
+			if (rte_is_same_ether_addr(addr,
+						   &hw->data->mac_addrs[j])) {
+				rte_ether_format_addr(mac_str,
+						      RTE_ETHER_ADDR_FMT_SIZE,
+						      addr);
+				hns3_err(hw, "failed to set mc mac addr, "
+					 "addrs invalid. addrs(%s) has already "
+					 "configured in mac_addr add API",
+					 mac_str);
+				return -EINVAL;
+			}
+		}
 	}
+
+	return 0;
+}
+
+static int
+hns3vf_set_mc_mac_addr_list(struct rte_eth_dev *dev,
+			    struct rte_ether_addr *mc_addr_set,
+			    uint32_t nb_mc_addr)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_ether_addr *addr;
+	int cur_addr_num;
+	int set_addr_num;
+	int num;
+	int ret;
+	int i;
+
+	ret = hns3vf_set_mc_addr_chk_param(hw, mc_addr_set, nb_mc_addr);
+	if (ret)
+		return ret;
+
 	rte_spinlock_lock(&hw->lock);
 	cur_addr_num = hw->mc_addrs_num;
 	for (i = 0; i < cur_addr_num; i++) {
 		num = cur_addr_num - i - 1;
 		addr = &hw->mc_addrs[num];
-		ret = hns3vf_remove_mc_mac_addr(hns, addr);
+		ret = hns3vf_remove_mc_mac_addr(hw, addr);
 		if (ret) {
 			rte_spinlock_unlock(&hw->lock);
 			return ret;
@@ -349,9 +523,10 @@ hns3vf_set_mc_mac_addr_list(struct rte_eth_dev *dev,
 		hw->mc_addrs_num--;
 	}
 
+	set_addr_num = (int)nb_mc_addr;
 	for (i = 0; i < set_addr_num; i++) {
 		addr = &mc_addr_set[i];
-		ret = hns3vf_add_mc_mac_addr(hns, addr);
+		ret = hns3vf_add_mc_mac_addr(hw, addr);
 		if (ret) {
 			rte_spinlock_unlock(&hw->lock);
 			return ret;
@@ -380,9 +555,9 @@ hns3vf_configure_all_mc_mac_addr(struct hns3_adapter *hns, bool del)
 		if (!rte_is_multicast_ether_addr(addr))
 			continue;
 		if (del)
-			ret = hns3vf_remove_mc_mac_addr(hns, addr);
+			ret = hns3vf_remove_mc_mac_addr(hw, addr);
 		else
-			ret = hns3vf_add_mc_mac_addr(hns, addr);
+			ret = hns3vf_add_mc_mac_addr(hw, addr);
 		if (ret) {
 			err = ret;
 			rte_ether_format_addr(mac_str, RTE_ETHER_ADDR_FMT_SIZE,
@@ -414,6 +589,97 @@ hns3vf_set_promisc_mode(struct hns3_hw *hw, bool en_bc_pmc)
 	return ret;
 }
 
+static int
+hns3vf_bind_ring_with_vector(struct hns3_hw *hw, uint8_t vector_id,
+			     bool mmap, enum hns3_ring_type queue_type,
+			     uint16_t queue_id)
+{
+	struct hns3_vf_bind_vector_msg bind_msg;
+	const char *op_str;
+	uint16_t code;
+	int ret;
+
+	memset(&bind_msg, 0, sizeof(bind_msg));
+	code = mmap ? HNS3_MBX_MAP_RING_TO_VECTOR :
+		HNS3_MBX_UNMAP_RING_TO_VECTOR;
+	bind_msg.vector_id = vector_id;
+
+	if (queue_type == HNS3_RING_TYPE_RX)
+		bind_msg.param[0].int_gl_index = HNS3_RING_GL_RX;
+	else
+		bind_msg.param[0].int_gl_index = HNS3_RING_GL_TX;
+
+	bind_msg.param[0].ring_type = queue_type;
+	bind_msg.ring_num = 1;
+	bind_msg.param[0].tqp_index = queue_id;
+	op_str = mmap ? "Map" : "Unmap";
+	ret = hns3_send_mbx_msg(hw, code, 0, (uint8_t *)&bind_msg,
+				sizeof(bind_msg), false, NULL, 0);
+	if (ret) {
+		hns3_err(hw, "%s TQP %d fail, vector_id is %d, ret is %d.",
+			 op_str, queue_id, bind_msg.vector_id, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+hns3vf_init_ring_with_vector(struct hns3_hw *hw)
+{
+	uint8_t vec;
+	int ret;
+	int i;
+
+	/*
+	 * In hns3 network engine, vector 0 is always the misc interrupt of this
+	 * function, vector 1~N can be used respectively for the queues of the
+	 * function. Tx and Rx queues with the same number share the interrupt
+	 * vector. In the initialization clearing the all hardware mapping
+	 * relationship configurations between queues and interrupt vectors is
+	 * needed, so some error caused by the residual configurations, such as
+	 * the unexpected Tx interrupt, can be avoid. Because of the hardware
+	 * constraints in hns3 hardware engine, we have to implement clearing
+	 * the mapping relationship configurations by binding all queues to the
+	 * last interrupt vector and reserving the last interrupt vector. This
+	 * method results in a decrease of the maximum queues when upper
+	 * applications call the rte_eth_dev_configure API function to enable
+	 * Rx interrupt.
+	 */
+	vec = hw->num_msi - 1; /* vector 0 for misc interrupt, not for queue */
+	/* vec - 1: the last interrupt is reserved */
+	hw->intr_tqps_num = vec > hw->tqps_num ? hw->tqps_num : vec - 1;
+	for (i = 0; i < hw->intr_tqps_num; i++) {
+		/*
+		 * Set gap limiter and rate limiter configuration of queue's
+		 * interrupt.
+		 */
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_RX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_gl(hw, i, HNS3_RING_GL_TX,
+				       HNS3_TQP_INTR_GL_DEFAULT);
+		hns3_set_queue_intr_rl(hw, i, HNS3_TQP_INTR_RL_DEFAULT);
+
+		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
+						   HNS3_RING_TYPE_TX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "VF fail to unbind TX ring(%d) with "
+					  "vector: %d, ret=%d", i, vec, ret);
+			return ret;
+		}
+
+		ret = hns3vf_bind_ring_with_vector(hw, vec, false,
+						   HNS3_RING_TYPE_RX, i);
+		if (ret) {
+			PMD_INIT_LOG(ERR, "VF fail to unbind RX ring(%d) with "
+					  "vector: %d, ret=%d", i, vec, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int
 hns3vf_dev_configure(struct rte_eth_dev *dev)
 {
@@ -424,30 +690,37 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)
 	uint16_t nb_rx_q = dev->data->nb_rx_queues;
 	uint16_t nb_tx_q = dev->data->nb_tx_queues;
 	struct rte_eth_rss_conf rss_conf;
+	uint32_t max_rx_pkt_len;
 	uint16_t mtu;
 	int ret;
 
 	/*
-	 * Hardware does not support where the number of rx and tx queues is
-	 * not equal in hip08.
+	 * Hardware does not support individually enable/disable/reset the Tx or
+	 * Rx queue in hns3 network engine. Driver must enable/disable/reset Tx
+	 * and Rx queues at the same time. When the numbers of Tx queues
+	 * allocated by upper applications are not equal to the numbers of Rx
+	 * queues, driver needs to setup fake Tx or Rx queues to adjust numbers
+	 * of Tx/Rx queues. otherwise, network engine can not work as usual. But
+	 * these fake queues are imperceptible, and can not be used by upper
+	 * applications.
 	 */
-	if (nb_rx_q != nb_tx_q) {
-		hns3_err(hw,
-			 "nb_rx_queues(%u) not equal with nb_tx_queues(%u)! "
-			 "Hardware does not support this configuration!",
-			 nb_rx_q, nb_tx_q);
-		return -EINVAL;
+	ret = hns3_set_fake_rx_or_tx_queues(dev, nb_rx_q, nb_tx_q);
+	if (ret) {
+		hns3_err(hw, "Failed to set rx/tx fake queues: %d", ret);
+		return ret;
 	}
 
+	hw->adapter_state = HNS3_NIC_CONFIGURING;
 	if (conf->link_speeds & ETH_LINK_SPEED_FIXED) {
 		hns3_err(hw, "setting link speed/duplex not supported");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto cfg_err;
 	}
 
-	hw->adapter_state = HNS3_NIC_CONFIGURING;
-
 	/* When RSS is not configured, redirect the packet queue 0 */
 	if ((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG) {
+		conf->rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+		hw->rss_dis_flag = false;
 		rss_conf = conf->rx_adv_conf.rss_conf;
 		if (rss_conf.rss_key == NULL) {
 			rss_conf.rss_key = rss_cfg->key;
@@ -464,12 +737,18 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)
 	 * according to the maximum RX packet length.
 	 */
 	if (conf->rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
-		/*
-		 * Security of max_rx_pkt_len is guaranteed in dpdk frame.
-		 * Maximum value of max_rx_pkt_len is HNS3_MAX_FRAME_LEN, so it
-		 * can safely assign to "uint16_t" type variable.
-		 */
-		mtu = (uint16_t)HNS3_PKTLEN_TO_MTU(conf->rxmode.max_rx_pkt_len);
+		max_rx_pkt_len = conf->rxmode.max_rx_pkt_len;
+		if (max_rx_pkt_len > HNS3_MAX_FRAME_LEN ||
+		    max_rx_pkt_len <= HNS3_DEFAULT_FRAME_LEN) {
+			hns3_err(hw, "maximum Rx packet length must be greater "
+				 "than %u and less than %u when jumbo frame enabled.",
+				 (uint16_t)HNS3_DEFAULT_FRAME_LEN,
+				 (uint16_t)HNS3_MAX_FRAME_LEN);
+			ret = -EINVAL;
+			goto cfg_err;
+		}
+
+		mtu = (uint16_t)HNS3_PKTLEN_TO_MTU(max_rx_pkt_len);
 		ret = hns3vf_dev_mtu_set(dev, mtu);
 		if (ret)
 			goto cfg_err;
@@ -484,7 +763,9 @@ hns3vf_dev_configure(struct rte_eth_dev *dev)
 	return 0;
 
 cfg_err:
+	(void)hns3_set_fake_rx_or_tx_queues(dev, 0, 0);
 	hw->adapter_state = HNS3_NIC_INITIALIZED;
+
 	return ret;
 }
 
@@ -508,12 +789,14 @@ hns3vf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	uint32_t frame_size = mtu + HNS3_ETH_OVERHEAD;
 	int ret;
 
-	if (dev->data->dev_started) {
-		hns3_err(hw, "Failed to set mtu, port %u must be stopped "
-			 "before configuration", dev->data->port_id);
-		return -EBUSY;
-	}
-
+	/*
+	 * The hns3 PF/VF devices on the same port share the hardware MTU
+	 * configuration. Currently, we send mailbox to inform hns3 PF kernel
+	 * ethdev driver to finish hardware MTU configuration in hns3 VF PMD
+	 * driver, there is no need to stop the port for hns3 VF device, and the
+	 * MTU value issued by hns3 VF PMD driver must be less than or equal to
+	 * PF's MTU.
+	 */
 	if (rte_atomic16_read(&hw->reset.resetting)) {
 		hns3_err(hw, "Failed to set mtu during resetting");
 		return -EIO;
@@ -525,7 +808,7 @@ hns3vf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (mtu > RTE_ETHER_MTU)
 		dev->data->dev_conf.rxmode.offloads |=
 						DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
@@ -542,11 +825,19 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 {
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
+	uint16_t q_num = hw->tqps_num;
+
+	/*
+	 * In interrupt mode, 'max_rx_queues' is set based on the number of
+	 * MSI-X interrupt resources of the hardware.
+	 */
+	if (hw->data->dev_conf.intr_conf.rxq == 1)
+		q_num = hw->intr_tqps_num;
 
-	info->max_rx_queues = hw->tqps_num;
+	info->max_rx_queues = q_num;
 	info->max_tx_queues = hw->tqps_num;
 	info->max_rx_pktlen = HNS3_MAX_FRAME_LEN; /* CRC included */
-	info->min_rx_bufsize = hw->rx_buf_len;
+	info->min_rx_bufsize = HNS3_MIN_BD_BUF_SIZE;
 	info->max_mac_addrs = HNS3_VF_UC_MACADDR_NUM;
 	info->max_mtu = info->max_rx_pktlen - HNS3_ETH_OVERHEAD;
 
@@ -559,10 +850,9 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_RX_OFFLOAD_KEEP_CRC |
 				 DEV_RX_OFFLOAD_SCATTER |
 				 DEV_RX_OFFLOAD_VLAN_STRIP |
-				 DEV_RX_OFFLOAD_QINQ_STRIP |
 				 DEV_RX_OFFLOAD_VLAN_FILTER |
-				 DEV_RX_OFFLOAD_JUMBO_FRAME);
-	info->tx_queue_offload_capa = DEV_TX_OFFLOAD_MBUF_FAST_FREE;
+				 DEV_RX_OFFLOAD_JUMBO_FRAME |
+				 DEV_RX_OFFLOAD_RSS_HASH);
 	info->tx_offload_capa = (DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
 				 DEV_TX_OFFLOAD_IPV4_CKSUM |
 				 DEV_TX_OFFLOAD_TCP_CKSUM |
@@ -571,7 +861,7 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 				 DEV_TX_OFFLOAD_VLAN_INSERT |
 				 DEV_TX_OFFLOAD_QINQ_INSERT |
 				 DEV_TX_OFFLOAD_MULTI_SEGS |
-				 info->tx_queue_offload_capa);
+				 DEV_TX_OFFLOAD_MBUF_FAST_FREE);
 
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
@@ -585,6 +875,17 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 		.nb_align = HNS3_ALIGN_RING_DESC,
 	};
 
+	info->default_rxconf = (struct rte_eth_rxconf) {
+		.rx_free_thresh = HNS3_DEFAULT_RX_FREE_THRESH,
+		/*
+		 * If there are no available Rx buffer descriptors, incoming
+		 * packets are always dropped by hardware based on hns3 network
+		 * engine.
+		 */
+		.rx_drop_en = 1,
+		.offloads = 0,
+	};
+
 	info->vmdq_queue_num = 0;
 
 	info->reta_size = HNS3_RSS_IND_TBL_SIZE;
@@ -710,8 +1011,6 @@ hns3vf_check_tqp_info(struct hns3_hw *hw)
 		return -EINVAL;
 	}
 
-	if (hw->rx_buf_len == 0)
-		hw->rx_buf_len = HNS3_DEFAULT_RX_BUF_LEN;
 	hw->alloc_rss_size = RTE_MIN(hw->rss_size_max, hw->tqps_num);
 
 	return 0;
@@ -733,7 +1032,6 @@ hns3vf_get_queue_info(struct hns3_hw *hw)
 
 	memcpy(&hw->tqps_num, &resp_msg[0], sizeof(uint16_t));
 	memcpy(&hw->rss_size_max, &resp_msg[2], sizeof(uint16_t));
-	memcpy(&hw->rx_buf_len, &resp_msg[4], sizeof(uint16_t));
 
 	return hns3vf_check_tqp_info(hw);
 }
@@ -784,6 +1082,7 @@ hns3vf_get_configuration(struct hns3_hw *hw)
 	int ret;
 
 	hw->mac.media_type = HNS3_MEDIA_TYPE_NONE;
+	hw->rss_dis_flag = false;
 
 	/* Get queue configuration from PF */
 	ret = hns3vf_get_queue_info(hw);
@@ -799,12 +1098,12 @@ hns3vf_get_configuration(struct hns3_hw *hw)
 	return hns3vf_get_tc_info(hw);
 }
 
-static void
+static int
 hns3vf_set_tc_info(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
 	uint16_t nb_rx_q = hw->data->nb_rx_queues;
-	uint16_t new_tqps;
+	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	uint8_t i;
 
 	hw->num_tc = 0;
@@ -812,11 +1111,22 @@ hns3vf_set_tc_info(struct hns3_adapter *hns)
 		if (hw->hw_tc_map & BIT(i))
 			hw->num_tc++;
 
-	new_tqps = RTE_MIN(hw->tqps_num, nb_rx_q);
-	hw->alloc_rss_size = RTE_MIN(hw->rss_size_max, new_tqps / hw->num_tc);
-	hw->alloc_tqps = hw->alloc_rss_size * hw->num_tc;
+	if (nb_rx_q < hw->num_tc) {
+		hns3_err(hw, "number of Rx queues(%d) is less than tcs(%d).",
+			 nb_rx_q, hw->num_tc);
+		return -EINVAL;
+	}
+
+	if (nb_tx_q < hw->num_tc) {
+		hns3_err(hw, "number of Tx queues(%d) is less than tcs(%d).",
+			 nb_tx_q, hw->num_tc);
+		return -EINVAL;
+	}
+
+	hns3_set_rss_size(hw, nb_rx_q);
+	hns3_tc_queue_mapping_cfg(hw, nb_tx_q);
 
-	hns3_tc_queue_mapping_cfg(hw);
+	return 0;
 }
 
 static void
@@ -895,6 +1205,13 @@ hns3vf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
 	unsigned int tmp_mask;
+	int ret = 0;
+
+	if (rte_atomic16_read(&hw->reset.resetting)) {
+		hns3_err(hw, "vf set vlan offload failed during resetting, "
+			     "mask = 0x%x", mask);
+		return -EIO;
+	}
 
 	tmp_mask = (unsigned int)mask;
 	/* Vlan stripping setting */
@@ -902,13 +1219,13 @@ hns3vf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 		rte_spinlock_lock(&hw->lock);
 		/* Enable or disable VLAN stripping */
 		if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-			hns3vf_en_hw_strip_rxvtag(hw, true);
+			ret = hns3vf_en_hw_strip_rxvtag(hw, true);
 		else
-			hns3vf_en_hw_strip_rxvtag(hw, false);
+			ret = hns3vf_en_hw_strip_rxvtag(hw, false);
 		rte_spinlock_unlock(&hw->lock);
 	}
 
-	return 0;
+	return ret;
 }
 
 static int
@@ -1055,6 +1372,35 @@ hns3vf_service_handler(void *param)
 			  eth_dev);
 }
 
+static int
+hns3_query_vf_resource(struct hns3_hw *hw)
+{
+	struct hns3_vf_res_cmd *req;
+	struct hns3_cmd_desc desc;
+	uint16_t num_msi;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_QUERY_VF_RSRC, true);
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "query vf resource failed, ret = %d", ret);
+		return ret;
+	}
+
+	req = (struct hns3_vf_res_cmd *)desc.data;
+	num_msi = hns3_get_field(rte_le_to_cpu_16(req->vf_intr_vector_number),
+				 HNS3_VEC_NUM_M, HNS3_VEC_NUM_S);
+	if (num_msi < HNS3_MIN_VECTOR_NUM) {
+		hns3_err(hw, "Just %u msi resources, not enough for vf(min:%d)",
+			 num_msi, HNS3_MIN_VECTOR_NUM);
+		return -EINVAL;
+	}
+
+	hw->num_msi = num_msi;
+
+	return 0;
+}
+
 static int
 hns3vf_init_hardware(struct hns3_adapter *hns)
 {
@@ -1082,13 +1428,24 @@ hns3vf_init_hardware(struct hns3_adapter *hns)
 		goto err_init_hardware;
 	}
 
+	/*
+	 * In the initialization clearing the all hardware mapping relationship
+	 * configurations between queues and interrupt vectors is needed, so
+	 * some error caused by the residual configurations, such as the
+	 * unexpected interrupt, can be avoid.
+	 */
+	ret = hns3vf_init_ring_with_vector(hw);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to init ring intr vector: %d", ret);
+		goto err_init_hardware;
+	}
+
 	ret = hns3vf_set_alive(hw, true);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to VF send alive to PF: %d", ret);
 		goto err_init_hardware;
 	}
 
-	hns3vf_request_link_info(hw);
 	return 0;
 
 err_init_hardware:
@@ -1131,6 +1488,11 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 		goto err_cmd_init;
 	}
 
+	/* Get VF resource */
+	ret = hns3_query_vf_resource(hw);
+	if (ret)
+		goto err_cmd_init;
+
 	rte_spinlock_init(&hw->mbx_resp.lock);
 
 	hns3vf_clear_event_cause(hw, 0);
@@ -1153,8 +1515,6 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 		goto err_get_config;
 	}
 
-	rte_eth_random_addr(hw->mac.mac_addr); /* Generate a random mac addr */
-
 	ret = hns3vf_clear_vport_list(hw);
 	if (ret) {
 		PMD_INIT_LOG(ERR, "Failed to clear tbl list: %d", ret);
@@ -1176,11 +1536,9 @@ hns3vf_init_vf(struct rte_eth_dev *eth_dev)
 	hns3_intr_unregister(&pci_dev->intr_handle, hns3vf_interrupt_handler,
 			     eth_dev);
 err_intr_callback_register:
-	hns3_cmd_uninit(hw);
-
 err_cmd_init:
+	hns3_cmd_uninit(hw);
 	hns3_cmd_destroy_queue(hw);
-
 err_cmd_init_queue:
 	hw->io_base = NULL;
 
@@ -1225,28 +1583,64 @@ hns3vf_do_stop(struct hns3_adapter *hns)
 }
 
 static void
-hns3vf_dev_stop(struct rte_eth_dev *eth_dev)
+hns3vf_unmap_rx_interrupt(struct rte_eth_dev *dev)
 {
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	uint8_t base = 0;
+	uint8_t vec = 0;
+	uint16_t q_id;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return;
+
+	/* unmap the ring with vector */
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			(void)hns3vf_bind_ring_with_vector(hw, vec, false,
+							   HNS3_RING_TYPE_RX,
+							   q_id);
+			if (vec < base + intr_handle->nb_efd - 1)
+				vec++;
+		}
+	}
+	/* Clean datapath event and queue/vec mapping */
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		rte_free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
+}
+
+static void
+hns3vf_dev_stop(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
 
 	PMD_INIT_FUNC_TRACE();
 
 	hw->adapter_state = HNS3_NIC_STOPPING;
-	hns3_set_rxtx_function(eth_dev);
+	hns3_set_rxtx_function(dev);
 	rte_wmb();
 	/* Disable datapath on secondary process. */
-	hns3_mp_req_stop_rxtx(eth_dev);
+	hns3_mp_req_stop_rxtx(dev);
 	/* Prevent crashes when queues are still in use. */
 	rte_delay_ms(hw->tqps_num);
 
 	rte_spinlock_lock(&hw->lock);
 	if (rte_atomic16_read(&hw->reset.resetting) == 0) {
 		hns3vf_do_stop(hns);
+		hns3vf_unmap_rx_interrupt(dev);
 		hns3_dev_release_mbufs(hns);
 		hw->adapter_state = HNS3_NIC_CONFIGURED;
 	}
-	rte_eal_alarm_cancel(hns3vf_service_handler, eth_dev);
+	rte_eal_alarm_cancel(hns3vf_service_handler, dev);
 	rte_spinlock_unlock(&hw->lock);
 }
 
@@ -1256,8 +1650,10 @@ hns3vf_dev_close(struct rte_eth_dev *eth_dev)
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->process_private);
 		return;
+    }
 
 	if (hw->adapter_state == HNS3_NIC_STARTED)
 		hns3vf_dev_stop(eth_dev);
@@ -1317,7 +1713,9 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 	struct hns3_hw *hw = &hns->hw;
 	int ret;
 
-	hns3vf_set_tc_info(hns);
+	ret = hns3vf_set_tc_info(hns);
+	if (ret)
+		return ret;
 
 	ret = hns3_start_queues(hns, reset_queue);
 	if (ret) {
@@ -1329,15 +1727,116 @@ hns3vf_do_start(struct hns3_adapter *hns, bool reset_queue)
 }
 
 static int
-hns3vf_dev_start(struct rte_eth_dev *eth_dev)
+hns3vf_map_rx_interrupt(struct rte_eth_dev *dev)
 {
-	struct hns3_adapter *hns = eth_dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint32_t intr_vector;
+	uint8_t base = 0;
+	uint8_t vec = 0;
+	uint16_t q_id;
+	int ret;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	/* disable uio/vfio intr/eventfd mapping */
+	rte_intr_disable(intr_handle);
+
+	/* check and configure queue intr-vector mapping */
+	if (rte_intr_cap_multiple(intr_handle) ||
+	    !RTE_ETH_DEV_SRIOV(dev).active) {
+		intr_vector = hw->used_rx_queues;
+		/* It creates event fd for each intr vector when MSIX is used */
+		if (rte_intr_efd_enable(intr_handle, intr_vector))
+			return -EINVAL;
+	}
+	if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) {
+		intr_handle->intr_vec =
+			rte_zmalloc("intr_vec",
+				    hw->used_rx_queues * sizeof(int), 0);
+		if (intr_handle->intr_vec == NULL) {
+			hns3_err(hw, "Failed to allocate %d rx_queues"
+				     " intr_vec", hw->used_rx_queues);
+			ret = -ENOMEM;
+			goto vf_alloc_intr_vec_error;
+		}
+	}
+
+	if (rte_intr_allow_others(intr_handle)) {
+		vec = RTE_INTR_VEC_RXTX_OFFSET;
+		base = RTE_INTR_VEC_RXTX_OFFSET;
+	}
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hns3vf_bind_ring_with_vector(hw, vec, true,
+							   HNS3_RING_TYPE_RX,
+							   q_id);
+			if (ret)
+				goto vf_bind_vector_error;
+			intr_handle->intr_vec[q_id] = vec;
+			if (vec < base + intr_handle->nb_efd - 1)
+				vec++;
+		}
+	}
+	rte_intr_enable(intr_handle);
+	return 0;
+
+vf_bind_vector_error:
+	rte_intr_efd_disable(intr_handle);
+	if (intr_handle->intr_vec) {
+		free(intr_handle->intr_vec);
+		intr_handle->intr_vec = NULL;
+	}
+	return ret;
+vf_alloc_intr_vec_error:
+	rte_intr_efd_disable(intr_handle);
+	return ret;
+}
+
+static int
+hns3vf_restore_rx_interrupt(struct hns3_hw *hw)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	uint16_t q_id;
 	int ret;
 
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return 0;
+
+	if (rte_intr_dp_is_en(intr_handle)) {
+		for (q_id = 0; q_id < hw->used_rx_queues; q_id++) {
+			ret = hns3vf_bind_ring_with_vector(hw,
+					intr_handle->intr_vec[q_id], true,
+					HNS3_RING_TYPE_RX, q_id);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void
+hns3vf_restore_filter(struct rte_eth_dev *dev)
+{
+	hns3_restore_rss_filter(dev);
+}
+
+static int
+hns3vf_dev_start(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	int ret = 0;
+
 	PMD_INIT_FUNC_TRACE();
 	if (rte_atomic16_read(&hw->reset.resetting))
 		return -EBUSY;
+
 	rte_spinlock_lock(&hw->lock);
 	hw->adapter_state = HNS3_NIC_STARTING;
 	ret = hns3vf_do_start(hns, true);
@@ -1346,13 +1845,30 @@ hns3vf_dev_start(struct rte_eth_dev *eth_dev)
 		rte_spinlock_unlock(&hw->lock);
 		return ret;
 	}
+	ret = hns3vf_map_rx_interrupt(dev);
+	if (ret) {
+		hw->adapter_state = HNS3_NIC_CONFIGURED;
+		rte_spinlock_unlock(&hw->lock);
+		return ret;
+	}
 	hw->adapter_state = HNS3_NIC_STARTED;
 	rte_spinlock_unlock(&hw->lock);
-	hns3_set_rxtx_function(eth_dev);
-	hns3_mp_req_start_rxtx(eth_dev);
-	rte_eal_alarm_set(HNS3VF_SERVICE_INTERVAL, hns3vf_service_handler,
-			  eth_dev);
-	return 0;
+
+	hns3_set_rxtx_function(dev);
+	hns3_mp_req_start_rxtx(dev);
+	hns3vf_service_handler(dev);
+
+	hns3vf_restore_filter(dev);
+
+	/* Enable interrupt of all rx queues before enabling queues */
+	hns3_dev_all_rx_queue_intr_enable(hw, true);
+	/*
+	 * When finished the initialization, enable queues to receive/transmit
+	 * packets.
+	 */
+	hns3_enable_all_queues(hw, true);
+
+	return ret;
 }
 
 static bool
@@ -1384,6 +1900,21 @@ hns3vf_is_reset_pending(struct hns3_adapter *hns)
 	struct hns3_hw *hw = &hns->hw;
 	enum hns3_reset_level reset;
 
+	/*
+	 * According to the protocol of PCIe, FLR to a PF device resets the PF
+	 * state as well as the SR-IOV extended capability including VF Enable
+	 * which means that VFs no longer exist.
+	 *
+	 * HNS3_VF_FULL_RESET means PF device is in FLR reset. when PF device
+	 * is in FLR stage, the register state of VF device is not reliable,
+	 * so register states detection can not be carried out. In this case,
+	 * we just ignore the register states and return false to indicate that
+	 * there are no other reset states that need to be processed by driver.
+	 */
+	if (hw->reset.level == HNS3_VF_FULL_RESET)
+		return false;
+
+	/* Check the registers to confirm whether there is reset pending */
 	hns3vf_check_event_cause(hns, NULL);
 	reset = hns3vf_get_reset_level(hw, &hw->reset.pending);
 	if (hw->reset.level != HNS3_NONE_RESET && hw->reset.level < reset) {
@@ -1446,15 +1977,17 @@ static int
 hns3vf_prepare_reset(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	int ret = 0;
+	int ret;
 
 	if (hw->reset.level == HNS3_VF_FUNC_RESET) {
 		ret = hns3_send_mbx_msg(hw, HNS3_MBX_RESET, 0, NULL,
 					0, true, NULL, 0);
+		if (ret)
+			return ret;
 	}
 	rte_atomic16_set(&hw->reset.disable_cmd, 1);
 
-	return ret;
+	return 0;
 }
 
 static int
@@ -1464,7 +1997,8 @@ hns3vf_stop_service(struct hns3_adapter *hns)
 	struct rte_eth_dev *eth_dev;
 
 	eth_dev = &rte_eth_devices[hw->data->port_id];
-	rte_eal_alarm_cancel(hns3vf_service_handler, eth_dev);
+	if (hw->adapter_state == HNS3_NIC_STARTED)
+		rte_eal_alarm_cancel(hns3vf_service_handler, eth_dev);
 	hw->mac.link_status = ETH_LINK_DOWN;
 
 	hns3_set_rxtx_function(eth_dev);
@@ -1502,8 +2036,18 @@ hns3vf_start_service(struct hns3_adapter *hns)
 	eth_dev = &rte_eth_devices[hw->data->port_id];
 	hns3_set_rxtx_function(eth_dev);
 	hns3_mp_req_start_rxtx(eth_dev);
+	if (hw->adapter_state == HNS3_NIC_STARTED) {
+		hns3vf_service_handler(eth_dev);
+
+		/* Enable interrupt of all rx queues before enabling queues */
+		hns3_dev_all_rx_queue_intr_enable(hw, true);
+		/*
+		 * When finished the initialization, enable queues to receive
+		 * and transmit packets.
+		 */
+		hns3_enable_all_queues(hw, true);
+	}
 
-	hns3vf_service_handler(eth_dev);
 	return 0;
 }
 
@@ -1525,6 +2069,10 @@ hns3vf_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_vlan_table;
 
+	ret = hns3vf_restore_rx_interrupt(hw);
+	if (ret)
+		goto err_vlan_table;
+
 	if (hw->adapter_state == HNS3_NIC_STARTED) {
 		ret = hns3vf_do_start(hns, false);
 		if (ret)
@@ -1623,14 +2171,18 @@ hns3vf_reinit_dev(struct hns3_adapter *hns)
 
 	if (hw->reset.level == HNS3_VF_FULL_RESET) {
 		rte_intr_disable(&pci_dev->intr_handle);
-		hns3vf_set_bus_master(pci_dev, true);
+		ret = hns3vf_set_bus_master(pci_dev, true);
+		if (ret < 0) {
+			hns3_err(hw, "failed to set pci bus, ret = %d", ret);
+			return ret;
+		}
 	}
 
 	/* Firmware command initialize */
 	ret = hns3_cmd_init(hw);
 	if (ret) {
 		hns3_err(hw, "Failed to init cmd: %d", ret);
-		goto err_cmd_init;
+		return ret;
 	}
 
 	if (hw->reset.level == HNS3_VF_FULL_RESET) {
@@ -1650,22 +2202,16 @@ hns3vf_reinit_dev(struct hns3_adapter *hns)
 	ret = hns3_reset_all_queues(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to reset all queues: %d", ret);
-		goto err_init;
+		return ret;
 	}
 
 	ret = hns3vf_init_hardware(hns);
 	if (ret) {
 		hns3_err(hw, "Failed to init hardware: %d", ret);
-		goto err_init;
+		return ret;
 	}
 
 	return 0;
-
-err_cmd_init:
-	hns3vf_set_bus_master(pci_dev, false);
-err_init:
-	hns3_cmd_uninit(hw);
-	return ret;
 }
 
 static const struct eth_dev_ops hns3vf_eth_dev_ops = {
@@ -1685,6 +2231,8 @@ static const struct eth_dev_ops hns3vf_eth_dev_ops = {
 	.tx_queue_setup     = hns3_tx_queue_setup,
 	.rx_queue_release   = hns3_dev_rx_queue_release,
 	.tx_queue_release   = hns3_dev_tx_queue_release,
+	.rx_queue_intr_enable   = hns3_dev_rx_queue_intr_enable,
+	.rx_queue_intr_disable  = hns3_dev_rx_queue_intr_disable,
 	.dev_configure      = hns3vf_dev_configure,
 	.mac_addr_add       = hns3vf_add_mac_addr,
 	.mac_addr_remove    = hns3vf_remove_mac_addr,
@@ -1736,12 +2284,24 @@ hns3vf_dev_init(struct rte_eth_dev *eth_dev)
 	hns3_set_rxtx_function(eth_dev);
 	eth_dev->dev_ops = &hns3vf_eth_dev_ops;
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
-		hns3_mp_init_secondary();
+		ret = hns3_mp_init_secondary();
+		if (ret) {
+			PMD_INIT_LOG(ERR, "Failed to init for secondary "
+					  "process, ret = %d", ret);
+			goto err_mp_init_secondary;
+		}
+
 		hw->secondary_cnt++;
 		return 0;
 	}
 
-	hns3_mp_init_primary();
+	ret = hns3_mp_init_primary();
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			     "Failed to init for primary process, ret = %d",
+			     ret);
+		goto err_mp_init_primary;
+	}
 
 	hw->adapter_state = HNS3_NIC_UNINITIALIZED;
 	hns->is_vf = true;
@@ -1771,8 +2331,10 @@ hns3vf_dev_init(struct rte_eth_dev *eth_dev)
 		goto err_rte_zmalloc;
 	}
 
+	rte_eth_random_addr(hw->mac.mac_addr); /* Generate a random mac addr */
 	rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.mac_addr,
 			    &eth_dev->data->mac_addrs[0]);
+
 	hw->adapter_state = HNS3_NIC_INITIALIZED;
 	/*
 	 * Pass the information to the rte_eth_dev_close() that it should also
@@ -1798,6 +2360,10 @@ hns3vf_dev_init(struct rte_eth_dev *eth_dev)
 	rte_free(hw->reset.wait_data);
 
 err_init_reset:
+	hns3_mp_uninit_primary();
+
+err_mp_init_primary:
+err_mp_init_secondary:
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
 	eth_dev->tx_pkt_burst = NULL;
@@ -1816,8 +2382,11 @@ hns3vf_dev_uninit(struct rte_eth_dev *eth_dev)
 
 	PMD_INIT_FUNC_TRACE();
 
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return -EPERM;
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+		rte_free(eth_dev->process_private);
+		eth_dev->process_private = NULL;
+		return 0;
+	}
 
 	eth_dev->dev_ops = NULL;
 	eth_dev->rx_pkt_burst = NULL;
diff --git a/dpdk/drivers/net/hns3/hns3_fdir.c b/dpdk/drivers/net/hns3/hns3_fdir.c
index ca3c78e1ce..98a044f567 100644
--- a/dpdk/drivers/net/hns3/hns3_fdir.c
+++ b/dpdk/drivers/net/hns3/hns3_fdir.c
@@ -619,7 +619,7 @@ static void hns3_fd_convert_meta_data(struct hns3_fd_key_cfg *cfg,
 				      uint8_t *key_x, uint8_t *key_y)
 {
 	uint16_t meta_data = 0;
-	uint16_t port_number;
+	uint32_t port_number;
 	uint8_t cur_pos = 0;
 	uint8_t tuple_size;
 	uint8_t shift_bits;
@@ -637,7 +637,7 @@ static void hns3_fd_convert_meta_data(struct hns3_fd_key_cfg *cfg,
 				     rule->key_conf.spec.tunnel_type ? 1 : 0);
 			cur_pos += tuple_size;
 		} else if (i == VLAN_NUMBER) {
-			uint8_t vlan_tag;
+			uint32_t vlan_tag;
 			uint8_t vlan_num;
 			if (rule->key_conf.spec.tunnel_type == 0)
 				vlan_num = rule->key_conf.vlan_num;
@@ -772,6 +772,20 @@ static int hns3_config_action(struct hns3_hw *hw, struct hns3_fdir_rule *rule)
 	return hns3_fd_ad_config(hw, ad_data.ad_id, &ad_data);
 }
 
+static int hns3_fd_clear_all_rules(struct hns3_hw *hw, uint32_t rule_num)
+{
+	uint32_t i;
+	int ret;
+
+	for (i = 0; i < rule_num; i++) {
+		ret = hns3_fd_tcam_config(hw, true, i, NULL, false);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int hns3_fdir_filter_init(struct hns3_adapter *hns)
 {
 	struct hns3_pf *pf = &hns->pf;
@@ -785,6 +799,13 @@ int hns3_fdir_filter_init(struct hns3_adapter *hns)
 		.hash_func = rte_hash_crc,
 		.hash_func_init_val = 0,
 	};
+	int ret;
+
+	ret = hns3_fd_clear_all_rules(&hns->hw, rule_num);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Clear all fd rules fail! ret = %d", ret);
+		return ret;
+	}
 
 	fdir_hash_params.socket_id = rte_socket_id();
 	TAILQ_INIT(&fdir_info->fdir_list);
@@ -872,7 +893,7 @@ static int hns3_insert_fdir_filter(struct hns3_hw *hw,
 	if (ret < 0) {
 		rte_spinlock_unlock(&fdir_info->flows_lock);
 		hns3_err(hw, "Hash table full? err:%d(%s)!", ret,
-			 strerror(ret));
+			 strerror(-ret));
 		return ret;
 	}
 
diff --git a/dpdk/drivers/net/hns3/hns3_flow.c b/dpdk/drivers/net/hns3/hns3_flow.c
index bcd121f48b..b1d3d81aee 100644
--- a/dpdk/drivers/net/hns3/hns3_flow.c
+++ b/dpdk/drivers/net/hns3/hns3_flow.c
@@ -46,8 +46,7 @@ static enum rte_flow_item_type first_items[] = {
 	RTE_FLOW_ITEM_TYPE_NVGRE,
 	RTE_FLOW_ITEM_TYPE_VXLAN,
 	RTE_FLOW_ITEM_TYPE_GENEVE,
-	RTE_FLOW_ITEM_TYPE_VXLAN_GPE,
-	RTE_FLOW_ITEM_TYPE_MPLS
+	RTE_FLOW_ITEM_TYPE_VXLAN_GPE
 };
 
 static enum rte_flow_item_type L2_next_items[] = {
@@ -67,8 +66,7 @@ static enum rte_flow_item_type L3_next_items[] = {
 static enum rte_flow_item_type L4_next_items[] = {
 	RTE_FLOW_ITEM_TYPE_VXLAN,
 	RTE_FLOW_ITEM_TYPE_GENEVE,
-	RTE_FLOW_ITEM_TYPE_VXLAN_GPE,
-	RTE_FLOW_ITEM_TYPE_MPLS
+	RTE_FLOW_ITEM_TYPE_VXLAN_GPE
 };
 
 static enum rte_flow_item_type tunnel_next_items[] = {
@@ -128,9 +126,9 @@ hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 	if (cnt) {
 		if (!cnt->shared || cnt->shared != shared)
 			return rte_flow_error_set(error, ENOTSUP,
-						  RTE_FLOW_ERROR_TYPE_ACTION,
-						  cnt,
-						  "Counter id is used,shared flag not match");
+				RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+				cnt,
+				"Counter id is used, shared flag not match");
 		cnt->ref_cnt++;
 		return 0;
 	}
@@ -138,7 +136,7 @@ hns3_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 	cnt = rte_zmalloc("hns3 counter", sizeof(*cnt), 0);
 	if (cnt == NULL)
 		return rte_flow_error_set(error, ENOMEM,
-					  RTE_FLOW_ERROR_TYPE_ACTION, cnt,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, cnt,
 					  "Alloc mem for counter failed");
 	cnt->id = id;
 	cnt->shared = shared;
@@ -166,13 +164,13 @@ hns3_counter_query(struct rte_eth_dev *dev, struct rte_flow *flow,
 	cnt = hns3_counter_lookup(dev, flow->counter_id);
 	if (cnt == NULL)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 					  "Can't find counter id");
 
 	ret = hns3_get_count(&hns->hw, flow->counter_id, &value);
 	if (ret) {
 		rte_flow_error_set(error, -ret,
-				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "Read counter fail.");
 		return ret;
 	}
@@ -224,14 +222,19 @@ hns3_handle_action_queue(struct rte_eth_dev *dev,
 			 struct rte_flow_error *error)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
-	struct hns3_hw *hw = &hns->hw;
 	const struct rte_flow_action_queue *queue;
+	struct hns3_hw *hw = &hns->hw;
 
 	queue = (const struct rte_flow_action_queue *)action->conf;
-	if (queue->index >= hw->data->nb_rx_queues)
+	if (queue->index >= hw->used_rx_queues) {
+		hns3_err(hw, "queue ID(%d) is greater than number of "
+			  "available queue (%d) in driver.",
+			  queue->index, hw->used_rx_queues);
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "Invalid queue ID in PF");
+	}
+
 	rule->queue_id = queue->index;
 	rule->action = HNS3_FD_ACTION_ACCEPT_PACKET;
 	return 0;
@@ -274,9 +277,9 @@ hns3_handle_actions(struct rte_eth_dev *dev,
 			    (const struct rte_flow_action_mark *)actions->conf;
 			if (mark->id >= HNS3_MAX_FILTER_ID)
 				return rte_flow_error_set(error, EINVAL,
-						     RTE_FLOW_ERROR_TYPE_ACTION,
-						     actions,
-						     "Invalid Mark ID");
+						RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+						actions,
+						"Invalid Mark ID");
 			rule->fd_id = mark->id;
 			rule->flags |= HNS3_RULE_FLAG_FDID;
 			break;
@@ -290,9 +293,9 @@ hns3_handle_actions(struct rte_eth_dev *dev,
 			counter_num = pf->fdir.fd_cfg.cnt_num[HNS3_FD_STAGE_1];
 			if (act_count->id >= counter_num)
 				return rte_flow_error_set(error, EINVAL,
-						     RTE_FLOW_ERROR_TYPE_ACTION,
-						     actions,
-						     "Invalid counter id");
+						RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+						actions,
+						"Invalid counter id");
 			rule->act_cnt = *act_count;
 			rule->flags |= HNS3_RULE_FLAG_COUNTER;
 			break;
@@ -456,7 +459,7 @@ hns3_parse_ipv4(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		    ipv4_mask->hdr.time_to_live ||
 		    ipv4_mask->hdr.hdr_checksum) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst ip,tos,proto in IPV4");
 		}
@@ -521,7 +524,7 @@ hns3_parse_ipv6(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		if (ipv6_mask->hdr.vtc_flow ||
 		    ipv6_mask->hdr.payload_len || ipv6_mask->hdr.hop_limits) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst ip,proto in IPV6");
 		}
@@ -581,7 +584,7 @@ hns3_parse_tcp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		    tcp_mask->hdr.rx_win ||
 		    tcp_mask->hdr.cksum || tcp_mask->hdr.tcp_urp) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in TCP");
 		}
@@ -628,7 +631,7 @@ hns3_parse_udp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		udp_mask = item->mask;
 		if (udp_mask->hdr.dgram_len || udp_mask->hdr.dgram_cksum) {
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in UDP");
 		}
@@ -675,7 +678,7 @@ hns3_parse_sctp(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		sctp_mask = item->mask;
 		if (sctp_mask->hdr.cksum)
 			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  RTE_FLOW_ERROR_TYPE_ITEM_MASK,
 						  item,
 						  "Only support src & dst port in SCTP");
 
@@ -820,14 +823,14 @@ hns3_parse_vxlan(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (vxlan_mask->flags)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Flags is not supported in VxLAN");
 
 	/* VNI must be totally masked or not. */
 	if (memcmp(vxlan_mask->vni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(vxlan_mask->vni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "VNI must be totally masked or not in VxLAN");
 	if (vxlan_mask->vni[0]) {
 		hns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);
@@ -871,14 +874,14 @@ hns3_parse_nvgre(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (nvgre_mask->protocol || nvgre_mask->c_k_s_rsvd0_ver)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Ver/protocal is not supported in NVGRE");
 
 	/* TNI must be totally masked or not. */
 	if (memcmp(nvgre_mask->tni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(nvgre_mask->tni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "TNI must be totally masked or not in NVGRE");
 
 	if (nvgre_mask->tni[0]) {
@@ -925,13 +928,13 @@ hns3_parse_geneve(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 
 	if (geneve_mask->ver_opt_len_o_c_rsvd0 || geneve_mask->protocol)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "Ver/protocal is not supported in GENEVE");
 	/* VNI must be totally masked or not. */
 	if (memcmp(geneve_mask->vni, full_mask, VNI_OR_TNI_LEN) &&
 	    memcmp(geneve_mask->vni, zero_mask, VNI_OR_TNI_LEN))
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_MASK, item,
 					  "VNI must be totally masked or not in GENEVE");
 	if (geneve_mask->vni[0]) {
 		hns3_set_bit(rule->input_set, OUTER_TUN_VNI, 1);
@@ -962,7 +965,7 @@ hns3_parse_tunnel(const struct rte_flow_item *item, struct hns3_fdir_rule *rule,
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_HANDLE,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
 					  NULL, "Unsupported tunnel type!");
 	}
 	if (ret)
@@ -1016,7 +1019,7 @@ hns3_parse_normal(const struct rte_flow_item *item,
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_HANDLE,
+					  RTE_FLOW_ERROR_TYPE_ITEM,
 					  NULL, "Unsupported normal type!");
 	}
 
@@ -1032,7 +1035,7 @@ hns3_validate_item(const struct rte_flow_item *item,
 
 	if (item->last)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, item,
+					  RTE_FLOW_ERROR_TYPE_ITEM_LAST, item,
 					  "Not supported last point for range");
 
 	for (i = 0; i < step_mngr.count; i++) {
@@ -1054,8 +1057,7 @@ is_tunnel_packet(enum rte_flow_item_type type)
 	if (type == RTE_FLOW_ITEM_TYPE_VXLAN_GPE ||
 	    type == RTE_FLOW_ITEM_TYPE_VXLAN ||
 	    type == RTE_FLOW_ITEM_TYPE_NVGRE ||
-	    type == RTE_FLOW_ITEM_TYPE_GENEVE ||
-	    type == RTE_FLOW_ITEM_TYPE_MPLS)
+	    type == RTE_FLOW_ITEM_TYPE_GENEVE)
 		return true;
 	return false;
 }
@@ -1116,11 +1118,6 @@ hns3_parse_fdir_filter(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 					  "Fdir not supported in VF");
 
-	if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
-					  "fdir_conf.mode isn't perfect");
-
 	step_mngr.items = first_items;
 	step_mngr.count = ARRAY_SIZE(first_items);
 	for (item = pattern; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
@@ -1193,10 +1190,24 @@ static bool
 hns3_action_rss_same(const struct rte_flow_action_rss *comp,
 		     const struct rte_flow_action_rss *with)
 {
-	return (comp->func == with->func &&
-		comp->level == with->level &&
-		comp->types == with->types &&
-		comp->key_len == with->key_len &&
+	bool func_is_same;
+
+	/*
+	 * When user flush all RSS rule, RSS func is set invalid with
+	 * RTE_ETH_HASH_FUNCTION_MAX. Then the user create a flow after
+	 * flushed, any validate RSS func is different with it before
+	 * flushed. Others, when user create an action RSS with RSS func
+	 * specified RTE_ETH_HASH_FUNCTION_DEFAULT, the func is the same
+	 * between continuous RSS flow.
+	 */
+	if (comp->func == RTE_ETH_HASH_FUNCTION_MAX)
+		func_is_same = false;
+	else
+		func_is_same = (with->func ? (comp->func == with->func) : true);
+
+	return (func_is_same &&
+		comp->types == (with->types & HNS3_ETH_RSS_SUPPORT) &&
+		comp->level == with->level && comp->key_len == with->key_len &&
 		comp->queue_num == with->queue_num &&
 		!memcmp(comp->key, with->key, with->key_len) &&
 		!memcmp(comp->queue, with->queue,
@@ -1242,65 +1253,49 @@ hns3_parse_rss_filter(struct rte_eth_dev *dev,
 	const struct rte_flow_action_rss *rss;
 	const struct rte_flow_action *act;
 	uint32_t act_index = 0;
-	uint64_t flow_types;
 	uint16_t n;
 
 	NEXT_ITEM_OF_ACTION(act, actions, act_index);
-	/* Get configuration args from APP cmdline input */
 	rss = act->conf;
 
-	if (rss == NULL || rss->queue_num == 0) {
+	if (rss == NULL) {
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act, "no valid queues");
 	}
 
+	if (rss->queue_num > RTE_DIM(rss_conf->queue))
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
+					  "queue number configured exceeds "
+					  "queue buffer size driver supported");
+
 	for (n = 0; n < rss->queue_num; n++) {
-		if (rss->queue[n] < dev->data->nb_rx_queues)
+		if (rss->queue[n] < hw->alloc_rss_size)
 			continue;
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
-					  act,
-					  "queue id > max number of queues");
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
+					  "queue id must be less than queue number allocated to a TC");
 	}
 
-	/* Parse flow types of RSS */
 	if (!(rss->types & HNS3_ETH_RSS_SUPPORT) && rss->types)
 		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  act,
 					  "Flow types is unsupported by "
 					  "hns3's RSS");
-
-	flow_types = rss->types & HNS3_ETH_RSS_SUPPORT;
-	if (flow_types != rss->types)
-		hns3_warn(hw, "RSS flow types(%" PRIx64 ") include unsupported "
-			  "flow types", rss->types);
-
-	/* Parse RSS related parameters from RSS configuration */
-	switch (rss->func) {
-	case RTE_ETH_HASH_FUNCTION_DEFAULT:
-	case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
-	case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
-		break;
-	default:
+	if (rss->func >= RTE_ETH_HASH_FUNCTION_MAX)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
-					  "input RSS hash functions are not supported");
-	}
-
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
+					  "RSS hash func are not supported");
 	if (rss->level)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "a nonzero RSS encapsulation level is not supported");
 	if (rss->key_len && rss->key_len != RTE_DIM(rss_conf->key))
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
+					  RTE_FLOW_ERROR_TYPE_ACTION_CONF, act,
 					  "RSS hash key must be exactly 40 bytes");
-	if (rss->queue_num > RTE_DIM(rss_conf->queue))
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, act,
-					  "too many queues for RSS context");
 
 	act_index++;
 
@@ -1328,6 +1323,7 @@ hns3_disable_rss(struct hns3_hw *hw)
 
 	/* Disable RSS */
 	hw->rss_info.conf.types = 0;
+	hw->rss_dis_flag = true;
 
 	return 0;
 }
@@ -1335,9 +1331,8 @@ hns3_disable_rss(struct hns3_hw *hw)
 static void
 hns3_parse_rss_key(struct hns3_hw *hw, struct rte_flow_action_rss *rss_conf)
 {
-	if (rss_conf->key == NULL ||
-	    rss_conf->key_len < HNS3_RSS_KEY_SIZE) {
-		hns3_info(hw, "Default RSS hash key to be set");
+	if (rss_conf->key == NULL || rss_conf->key_len < HNS3_RSS_KEY_SIZE) {
+		hns3_warn(hw, "Default RSS hash key to be set");
 		rss_conf->key = hns3_hash_key;
 		rss_conf->key_len = HNS3_RSS_KEY_SIZE;
 	}
@@ -1360,7 +1355,7 @@ hns3_parse_rss_algorithm(struct hns3_hw *hw, enum rte_eth_hash_function *func,
 		*hash_algo = HNS3_RSS_HASH_ALGO_SIMPLE;
 		break;
 	default:
-		hns3_err(hw, "Invalid RSS algorithm configuration(%u)",
+		hns3_err(hw, "Invalid RSS algorithm configuration(%d)",
 			 algo_func);
 		return -EINVAL;
 	}
@@ -1378,10 +1373,8 @@ hns3_hw_rss_hash_set(struct hns3_hw *hw, struct rte_flow_action_rss *rss_config)
 	struct hns3_rss_tuple_cfg *tuple;
 	int ret;
 
-	/* Parse hash key */
 	hns3_parse_rss_key(hw, rss_config);
 
-	/* Parse hash algorithm */
 	ret = hns3_parse_rss_algorithm(hw, &rss_config->func, &hash_algo);
 	if (ret)
 		return ret;
@@ -1409,26 +1402,19 @@ hns3_update_indir_table(struct rte_eth_dev *dev,
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
 	uint8_t indir_tbl[HNS3_RSS_IND_TBL_SIZE];
-	uint16_t j, allow_rss_queues;
+	uint16_t j;
 	uint8_t queue_id;
 	uint32_t i;
 
-	if (num == 0) {
-		hns3_err(hw, "No PF queues are configured to enable RSS");
-		return -ENOTSUP;
-	}
-
-	allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
 	/* Fill in redirection table */
 	memcpy(indir_tbl, hw->rss_info.rss_indirection_tbl,
 	       HNS3_RSS_IND_TBL_SIZE);
 	for (i = 0, j = 0; i < HNS3_RSS_IND_TBL_SIZE; i++, j++) {
 		j %= num;
-		if (conf->queue[j] >= allow_rss_queues) {
-			hns3_err(hw, "Invalid queue id(%u) to be set in "
-				     "redirection table, max number of rss "
-				     "queues: %u", conf->queue[j],
-				 allow_rss_queues);
+		if (conf->queue[j] >= hw->alloc_rss_size) {
+			hns3_err(hw, "queue id(%u) set to redirection table "
+				 "exceeds queue number(%u) allocated to a TC.",
+				 conf->queue[j], hw->alloc_rss_size);
 			return -EINVAL;
 		}
 		queue_id = conf->queue[j];
@@ -1442,7 +1428,9 @@ static int
 hns3_config_rss_filter(struct rte_eth_dev *dev,
 		       const struct hns3_rss_conf *conf, bool add)
 {
+	struct hns3_process_private *process_list = dev->process_private;
 	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_rss_conf_ele *rss_filter_ptr;
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rss_conf *rss_info;
 	uint64_t flow_types;
@@ -1469,8 +1457,18 @@ hns3_config_rss_filter(struct rte_eth_dev *dev,
 		return -EINVAL;
 	}
 
+	if (rss_flow_conf.key_len &&
+	    rss_flow_conf.key_len > RTE_DIM(rss_info->key)) {
+		hns3_err(hw,
+			"input hash key(%u) greater than supported len(%zu)",
+			rss_flow_conf.key_len, RTE_DIM(rss_info->key));
+		return -EINVAL;
+	}
+
 	/* Filter the unsupported flow types */
-	flow_types = rss_flow_conf.types & HNS3_ETH_RSS_SUPPORT;
+	flow_types = conf->conf.types ?
+		     rss_flow_conf.types & HNS3_ETH_RSS_SUPPORT :
+		     hw->rss_info.conf.types;
 	if (flow_types != rss_flow_conf.types)
 		hns3_warn(hw, "modified RSS types based on hardware support, "
 			      "requested:%" PRIx64 " configured:%" PRIx64,
@@ -1478,38 +1476,44 @@ hns3_config_rss_filter(struct rte_eth_dev *dev,
 	/* Update the useful flow types */
 	rss_flow_conf.types = flow_types;
 
-	if ((rss_flow_conf.types & ETH_RSS_PROTO_MASK) == 0)
-		return hns3_disable_rss(hw);
-
 	rss_info = &hw->rss_info;
 	if (!add) {
-		if (hns3_action_rss_same(&rss_info->conf, &rss_flow_conf)) {
-			ret = hns3_disable_rss(hw);
-			if (ret) {
-				hns3_err(hw, "RSS disable failed(%d)", ret);
-				return ret;
-			}
-			memset(rss_info, 0, sizeof(struct hns3_rss_conf));
+		if (!conf->valid)
 			return 0;
+
+		ret = hns3_disable_rss(hw);
+		if (ret) {
+			hns3_err(hw, "RSS disable failed(%d)", ret);
+			return ret;
+		}
+
+		if (rss_flow_conf.queue_num) {
+			/*
+			 * Due the content of queue pointer have been reset to
+			 * 0, the rss_info->conf.queue should be set NULL
+			 */
+			rss_info->conf.queue = NULL;
+			rss_info->conf.queue_num = 0;
 		}
-		return -EINVAL;
-	}
 
-	/* Get rx queues num */
-	num = dev->data->nb_rx_queues;
+		/* set RSS func invalid after flushed */
+		rss_info->conf.func = RTE_ETH_HASH_FUNCTION_MAX;
+		return 0;
+	}
 
 	/* Set rx queues to use */
-	num = RTE_MIN(num, rss_flow_conf.queue_num);
+	num = RTE_MIN(dev->data->nb_rx_queues, rss_flow_conf.queue_num);
 	if (rss_flow_conf.queue_num > num)
 		hns3_warn(hw, "Config queue numbers %u are beyond the scope of truncated",
 			  rss_flow_conf.queue_num);
 	hns3_info(hw, "Max of contiguous %u PF queues are configured", num);
 
 	rte_spinlock_lock(&hw->lock);
-	/* Update redirection talbe of rss */
-	ret = hns3_update_indir_table(dev, &rss_flow_conf, num);
-	if (ret)
-		goto rss_config_err;
+	if (num) {
+		ret = hns3_update_indir_table(dev, &rss_flow_conf, num);
+		if (ret)
+			goto rss_config_err;
+	}
 
 	/* Set hash algorithm and flow types by the user's config */
 	ret = hns3_hw_rss_hash_set(hw, &rss_flow_conf);
@@ -1522,23 +1526,65 @@ hns3_config_rss_filter(struct rte_eth_dev *dev,
 		goto rss_config_err;
 	}
 
+	/*
+	 * When create a new RSS rule, the old rule will be overlaid and set
+	 * invalid.
+	 */
+	TAILQ_FOREACH(rss_filter_ptr, &process_list->filter_rss_list, entries)
+		rss_filter_ptr->filter_info.valid = false;
+
 rss_config_err:
 	rte_spinlock_unlock(&hw->lock);
 
 	return ret;
 }
 
-/* Remove the rss filter */
 static int
 hns3_clear_rss_filter(struct rte_eth_dev *dev)
+{
+	struct hns3_process_private *process_list = dev->process_private;
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_rss_conf_ele *rss_filter_ptr;
+	struct hns3_hw *hw = &hns->hw;
+	int rss_rule_succ_cnt = 0; /* count for success of clearing RSS rules */
+	int rss_rule_fail_cnt = 0; /* count for failure of clearing RSS rules */
+	int ret = 0;
+
+	rss_filter_ptr = TAILQ_FIRST(&process_list->filter_rss_list);
+	while (rss_filter_ptr) {
+		TAILQ_REMOVE(&process_list->filter_rss_list, rss_filter_ptr,
+			     entries);
+		ret = hns3_config_rss_filter(dev, &rss_filter_ptr->filter_info,
+					     false);
+		if (ret)
+			rss_rule_fail_cnt++;
+		else
+			rss_rule_succ_cnt++;
+		rte_free(rss_filter_ptr);
+		rss_filter_ptr = TAILQ_FIRST(&process_list->filter_rss_list);
+	}
+
+	if (rss_rule_fail_cnt) {
+		hns3_err(hw, "fail to delete all RSS filters, success num = %d "
+			     "fail num = %d", rss_rule_succ_cnt,
+			     rss_rule_fail_cnt);
+		ret = -EIO;
+	}
+
+	return ret;
+}
+
+int
+hns3_restore_rss_filter(struct rte_eth_dev *dev)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
 
-	if (hw->rss_info.conf.queue_num == 0)
+	/* When user flush all rules, it doesn't need to restore RSS rule */
+	if (hw->rss_info.conf.func == RTE_ETH_HASH_FUNCTION_MAX)
 		return 0;
 
-	return hns3_config_rss_filter(dev, &hw->rss_info, false);
+	return hns3_config_rss_filter(dev, &hw->rss_info, true);
 }
 
 static int
@@ -1549,7 +1595,6 @@ hns3_flow_parse_rss(struct rte_eth_dev *dev,
 	struct hns3_hw *hw = &hns->hw;
 	bool ret;
 
-	/* Action rss same */
 	ret = hns3_action_rss_same(&hw->rss_info.conf, &conf->conf);
 	if (ret) {
 		hns3_err(hw, "Enter duplicate RSS configuration : %d", ret);
@@ -1673,8 +1718,9 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			ret = -ENOMEM;
 			goto err;
 		}
-		memcpy(&rss_filter_ptr->filter_info, rss_conf,
-			sizeof(struct hns3_rss_conf));
+		hns3_rss_conf_copy(&rss_filter_ptr->filter_info,
+				   &rss_conf->conf);
+		rss_filter_ptr->filter_info.valid = true;
 		TAILQ_INSERT_TAIL(&process_list->filter_rss_list,
 				  rss_filter_ptr, entries);
 
@@ -1696,16 +1742,18 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 
 		flow->counter_id = fdir_rule.act_cnt.id;
 	}
+
+	fdir_rule_ptr = rte_zmalloc("hns3 fdir rule",
+				    sizeof(struct hns3_fdir_rule_ele),
+				    0);
+	if (fdir_rule_ptr == NULL) {
+		hns3_err(hw, "failed to allocate fdir_rule memory.");
+		ret = -ENOMEM;
+		goto err_fdir;
+	}
+
 	ret = hns3_fdir_filter_program(hns, &fdir_rule, false);
 	if (!ret) {
-		fdir_rule_ptr = rte_zmalloc("hns3 fdir rule",
-					    sizeof(struct hns3_fdir_rule_ele),
-					    0);
-		if (fdir_rule_ptr == NULL) {
-			hns3_err(hw, "Failed to allocate fdir_rule memory");
-			ret = -ENOMEM;
-			goto err_fdir;
-		}
 		memcpy(&fdir_rule_ptr->fdir_conf, &fdir_rule,
 			sizeof(struct hns3_fdir_rule));
 		TAILQ_INSERT_TAIL(&process_list->fdir_list,
@@ -1716,10 +1764,10 @@ hns3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		return flow;
 	}
 
+	rte_free(fdir_rule_ptr);
 err_fdir:
 	if (fdir_rule.flags & HNS3_RULE_FLAG_COUNTER)
 		hns3_counter_release(dev, fdir_rule.act_cnt.id);
-
 err:
 	rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
 			   "Failed to create flow");
@@ -1740,7 +1788,6 @@ hns3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
 	struct hns3_fdir_rule_ele *fdir_rule_ptr;
 	struct hns3_rss_conf_ele *rss_filter_ptr;
 	struct hns3_flow_mem *flow_node;
-	struct hns3_hw *hw = &hns->hw;
 	enum rte_filter_type filter_type;
 	struct hns3_fdir_rule fdir_rule;
 	int ret;
@@ -1770,7 +1817,8 @@ hns3_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
 		break;
 	case RTE_ETH_FILTER_HASH:
 		rss_filter_ptr = (struct hns3_rss_conf_ele *)flow->rule;
-		ret = hns3_config_rss_filter(dev, &hw->rss_info, false);
+		ret = hns3_config_rss_filter(dev, &rss_filter_ptr->filter_info,
+					     false);
 		if (ret)
 			return rte_flow_error_set(error, EIO,
 						  RTE_FLOW_ERROR_TYPE_HANDLE,
@@ -1822,8 +1870,11 @@ hns3_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
 	}
 
 	ret = hns3_clear_rss_filter(dev);
-	if (ret)
+	if (ret) {
+		rte_flow_error_set(error, ret, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "Failed to flush rss filter");
 		return ret;
+	}
 
 	hns3_filterlist_flush(dev);
 
diff --git a/dpdk/drivers/net/hns3/hns3_intr.c b/dpdk/drivers/net/hns3/hns3_intr.c
index 6c3ebd3ee1..46d617c68e 100644
--- a/dpdk/drivers/net/hns3/hns3_intr.c
+++ b/dpdk/drivers/net/hns3/hns3_intr.c
@@ -882,8 +882,14 @@ hns3_reset_err_handle(struct hns3_adapter *hns)
 		return true;
 	}
 
+	/*
+	 * Failure to reset does not mean that the network port is
+	 * completely unavailable, so cmd still needs to be initialized.
+	 * Regardless of whether the execution is successful or not, the
+	 * flow after execution must be continued.
+	 */
 	if (rte_atomic16_read(&hw->reset.disable_cmd))
-		hns3_cmd_init(hw);
+		(void)hns3_cmd_init(hw);
 reset_fail:
 	hw->reset.attempts = 0;
 	hw->reset.stats.fail_cnt++;
@@ -1001,7 +1007,9 @@ hns3_reset_post(struct hns3_adapter *hns)
 		hw->reset.attempts = 0;
 		hw->reset.stats.success_cnt++;
 		hw->reset.stage = RESET_STAGE_NONE;
+		rte_spinlock_lock(&hw->lock);
 		hw->reset.ops->start_service(hns);
+		rte_spinlock_unlock(&hw->lock);
 		gettimeofday(&tv, NULL);
 		timersub(&tv, &hw->reset.start_time, &tv_delta);
 		hns3_warn(hw, "%s reset done fail_cnt:%" PRIx64
diff --git a/dpdk/drivers/net/hns3/hns3_mbx.c b/dpdk/drivers/net/hns3/hns3_mbx.c
index c1647af4bf..64996c9ae1 100644
--- a/dpdk/drivers/net/hns3/hns3_mbx.c
+++ b/dpdk/drivers/net/hns3/hns3_mbx.c
@@ -150,6 +150,8 @@ hns3_send_mbx_msg(struct hns3_hw *hw, uint16_t code, uint16_t subcode,
 {
 	struct hns3_mbx_vf_to_pf_cmd *req;
 	struct hns3_cmd_desc desc;
+	bool is_ring_vector_msg;
+	int offset;
 	int ret;
 
 	req = (struct hns3_mbx_vf_to_pf_cmd *)desc.data;
@@ -164,9 +166,15 @@ hns3_send_mbx_msg(struct hns3_hw *hw, uint16_t code, uint16_t subcode,
 
 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_MBX_VF_TO_PF, false);
 	req->msg[0] = code;
-	req->msg[1] = subcode;
-	if (msg_data)
-		memcpy(&req->msg[HNS3_CMD_CODE_OFFSET], msg_data, msg_len);
+	is_ring_vector_msg = (code == HNS3_MBX_MAP_RING_TO_VECTOR) ||
+			     (code == HNS3_MBX_UNMAP_RING_TO_VECTOR) ||
+			     (code == HNS3_MBX_GET_RING_VECTOR_MAP);
+	if (!is_ring_vector_msg)
+		req->msg[1] = subcode;
+	if (msg_data) {
+		offset = is_ring_vector_msg ? 1 : HNS3_CMD_CODE_OFFSET;
+		memcpy(&req->msg[offset], msg_data, msg_len);
+	}
 
 	/* synchronous send */
 	if (need_resp) {
@@ -211,6 +219,7 @@ hns3_mbx_handler(struct hns3_hw *hw)
 	struct hns3_mac *mac = &hw->mac;
 	enum hns3_reset_level reset_level;
 	uint16_t *msg_q;
+	uint8_t opcode;
 	uint32_t tail;
 
 	tail = hw->arq.tail;
@@ -219,7 +228,8 @@ hns3_mbx_handler(struct hns3_hw *hw)
 	while (tail != hw->arq.head) {
 		msg_q = hw->arq.msg_q[hw->arq.head];
 
-		switch (msg_q[0]) {
+		opcode = msg_q[0] & 0xff;
+		switch (opcode) {
 		case HNS3_MBX_LINK_STAT_CHANGE:
 			memcpy(&mac->link_speed, &msg_q[2],
 				   sizeof(mac->link_speed));
@@ -241,7 +251,7 @@ hns3_mbx_handler(struct hns3_hw *hw)
 			break;
 		default:
 			hns3_err(hw, "Fetched unsupported(%d) message from arq",
-				 msg_q[0]);
+				 opcode);
 			break;
 		}
 
@@ -282,6 +292,40 @@ hns3_update_resp_position(struct hns3_hw *hw, uint32_t resp_msg)
 	resp->tail = tail;
 }
 
+static void
+hns3_link_fail_parse(struct hns3_hw *hw, uint8_t link_fail_code)
+{
+	switch (link_fail_code) {
+	case HNS3_MBX_LF_NORMAL:
+		break;
+	case HNS3_MBX_LF_REF_CLOCK_LOST:
+		hns3_warn(hw, "Reference clock lost!");
+		break;
+	case HNS3_MBX_LF_XSFP_TX_DISABLE:
+		hns3_warn(hw, "SFP tx is disabled!");
+		break;
+	case HNS3_MBX_LF_XSFP_ABSENT:
+		hns3_warn(hw, "SFP is absent!");
+		break;
+	default:
+		hns3_warn(hw, "Unknown fail code:%u!", link_fail_code);
+		break;
+	}
+}
+
+static void
+hns3_handle_link_change_event(struct hns3_hw *hw,
+			      struct hns3_mbx_pf_to_vf_cmd *req)
+{
+#define LINK_STATUS_OFFSET     1
+#define LINK_FAIL_CODE_OFFSET  2
+
+	if (!req->msg[LINK_STATUS_OFFSET])
+		hns3_link_fail_parse(hw, req->msg[LINK_FAIL_CODE_OFFSET]);
+
+	hns3_update_link_status(hw);
+}
+
 void
 hns3_dev_handle_mbx_msg(struct hns3_hw *hw)
 {
@@ -291,6 +335,7 @@ hns3_dev_handle_mbx_msg(struct hns3_hw *hw)
 	struct hns3_cmd_desc *desc;
 	uint32_t msg_data;
 	uint16_t *msg_q;
+	uint8_t opcode;
 	uint16_t flag;
 	uint8_t *temp;
 	int i;
@@ -301,12 +346,13 @@ hns3_dev_handle_mbx_msg(struct hns3_hw *hw)
 
 		desc = &crq->desc[crq->next_to_use];
 		req = (struct hns3_mbx_pf_to_vf_cmd *)desc->data;
+		opcode = req->msg[0] & 0xff;
 
 		flag = rte_le_to_cpu_16(crq->desc[crq->next_to_use].flag);
 		if (unlikely(!hns3_get_bit(flag, HNS3_CMDQ_RX_OUTVLD_B))) {
 			hns3_warn(hw,
 				  "dropped invalid mailbox message, code = %d",
-				  req->msg[0]);
+				  opcode);
 
 			/* dropping/not processing this invalid message */
 			crq->desc[crq->next_to_use].flag = 0;
@@ -314,7 +360,7 @@ hns3_dev_handle_mbx_msg(struct hns3_hw *hw)
 			continue;
 		}
 
-		switch (req->msg[0]) {
+		switch (opcode) {
 		case HNS3_MBX_PF_VF_RESP:
 			resp->resp_status = hns3_resp_to_errno(req->msg[3]);
 
@@ -335,6 +381,9 @@ hns3_dev_handle_mbx_msg(struct hns3_hw *hw)
 
 			hns3_mbx_handler(hw);
 			break;
+		case HNS3_MBX_PUSH_LINK_STATUS:
+			hns3_handle_link_change_event(hw, req);
+			break;
 		default:
 			hns3_err(hw,
 				 "VF received unsupported(%d) mbx msg from PF",
diff --git a/dpdk/drivers/net/hns3/hns3_mbx.h b/dpdk/drivers/net/hns3/hns3_mbx.h
index 01eddb845d..b01eaacc3c 100644
--- a/dpdk/drivers/net/hns3/hns3_mbx.h
+++ b/dpdk/drivers/net/hns3/hns3_mbx.h
@@ -41,6 +41,8 @@ enum HNS3_MBX_OPCODE {
 	HNS3_MBX_GET_QID_IN_PF,         /* (VF -> PF) get queue id in pf */
 
 	HNS3_MBX_HANDLE_VF_TBL = 38,    /* (VF -> PF) store/clear hw cfg tbl */
+	HNS3_MBX_GET_RING_VECTOR_MAP,   /* (VF -> PF) get ring-to-vector map */
+	HNS3_MBX_PUSH_LINK_STATUS = 201, /* (IMP -> PF) get port link status */
 };
 
 /* below are per-VF mac-vlan subcodes */
@@ -64,6 +66,13 @@ enum hns3_mbx_tbl_cfg_subcode {
 	HNS3_MBX_VPORT_LIST_CLEAR = 0,
 };
 
+enum hns3_mbx_link_fail_subcode {
+	HNS3_MBX_LF_NORMAL = 0,
+	HNS3_MBX_LF_REF_CLOCK_LOST,
+	HNS3_MBX_LF_XSFP_TX_DISABLE,
+	HNS3_MBX_LF_XSFP_ABSENT,
+};
+
 #define HNS3_MBX_MAX_MSG_SIZE	16
 #define HNS3_MBX_MAX_RESP_DATA_SIZE	8
 #define HNS3_MBX_RING_MAP_BASIC_MSG_NUM	3
@@ -104,6 +113,19 @@ struct hns3_mbx_pf_to_vf_cmd {
 	uint16_t msg[8];
 };
 
+struct hns3_ring_chain_param {
+	uint8_t ring_type;
+	uint8_t tqp_index;
+	uint8_t int_gl_index;
+};
+
+#define HNS3_MBX_MAX_RING_CHAIN_PARAM_NUM	4
+struct hns3_vf_bind_vector_msg {
+	uint8_t vector_id;
+	uint8_t ring_num;
+	struct hns3_ring_chain_param param[HNS3_MBX_MAX_RING_CHAIN_PARAM_NUM];
+};
+
 struct hns3_vf_rst_cmd {
 	uint8_t dest_vfid;
 	uint8_t vf_rst;
diff --git a/dpdk/drivers/net/hns3/hns3_mp.c b/dpdk/drivers/net/hns3/hns3_mp.c
index 596c31064a..639f46ced8 100644
--- a/dpdk/drivers/net/hns3/hns3_mp.c
+++ b/dpdk/drivers/net/hns3/hns3_mp.c
@@ -14,6 +14,8 @@
 #include "hns3_rxtx.h"
 #include "hns3_mp.h"
 
+static bool hns3_inited;
+
 /*
  * Initialize IPC message.
  *
@@ -192,9 +194,20 @@ void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev)
 /*
  * Initialize by primary process.
  */
-void hns3_mp_init_primary(void)
+int hns3_mp_init_primary(void)
 {
-	rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
+	int ret;
+
+	if (!hns3_inited) {
+		/* primary is allowed to not support IPC */
+		ret = rte_mp_action_register(HNS3_MP_NAME, mp_primary_handle);
+		if (ret && rte_errno != ENOTSUP)
+			return ret;
+
+		hns3_inited = true;
+	}
+
+	return 0;
 }
 
 /*
@@ -202,13 +215,24 @@ void hns3_mp_init_primary(void)
  */
 void hns3_mp_uninit_primary(void)
 {
-	rte_mp_action_unregister(HNS3_MP_NAME);
+	if (hns3_inited)
+		rte_mp_action_unregister(HNS3_MP_NAME);
 }
 
 /*
  * Initialize by secondary process.
  */
-void hns3_mp_init_secondary(void)
+int hns3_mp_init_secondary(void)
 {
-	rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
+	int ret;
+
+	if (!hns3_inited) {
+		ret = rte_mp_action_register(HNS3_MP_NAME, mp_secondary_handle);
+		if (ret)
+			return ret;
+
+		hns3_inited = true;
+	}
+
+	return 0;
 }
diff --git a/dpdk/drivers/net/hns3/hns3_mp.h b/dpdk/drivers/net/hns3/hns3_mp.h
index aefbeb140e..036546ae11 100644
--- a/dpdk/drivers/net/hns3/hns3_mp.h
+++ b/dpdk/drivers/net/hns3/hns3_mp.h
@@ -7,8 +7,8 @@
 
 void hns3_mp_req_start_rxtx(struct rte_eth_dev *dev);
 void hns3_mp_req_stop_rxtx(struct rte_eth_dev *dev);
-void hns3_mp_init_primary(void);
+int hns3_mp_init_primary(void);
 void hns3_mp_uninit_primary(void);
-void hns3_mp_init_secondary(void);
+int hns3_mp_init_secondary(void);
 
 #endif /* _HNS3_MP_H_ */
diff --git a/dpdk/drivers/net/hns3/hns3_regs.c b/dpdk/drivers/net/hns3/hns3_regs.c
index 23405030e7..2f34357d48 100644
--- a/dpdk/drivers/net/hns3/hns3_regs.c
+++ b/dpdk/drivers/net/hns3/hns3_regs.c
@@ -116,17 +116,12 @@ static int
 hns3_get_regs_length(struct hns3_hw *hw, uint32_t *length)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
-	int cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
+	uint32_t cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
 	uint32_t regs_num_32_bit, regs_num_64_bit;
+	uint32_t dfx_reg_lines;
+	uint32_t len;
 	int ret;
 
-	ret = hns3_get_regs_num(hw, &regs_num_32_bit, &regs_num_64_bit);
-	if (ret) {
-		hns3_err(hw, "Get register number failed, ret = %d.",
-			 ret);
-		return -ENOTSUP;
-	}
-
 	cmdq_lines = sizeof(cmdq_reg_addrs) / REG_LEN_PER_LINE + 1;
 	if (hns->is_vf)
 		common_lines =
@@ -136,11 +131,24 @@ hns3_get_regs_length(struct hns3_hw *hw, uint32_t *length)
 	ring_lines = sizeof(ring_reg_addrs) / REG_LEN_PER_LINE + 1;
 	tqp_intr_lines = sizeof(tqp_intr_reg_addrs) / REG_LEN_PER_LINE + 1;
 
-	*length = (cmdq_lines + common_lines + ring_lines * hw->tqps_num +
-		   tqp_intr_lines * hw->num_msi) * REG_LEN_PER_LINE +
-		  regs_num_32_bit * sizeof(uint32_t) +
-		  regs_num_64_bit * sizeof(uint64_t);
+	len = (cmdq_lines + common_lines + ring_lines * hw->tqps_num +
+	      tqp_intr_lines * hw->num_msi) * REG_NUM_PER_LINE;
+
+	if (!hns->is_vf) {
+		ret = hns3_get_regs_num(hw, &regs_num_32_bit, &regs_num_64_bit);
+		if (ret) {
+			hns3_err(hw, "Get register number failed, ret = %d.",
+				 ret);
+			return -ENOTSUP;
+		}
+		dfx_reg_lines = regs_num_32_bit * sizeof(uint32_t) /
+					REG_LEN_PER_LINE + 1;
+		dfx_reg_lines += regs_num_64_bit * sizeof(uint64_t) /
+					REG_LEN_PER_LINE + 1;
+		len += dfx_reg_lines * REG_NUM_PER_LINE;
+	}
 
+	*length = len;
 	return 0;
 }
 
@@ -258,63 +266,68 @@ hns3_get_64_bit_regs(struct hns3_hw *hw, uint32_t regs_num, void *data)
 	return 0;
 }
 
-static void
+static int
+hns3_insert_reg_separator(int reg_num, uint32_t *data)
+{
+	int separator_num;
+	int i;
+
+	separator_num = MAX_SEPARATE_NUM - reg_num % REG_NUM_PER_LINE;
+	for (i = 0; i < separator_num; i++)
+		*data++ = SEPARATOR_VALUE;
+	return separator_num;
+}
+
+static int
 hns3_direct_access_regs(struct hns3_hw *hw, uint32_t *data)
 {
 	struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
+	uint32_t *origin_data_ptr = data;
 	uint32_t reg_offset;
-	int separator_num;
-	int reg_um;
+	int reg_num;
 	int i, j;
 
 	/* fetching per-PF registers values from PF PCIe register space */
-	reg_um = sizeof(cmdq_reg_addrs) / sizeof(uint32_t);
-	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
-	for (i = 0; i < reg_um; i++)
+	reg_num = sizeof(cmdq_reg_addrs) / sizeof(uint32_t);
+	for (i = 0; i < reg_num; i++)
 		*data++ = hns3_read_dev(hw, cmdq_reg_addrs[i]);
-	for (i = 0; i < separator_num; i++)
-		*data++ = SEPARATOR_VALUE;
+	data += hns3_insert_reg_separator(reg_num, data);
 
 	if (hns->is_vf)
-		reg_um = sizeof(common_vf_reg_addrs) / sizeof(uint32_t);
+		reg_num = sizeof(common_vf_reg_addrs) / sizeof(uint32_t);
 	else
-		reg_um = sizeof(common_reg_addrs) / sizeof(uint32_t);
-	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
-	for (i = 0; i < reg_um; i++)
+		reg_num = sizeof(common_reg_addrs) / sizeof(uint32_t);
+	for (i = 0; i < reg_num; i++)
 		if (hns->is_vf)
 			*data++ = hns3_read_dev(hw, common_vf_reg_addrs[i]);
 		else
 			*data++ = hns3_read_dev(hw, common_reg_addrs[i]);
-	for (i = 0; i < separator_num; i++)
-		*data++ = SEPARATOR_VALUE;
+	data += hns3_insert_reg_separator(reg_num, data);
 
-	reg_um = sizeof(ring_reg_addrs) / sizeof(uint32_t);
-	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
+	reg_num = sizeof(ring_reg_addrs) / sizeof(uint32_t);
 	for (j = 0; j < hw->tqps_num; j++) {
 		reg_offset = HNS3_TQP_REG_OFFSET + HNS3_TQP_REG_SIZE * j;
-		for (i = 0; i < reg_um; i++)
+		for (i = 0; i < reg_num; i++)
 			*data++ = hns3_read_dev(hw,
 						ring_reg_addrs[i] + reg_offset);
-		for (i = 0; i < separator_num; i++)
-			*data++ = SEPARATOR_VALUE;
+		data += hns3_insert_reg_separator(reg_num, data);
 	}
 
-	reg_um = sizeof(tqp_intr_reg_addrs) / sizeof(uint32_t);
-	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
-	for (j = 0; j < hw->num_msi; j++) {
+	reg_num = sizeof(tqp_intr_reg_addrs) / sizeof(uint32_t);
+	for (j = 0; j < hw->intr_tqps_num; j++) {
 		reg_offset = HNS3_TQP_INTR_REG_SIZE * j;
-		for (i = 0; i < reg_um; i++)
-			*data++ = hns3_read_dev(hw,
-						tqp_intr_reg_addrs[i] +
+		for (i = 0; i < reg_num; i++)
+			*data++ = hns3_read_dev(hw, tqp_intr_reg_addrs[i] +
 						reg_offset);
-		for (i = 0; i < separator_num; i++)
-			*data++ = SEPARATOR_VALUE;
+		data += hns3_insert_reg_separator(reg_num, data);
 	}
+	return data - origin_data_ptr;
 }
 
 int
 hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
 {
+#define HNS3_64_BIT_REG_SIZE (sizeof(uint64_t) / sizeof(uint32_t))
 	struct hns3_adapter *hns = eth_dev->data->dev_private;
 	struct hns3_hw *hw = &hns->hw;
 	uint32_t regs_num_32_bit;
@@ -344,7 +357,10 @@ hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
 		return -ENOTSUP;
 
 	/* fetching per-PF registers values from PF PCIe register space */
-	hns3_direct_access_regs(hw, data);
+	data += hns3_direct_access_regs(hw, data);
+
+	if (hns->is_vf)
+		return 0;
 
 	ret = hns3_get_regs_num(hw, &regs_num_32_bit, &regs_num_64_bit);
 	if (ret) {
@@ -358,11 +374,16 @@ hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs)
 		hns3_err(hw, "Get 32 bit register failed, ret = %d", ret);
 		return ret;
 	}
-
 	data += regs_num_32_bit;
+	data += hns3_insert_reg_separator(regs_num_32_bit, data);
+
 	ret = hns3_get_64_bit_regs(hw, regs_num_64_bit, data);
-	if (ret)
+	if (ret) {
 		hns3_err(hw, "Get 64 bit register failed, ret = %d", ret);
-
+		return ret;
+	}
+	data += regs_num_64_bit * HNS3_64_BIT_REG_SIZE;
+	data += hns3_insert_reg_separator(regs_num_64_bit *
+					  HNS3_64_BIT_REG_SIZE, data);
 	return ret;
 }
diff --git a/dpdk/drivers/net/hns3/hns3_regs.h b/dpdk/drivers/net/hns3/hns3_regs.h
index 2f5faafe18..64bd6931b3 100644
--- a/dpdk/drivers/net/hns3/hns3_regs.h
+++ b/dpdk/drivers/net/hns3/hns3_regs.h
@@ -94,6 +94,16 @@
 #define HNS3_TQP_INTR_RL_REG			0x20900
 
 #define HNS3_TQP_INTR_REG_SIZE			4
+#define HNS3_TQP_INTR_GL_MAX			0x1FE0
+#define HNS3_TQP_INTR_GL_DEFAULT		20
+#define HNS3_TQP_INTR_RL_MAX			0xEC
+#define HNS3_TQP_INTR_RL_ENABLE_MASK		0x40
+#define HNS3_TQP_INTR_RL_DEFAULT		0
+
+/* gl_usec convert to hardware count, as writing each 1 represents 2us */
+#define HNS3_GL_USEC_TO_REG(gl_usec)		((gl_usec) >> 1)
+/* rl_usec convert to hardware count, as writing each 1 represents 4us */
+#define HNS3_RL_USEC_TO_REG(rl_usec)		((rl_usec) >> 2)
 
 int hns3_get_regs(struct rte_eth_dev *eth_dev, struct rte_dev_reg_info *regs);
 #endif /* _HNS3_REGS_H_ */
diff --git a/dpdk/drivers/net/hns3/hns3_rss.c b/dpdk/drivers/net/hns3/hns3_rss.c
index b8c20e6d9d..a63d6ef725 100644
--- a/dpdk/drivers/net/hns3/hns3_rss.c
+++ b/dpdk/drivers/net/hns3/hns3_rss.c
@@ -127,7 +127,7 @@ hns3_set_rss_indir_table(struct hns3_hw *hw, uint8_t *indir, uint16_t size)
 		req->rss_set_bitmap = rte_cpu_to_le_16(HNS3_RSS_SET_BITMAP_MSK);
 		for (j = 0; j < HNS3_RSS_CFG_TBL_SIZE; j++) {
 			num = i * HNS3_RSS_CFG_TBL_SIZE + j;
-			req->rss_result[j] = indir[num] % hw->alloc_rss_size;
+			req->rss_result[j] = indir[num];
 		}
 		ret = hns3_cmd_send(hw, &desc, 1);
 		if (ret) {
@@ -211,7 +211,11 @@ hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw,
 			req->ipv6_fragment_en |= HNS3_IP_OTHER_BIT_MASK;
 			break;
 		default:
-			/* Other unsupported flow types won't change tuples */
+			/*
+			 * rss_hf doesn't include unsupported flow types
+			 * because the API framework has checked it, and
+			 * this branch will never go unless rss_hf is zero.
+			 */
 			break;
 		}
 	}
@@ -251,12 +255,15 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev,
 	struct hns3_hw *hw = &hns->hw;
 	struct hns3_rss_tuple_cfg *tuple = &hw->rss_info.rss_tuple_sets;
 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
-	uint8_t algo = rss_cfg->conf.func;
 	uint8_t key_len = rss_conf->rss_key_len;
+	uint8_t algo;
 	uint64_t rss_hf = rss_conf->rss_hf;
 	uint8_t *key = rss_conf->rss_key;
 	int ret;
 
+	if (hw->rss_dis_flag)
+		return -EINVAL;
+
 	rte_spinlock_lock(&hw->lock);
 	ret = hns3_set_rss_tuple_by_rss_hf(hw, tuple, rss_hf);
 	if (ret)
@@ -285,6 +292,8 @@ hns3_dev_rss_hash_update(struct rte_eth_dev *dev,
 			ret = -EINVAL;
 			goto conf_err;
 		}
+		algo = rss_cfg->conf.func == RTE_ETH_HASH_FUNCTION_SIMPLE_XOR ?
+			HNS3_RSS_HASH_ALGO_SIMPLE : HNS3_RSS_HASH_ALGO_TOEPLITZ;
 		ret = hns3_set_rss_algo_key(hw, algo, key);
 		if (ret)
 			goto conf_err;
@@ -319,8 +328,10 @@ hns3_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
 	rss_conf->rss_hf = rss_cfg->conf.types;
 
 	/* Get the RSS Key required by the user */
-	if (rss_conf->rss_key)
+	if (rss_conf->rss_key && rss_conf->rss_key_len >= HNS3_RSS_KEY_SIZE) {
 		memcpy(rss_conf->rss_key, rss_cfg->key, HNS3_RSS_KEY_SIZE);
+		rss_conf->rss_key_len = HNS3_RSS_KEY_SIZE;
+	}
 	rte_spinlock_unlock(&hw->lock);
 
 	return 0;
@@ -347,7 +358,7 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
 	struct hns3_rss_conf *rss_cfg = &hw->rss_info;
 	uint16_t i, indir_size = HNS3_RSS_IND_TBL_SIZE; /* Table size is 512 */
 	uint8_t indirection_tbl[HNS3_RSS_IND_TBL_SIZE];
-	uint16_t idx, shift, allow_rss_queues;
+	uint16_t idx, shift;
 	int ret;
 
 	if (reta_size != indir_size || reta_size > ETH_RSS_RETA_SIZE_512) {
@@ -359,16 +370,15 @@ hns3_dev_rss_reta_update(struct rte_eth_dev *dev,
 	rte_spinlock_lock(&hw->lock);
 	memcpy(indirection_tbl, rss_cfg->rss_indirection_tbl,
 		HNS3_RSS_IND_TBL_SIZE);
-	allow_rss_queues = RTE_MIN(dev->data->nb_rx_queues, hw->rss_size_max);
 	for (i = 0; i < reta_size; i++) {
 		idx = i / RTE_RETA_GROUP_SIZE;
 		shift = i % RTE_RETA_GROUP_SIZE;
-		if (reta_conf[idx].reta[shift] >= allow_rss_queues) {
+		if (reta_conf[idx].reta[shift] >= hw->alloc_rss_size) {
 			rte_spinlock_unlock(&hw->lock);
-			hns3_err(hw, "Invalid queue id(%u) to be set in "
-				 "redirection table, max number of rss "
-				 "queues: %u", reta_conf[idx].reta[shift],
-				 allow_rss_queues);
+			hns3_err(hw, "queue id(%u) set to redirection table "
+				 "exceeds queue number(%u) allocated to a TC",
+				 reta_conf[idx].reta[shift],
+				 hw->alloc_rss_size);
 			return -EINVAL;
 		}
 
@@ -417,7 +427,7 @@ hns3_dev_rss_reta_query(struct rte_eth_dev *dev,
 		shift = i % RTE_RETA_GROUP_SIZE;
 		if (reta_conf[idx].mask & (1ULL << shift))
 			reta_conf[idx].reta[shift] =
-			  rss_cfg->rss_indirection_tbl[i] % hw->alloc_rss_size;
+						rss_cfg->rss_indirection_tbl[i];
 	}
 	rte_spinlock_unlock(&hw->lock);
 	return 0;
@@ -500,7 +510,9 @@ hns3_set_default_rss_args(struct hns3_hw *hw)
 	int i;
 
 	/* Default hash algorithm */
-	rss_cfg->conf.func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
+	rss_cfg->conf.func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
+
+	/* Default RSS key */
 	memcpy(rss_cfg->key, hns3_hash_key, HNS3_RSS_KEY_SIZE);
 
 	/* Initialize RSS indirection table */
@@ -524,7 +536,7 @@ hns3_config_rss(struct hns3_adapter *hns)
 
 	enum rte_eth_rx_mq_mode mq_mode = hw->data->dev_conf.rxmode.mq_mode;
 
-	/* When there is no open RSS, redirect the packet queue 0 */
+	/* When RSS is off, redirect the packet queue 0 */
 	if (((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG) == 0)
 		hns3_rss_uninit(hns);
 
@@ -538,10 +550,16 @@ hns3_config_rss(struct hns3_adapter *hns)
 	if (ret)
 		return ret;
 
-	ret = hns3_set_rss_indir_table(hw, rss_cfg->rss_indirection_tbl,
-				       HNS3_RSS_IND_TBL_SIZE);
-	if (ret)
-		goto rss_tuple_uninit;
+	/*
+	 * When RSS is off, it doesn't need to configure rss redirection table
+	 * to hardware.
+	 */
+	if (((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG)) {
+		ret = hns3_set_rss_indir_table(hw, rss_cfg->rss_indirection_tbl,
+					       HNS3_RSS_IND_TBL_SIZE);
+		if (ret)
+			goto rss_tuple_uninit;
+	}
 
 	ret = hns3_set_rss_tc_mode(hw);
 	if (ret)
@@ -550,9 +568,11 @@ hns3_config_rss(struct hns3_adapter *hns)
 	return ret;
 
 rss_indir_table_uninit:
-	ret1 = hns3_rss_reset_indir_table(hw);
-	if (ret1 != 0)
-		return ret;
+	if (((uint32_t)mq_mode & ETH_MQ_RX_RSS_FLAG)) {
+		ret1 = hns3_rss_reset_indir_table(hw);
+		if (ret1 != 0)
+			return ret;
+	}
 
 rss_tuple_uninit:
 	hns3_rss_tuple_uninit(hw);
diff --git a/dpdk/drivers/net/hns3/hns3_rss.h b/dpdk/drivers/net/hns3/hns3_rss.h
index 7ffc151314..b49e399901 100644
--- a/dpdk/drivers/net/hns3/hns3_rss.h
+++ b/dpdk/drivers/net/hns3/hns3_rss.h
@@ -54,6 +54,7 @@ struct hns3_rss_conf {
 	struct hns3_rss_tuple_cfg rss_tuple_sets;
 	uint8_t rss_indirection_tbl[HNS3_RSS_IND_TBL_SIZE]; /* Shadow table */
 	uint16_t queue[HNS3_RSS_QUEUES_BUFFER_NUM]; /* Queues indices to use */
+	bool valid; /* check if RSS rule is valid */
 };
 
 /* Bit 8 ~Bit 15 */
@@ -121,4 +122,6 @@ int hns3_set_rss_tuple_by_rss_hf(struct hns3_hw *hw,
 				 uint64_t rss_hf);
 int hns3_set_rss_algo_key(struct hns3_hw *hw, uint8_t hash_algo,
 			  const uint8_t *key);
+int hns3_restore_rss_filter(struct rte_eth_dev *dev);
+
 #endif /* _HNS3_RSS_H_ */
diff --git a/dpdk/drivers/net/hns3/hns3_rxtx.c b/dpdk/drivers/net/hns3/hns3_rxtx.c
index 8166447131..5971cf6cd5 100644
--- a/dpdk/drivers/net/hns3/hns3_rxtx.c
+++ b/dpdk/drivers/net/hns3/hns3_rxtx.c
@@ -30,13 +30,14 @@
 #include "hns3_logs.h"
 
 #define HNS3_CFG_DESC_NUM(num)	((num) / 8 - 1)
-#define DEFAULT_RX_FREE_THRESH	16
+#define DEFAULT_RX_FREE_THRESH	32
 
 static void
 hns3_rx_queue_release_mbufs(struct hns3_rx_queue *rxq)
 {
 	uint16_t i;
 
+	/* Note: Fake rx queue will not enter here */
 	if (rxq->sw_ring) {
 		for (i = 0; i < rxq->nb_rx_desc; i++) {
 			if (rxq->sw_ring[i].mbuf) {
@@ -52,6 +53,7 @@ hns3_tx_queue_release_mbufs(struct hns3_tx_queue *txq)
 {
 	uint16_t i;
 
+	/* Note: Fake rx queue will not enter here */
 	if (txq->sw_ring) {
 		for (i = 0; i < txq->nb_tx_desc; i++) {
 			if (txq->sw_ring[i].mbuf) {
@@ -120,22 +122,115 @@ hns3_dev_tx_queue_release(void *queue)
 	rte_spinlock_unlock(&hns->hw.lock);
 }
 
-void
-hns3_free_all_queues(struct rte_eth_dev *dev)
+static void
+hns3_fake_rx_queue_release(struct hns3_rx_queue *queue)
+{
+	struct hns3_rx_queue *rxq = queue;
+	struct hns3_adapter *hns;
+	struct hns3_hw *hw;
+	uint16_t idx;
+
+	if (rxq == NULL)
+		return;
+
+	hns = rxq->hns;
+	hw = &hns->hw;
+	idx = rxq->queue_id;
+	if (hw->fkq_data.rx_queues[idx]) {
+		hns3_rx_queue_release(hw->fkq_data.rx_queues[idx]);
+		hw->fkq_data.rx_queues[idx] = NULL;
+	}
+
+	/* free fake rx queue arrays */
+	if (idx == (hw->fkq_data.nb_fake_rx_queues - 1)) {
+		hw->fkq_data.nb_fake_rx_queues = 0;
+		rte_free(hw->fkq_data.rx_queues);
+		hw->fkq_data.rx_queues = NULL;
+	}
+}
+
+static void
+hns3_fake_tx_queue_release(struct hns3_tx_queue *queue)
 {
+	struct hns3_tx_queue *txq = queue;
+	struct hns3_adapter *hns;
+	struct hns3_hw *hw;
+	uint16_t idx;
+
+	if (txq == NULL)
+		return;
+
+	hns = txq->hns;
+	hw = &hns->hw;
+	idx = txq->queue_id;
+	if (hw->fkq_data.tx_queues[idx]) {
+		hns3_tx_queue_release(hw->fkq_data.tx_queues[idx]);
+		hw->fkq_data.tx_queues[idx] = NULL;
+	}
+
+	/* free fake tx queue arrays */
+	if (idx == (hw->fkq_data.nb_fake_tx_queues - 1)) {
+		hw->fkq_data.nb_fake_tx_queues = 0;
+		rte_free(hw->fkq_data.tx_queues);
+		hw->fkq_data.tx_queues = NULL;
+	}
+}
+
+static void
+hns3_free_rx_queues(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_fake_queue_data *fkq_data;
+	struct hns3_hw *hw = &hns->hw;
+	uint16_t nb_rx_q;
 	uint16_t i;
 
-	if (dev->data->rx_queues)
-		for (i = 0; i < dev->data->nb_rx_queues; i++) {
+	nb_rx_q = hw->data->nb_rx_queues;
+	for (i = 0; i < nb_rx_q; i++) {
+		if (dev->data->rx_queues[i]) {
 			hns3_rx_queue_release(dev->data->rx_queues[i]);
 			dev->data->rx_queues[i] = NULL;
 		}
+	}
+
+	/* Free fake Rx queues */
+	fkq_data = &hw->fkq_data;
+	for (i = 0; i < fkq_data->nb_fake_rx_queues; i++) {
+		if (fkq_data->rx_queues[i])
+			hns3_fake_rx_queue_release(fkq_data->rx_queues[i]);
+	}
+}
+
+static void
+hns3_free_tx_queues(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_fake_queue_data *fkq_data;
+	struct hns3_hw *hw = &hns->hw;
+	uint16_t nb_tx_q;
+	uint16_t i;
 
-	if (dev->data->tx_queues)
-		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+	nb_tx_q = hw->data->nb_tx_queues;
+	for (i = 0; i < nb_tx_q; i++) {
+		if (dev->data->tx_queues[i]) {
 			hns3_tx_queue_release(dev->data->tx_queues[i]);
 			dev->data->tx_queues[i] = NULL;
 		}
+	}
+
+	/* Free fake Tx queues */
+	fkq_data = &hw->fkq_data;
+	for (i = 0; i < fkq_data->nb_fake_tx_queues; i++) {
+		if (fkq_data->tx_queues[i])
+			hns3_fake_tx_queue_release(fkq_data->tx_queues[i]);
+	}
+}
+
+void
+hns3_free_all_queues(struct rte_eth_dev *dev)
+{
+	hns3_free_rx_queues(dev);
+	hns3_free_tx_queues(dev);
 }
 
 static int
@@ -220,20 +315,54 @@ hns3_init_tx_queue_hw(struct hns3_tx_queue *txq)
 		       HNS3_CFG_DESC_NUM(txq->nb_tx_desc));
 }
 
-static void
+void
+hns3_update_all_queues_pvid_state(struct hns3_hw *hw)
+{
+	uint16_t nb_rx_q = hw->data->nb_rx_queues;
+	uint16_t nb_tx_q = hw->data->nb_tx_queues;
+	struct hns3_rx_queue *rxq;
+	struct hns3_tx_queue *txq;
+	int pvid_state;
+	int i;
+
+	pvid_state = hw->port_base_vlan_cfg.state;
+	for (i = 0; i < hw->cfg_max_queues; i++) {
+		if (i < nb_rx_q) {
+			rxq = hw->data->rx_queues[i];
+			if (rxq != NULL)
+				rxq->pvid_state = pvid_state;
+		}
+		if (i < nb_tx_q) {
+			txq = hw->data->tx_queues[i];
+			if (txq != NULL)
+				txq->pvid_state = pvid_state;
+		}
+	}
+}
+
+void
 hns3_enable_all_queues(struct hns3_hw *hw, bool en)
 {
+	uint16_t nb_rx_q = hw->data->nb_rx_queues;
+	uint16_t nb_tx_q = hw->data->nb_tx_queues;
 	struct hns3_rx_queue *rxq;
 	struct hns3_tx_queue *txq;
 	uint32_t rcb_reg;
 	int i;
 
-	for (i = 0; i < hw->data->nb_rx_queues; i++) {
-		rxq = hw->data->rx_queues[i];
-		txq = hw->data->tx_queues[i];
+	for (i = 0; i < hw->cfg_max_queues; i++) {
+		if (i < nb_rx_q)
+			rxq = hw->data->rx_queues[i];
+		else
+			rxq = hw->fkq_data.rx_queues[i - nb_rx_q];
+		if (i < nb_tx_q)
+			txq = hw->data->tx_queues[i];
+		else
+			txq = hw->fkq_data.tx_queues[i - nb_tx_q];
 		if (rxq == NULL || txq == NULL ||
 		    (en && (rxq->rx_deferred_start || txq->tx_deferred_start)))
 			continue;
+
 		rcb_reg = hns3_read_dev(rxq, HNS3_RING_EN_REG);
 		if (en)
 			rcb_reg |= BIT(HNS3_RING_EN_B);
@@ -382,10 +511,9 @@ int
 hns3_reset_all_queues(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	int ret;
-	uint16_t i;
+	int ret, i;
 
-	for (i = 0; i < hw->data->nb_rx_queues; i++) {
+	for (i = 0; i < hw->cfg_max_queues; i++) {
 		ret = hns3_reset_queue(hns, i);
 		if (ret) {
 			hns3_err(hw, "Failed to reset No.%d queue: %d", i, ret);
@@ -395,6 +523,99 @@ hns3_reset_all_queues(struct hns3_adapter *hns)
 	return 0;
 }
 
+void
+hns3_set_queue_intr_gl(struct hns3_hw *hw, uint16_t queue_id,
+		       uint8_t gl_idx, uint16_t gl_value)
+{
+	uint32_t offset[] = {HNS3_TQP_INTR_GL0_REG,
+			     HNS3_TQP_INTR_GL1_REG,
+			     HNS3_TQP_INTR_GL2_REG};
+	uint32_t addr, value;
+
+	if (gl_idx >= RTE_DIM(offset) || gl_value > HNS3_TQP_INTR_GL_MAX)
+		return;
+
+	addr = offset[gl_idx] + queue_id * HNS3_TQP_INTR_REG_SIZE;
+	value = HNS3_GL_USEC_TO_REG(gl_value);
+
+	hns3_write_dev(hw, addr, value);
+}
+
+void
+hns3_set_queue_intr_rl(struct hns3_hw *hw, uint16_t queue_id, uint16_t rl_value)
+{
+	uint32_t addr, value;
+
+	if (rl_value > HNS3_TQP_INTR_RL_MAX)
+		return;
+
+	addr = HNS3_TQP_INTR_RL_REG + queue_id * HNS3_TQP_INTR_REG_SIZE;
+	value = HNS3_RL_USEC_TO_REG(rl_value);
+	if (value > 0)
+		value |= HNS3_TQP_INTR_RL_ENABLE_MASK;
+
+	hns3_write_dev(hw, addr, value);
+}
+
+static void
+hns3_queue_intr_enable(struct hns3_hw *hw, uint16_t queue_id, bool en)
+{
+	uint32_t addr, value;
+
+	addr = HNS3_TQP_INTR_CTRL_REG + queue_id * HNS3_TQP_INTR_REG_SIZE;
+	value = en ? 1 : 0;
+
+	hns3_write_dev(hw, addr, value);
+}
+
+/*
+ * Enable all rx queue interrupt when in interrupt rx mode.
+ * This api was called before enable queue rx&tx (in normal start or reset
+ * recover scenes), used to fix hardware rx queue interrupt enable was clear
+ * when FLR.
+ */
+void
+hns3_dev_all_rx_queue_intr_enable(struct hns3_hw *hw, bool en)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[hw->data->port_id];
+	uint16_t nb_rx_q = hw->data->nb_rx_queues;
+	int i;
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return;
+
+	for (i = 0; i < nb_rx_q; i++)
+		hns3_queue_intr_enable(hw, i, en);
+}
+
+int
+hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
+	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return -ENOTSUP;
+
+	hns3_queue_intr_enable(hw, queue_id, true);
+
+	return rte_intr_ack(intr_handle);
+}
+
+int
+hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+	if (dev->data->dev_conf.intr_conf.rxq == 0)
+		return -ENOTSUP;
+
+	hns3_queue_intr_enable(hw, queue_id, false);
+
+	return 0;
+}
+
 static int
 hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 {
@@ -404,32 +625,40 @@ hns3_dev_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 
 	PMD_INIT_FUNC_TRACE();
 
-	rxq = hw->data->rx_queues[idx];
-
+	rxq = (struct hns3_rx_queue *)hw->data->rx_queues[idx];
 	ret = hns3_alloc_rx_queue_mbufs(hw, rxq);
 	if (ret) {
 		hns3_err(hw, "Failed to alloc mbuf for No.%d rx queue: %d",
-			    idx, ret);
+			 idx, ret);
 		return ret;
 	}
 
 	rxq->next_to_use = 0;
-	rxq->next_to_clean = 0;
+	rxq->rx_free_hold = 0;
 	hns3_init_rx_queue_hw(rxq);
 
 	return 0;
 }
 
 static void
-hns3_dev_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+hns3_fake_rx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 {
 	struct hns3_hw *hw = &hns->hw;
-	struct hns3_tx_queue *txq;
+	struct hns3_rx_queue *rxq;
+
+	rxq = (struct hns3_rx_queue *)hw->fkq_data.rx_queues[idx];
+	rxq->next_to_use = 0;
+	rxq->rx_free_hold = 0;
+	hns3_init_rx_queue_hw(rxq);
+}
+
+static void
+hns3_init_tx_queue(struct hns3_tx_queue *queue)
+{
+	struct hns3_tx_queue *txq = queue;
 	struct hns3_desc *desc;
 	int i;
 
-	txq = hw->data->tx_queues[idx];
-
 	/* Clear tx bd */
 	desc = txq->tx_ring;
 	for (i = 0; i < txq->nb_tx_desc; i++) {
@@ -439,10 +668,30 @@ hns3_dev_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
 
 	txq->next_to_use = 0;
 	txq->next_to_clean = 0;
-	txq->tx_bd_ready   = txq->nb_tx_desc;
+	txq->tx_bd_ready = txq->nb_tx_desc - 1;
 	hns3_init_tx_queue_hw(txq);
 }
 
+static void
+hns3_dev_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+{
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_tx_queue *txq;
+
+	txq = (struct hns3_tx_queue *)hw->data->tx_queues[idx];
+	hns3_init_tx_queue(txq);
+}
+
+static void
+hns3_fake_tx_queue_start(struct hns3_adapter *hns, uint16_t idx)
+{
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_tx_queue *txq;
+
+	txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[idx];
+	hns3_init_tx_queue(txq);
+}
+
 static void
 hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 {
@@ -459,7 +708,7 @@ hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 
 		for (j = 0; j < tc_queue->tqp_count; j++) {
 			num = tc_queue->tqp_offset + j;
-			txq = hw->data->tx_queues[num];
+			txq = (struct hns3_tx_queue *)hw->data->tx_queues[num];
 			if (txq == NULL)
 				continue;
 
@@ -468,16 +717,13 @@ hns3_init_tx_ring_tc(struct hns3_adapter *hns)
 	}
 }
 
-int
-hns3_start_queues(struct hns3_adapter *hns, bool reset_queue)
+static int
+hns3_start_rx_queues(struct hns3_adapter *hns)
 {
 	struct hns3_hw *hw = &hns->hw;
-	struct rte_eth_dev_data *dev_data = hw->data;
 	struct hns3_rx_queue *rxq;
-	struct hns3_tx_queue *txq;
+	int i, j;
 	int ret;
-	int i;
-	int j;
 
 	/* Initialize RSS for queues */
 	ret = hns3_config_rss(hns);
@@ -486,49 +732,88 @@ hns3_start_queues(struct hns3_adapter *hns, bool reset_queue)
 		return ret;
 	}
 
-	if (reset_queue) {
-		ret = hns3_reset_all_queues(hns);
-		if (ret) {
-			hns3_err(hw, "Failed to reset all queues %d", ret);
-			return ret;
-		}
-	}
-
-	/*
-	 * Hardware does not support where the number of rx and tx queues is
-	 * not equal in hip08. In .dev_configure callback function we will
-	 * check the two values, here we think that the number of rx and tx
-	 * queues is equal.
-	 */
 	for (i = 0; i < hw->data->nb_rx_queues; i++) {
-		rxq = dev_data->rx_queues[i];
-		txq = dev_data->tx_queues[i];
-		if (rxq == NULL || txq == NULL || rxq->rx_deferred_start ||
-		    txq->tx_deferred_start)
+		rxq = (struct hns3_rx_queue *)hw->data->rx_queues[i];
+		if (rxq == NULL || rxq->rx_deferred_start)
 			continue;
-
 		ret = hns3_dev_rx_queue_start(hns, i);
 		if (ret) {
 			hns3_err(hw, "Failed to start No.%d rx queue: %d", i,
 				 ret);
 			goto out;
 		}
-		hns3_dev_tx_queue_start(hns, i);
 	}
-	hns3_init_tx_ring_tc(hns);
 
-	hns3_enable_all_queues(hw, true);
+	for (i = 0; i < hw->fkq_data.nb_fake_rx_queues; i++) {
+		rxq = (struct hns3_rx_queue *)hw->fkq_data.rx_queues[i];
+		if (rxq == NULL || rxq->rx_deferred_start)
+			continue;
+		hns3_fake_rx_queue_start(hns, i);
+	}
 	return 0;
 
 out:
 	for (j = 0; j < i; j++) {
-		rxq = dev_data->rx_queues[j];
+		rxq = (struct hns3_rx_queue *)hw->data->rx_queues[j];
 		hns3_rx_queue_release_mbufs(rxq);
 	}
 
 	return ret;
 }
 
+static void
+hns3_start_tx_queues(struct hns3_adapter *hns)
+{
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_tx_queue *txq;
+	int i;
+
+	for (i = 0; i < hw->data->nb_tx_queues; i++) {
+		txq = (struct hns3_tx_queue *)hw->data->tx_queues[i];
+		if (txq == NULL || txq->tx_deferred_start)
+			continue;
+		hns3_dev_tx_queue_start(hns, i);
+	}
+
+	for (i = 0; i < hw->fkq_data.nb_fake_tx_queues; i++) {
+		txq = (struct hns3_tx_queue *)hw->fkq_data.tx_queues[i];
+		if (txq == NULL || txq->tx_deferred_start)
+			continue;
+		hns3_fake_tx_queue_start(hns, i);
+	}
+
+	hns3_init_tx_ring_tc(hns);
+}
+
+/*
+ * Start all queues.
+ * Note: just init and setup queues, and don't enable queue rx&tx.
+ */
+int
+hns3_start_queues(struct hns3_adapter *hns, bool reset_queue)
+{
+	struct hns3_hw *hw = &hns->hw;
+	int ret;
+
+	if (reset_queue) {
+		ret = hns3_reset_all_queues(hns);
+		if (ret) {
+			hns3_err(hw, "Failed to reset all queues %d", ret);
+			return ret;
+		}
+	}
+
+	ret = hns3_start_rx_queues(hns);
+	if (ret) {
+		hns3_err(hw, "Failed to start rx queues: %d", ret);
+		return ret;
+	}
+
+	hns3_start_tx_queues(hns);
+
+	return 0;
+}
+
 int
 hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue)
 {
@@ -546,6 +831,333 @@ hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue)
 	return 0;
 }
 
+static void*
+hns3_alloc_rxq_and_dma_zone(struct rte_eth_dev *dev,
+			    struct hns3_queue_info *q_info)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	const struct rte_memzone *rx_mz;
+	struct hns3_rx_queue *rxq;
+	unsigned int rx_desc;
+
+	rxq = rte_zmalloc_socket(q_info->type, sizeof(struct hns3_rx_queue),
+				 RTE_CACHE_LINE_SIZE, q_info->socket_id);
+	if (rxq == NULL) {
+		hns3_err(hw, "Failed to allocate memory for No.%d rx ring!",
+			 q_info->idx);
+		return NULL;
+	}
+
+	/* Allocate rx ring hardware descriptors. */
+	rxq->queue_id = q_info->idx;
+	rxq->nb_rx_desc = q_info->nb_desc;
+	rx_desc = rxq->nb_rx_desc * sizeof(struct hns3_desc);
+	rx_mz = rte_eth_dma_zone_reserve(dev, q_info->ring_name, q_info->idx,
+					 rx_desc, HNS3_RING_BASE_ALIGN,
+					 q_info->socket_id);
+	if (rx_mz == NULL) {
+		hns3_err(hw, "Failed to reserve DMA memory for No.%d rx ring!",
+			 q_info->idx);
+		hns3_rx_queue_release(rxq);
+		return NULL;
+	}
+	rxq->mz = rx_mz;
+	rxq->rx_ring = (struct hns3_desc *)rx_mz->addr;
+	rxq->rx_ring_phys_addr = rx_mz->iova;
+
+	hns3_dbg(hw, "No.%d rx descriptors iova 0x%" PRIx64, q_info->idx,
+		 rxq->rx_ring_phys_addr);
+
+	return rxq;
+}
+
+static int
+hns3_fake_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
+			 uint16_t nb_desc, unsigned int socket_id)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_queue_info q_info;
+	struct hns3_rx_queue *rxq;
+	uint16_t nb_rx_q;
+
+	if (hw->fkq_data.rx_queues[idx]) {
+		hns3_rx_queue_release(hw->fkq_data.rx_queues[idx]);
+		hw->fkq_data.rx_queues[idx] = NULL;
+	}
+
+	q_info.idx = idx;
+	q_info.socket_id = socket_id;
+	q_info.nb_desc = nb_desc;
+	q_info.type = "hns3 fake RX queue";
+	q_info.ring_name = "rx_fake_ring";
+	rxq = hns3_alloc_rxq_and_dma_zone(dev, &q_info);
+	if (rxq == NULL) {
+		hns3_err(hw, "Failed to setup No.%d fake rx ring.", idx);
+		return -ENOMEM;
+	}
+
+	/* Don't need alloc sw_ring, because upper applications don't use it */
+	rxq->sw_ring = NULL;
+
+	rxq->hns = hns;
+	rxq->rx_deferred_start = false;
+	rxq->port_id = dev->data->port_id;
+	rxq->configured = true;
+	nb_rx_q = dev->data->nb_rx_queues;
+	rxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
+				(nb_rx_q + idx) * HNS3_TQP_REG_SIZE);
+	rxq->rx_buf_len = HNS3_MIN_BD_BUF_SIZE;
+
+	rte_spinlock_lock(&hw->lock);
+	hw->fkq_data.rx_queues[idx] = rxq;
+	rte_spinlock_unlock(&hw->lock);
+
+	return 0;
+}
+
+static void*
+hns3_alloc_txq_and_dma_zone(struct rte_eth_dev *dev,
+			    struct hns3_queue_info *q_info)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	const struct rte_memzone *tx_mz;
+	struct hns3_tx_queue *txq;
+	struct hns3_desc *desc;
+	unsigned int tx_desc;
+	int i;
+
+	txq = rte_zmalloc_socket(q_info->type, sizeof(struct hns3_tx_queue),
+				 RTE_CACHE_LINE_SIZE, q_info->socket_id);
+	if (txq == NULL) {
+		hns3_err(hw, "Failed to allocate memory for No.%d tx ring!",
+			 q_info->idx);
+		return NULL;
+	}
+
+	/* Allocate tx ring hardware descriptors. */
+	txq->queue_id = q_info->idx;
+	txq->nb_tx_desc = q_info->nb_desc;
+	tx_desc = txq->nb_tx_desc * sizeof(struct hns3_desc);
+	tx_mz = rte_eth_dma_zone_reserve(dev, q_info->ring_name, q_info->idx,
+					 tx_desc, HNS3_RING_BASE_ALIGN,
+					 q_info->socket_id);
+	if (tx_mz == NULL) {
+		hns3_err(hw, "Failed to reserve DMA memory for No.%d tx ring!",
+			 q_info->idx);
+		hns3_tx_queue_release(txq);
+		return NULL;
+	}
+	txq->mz = tx_mz;
+	txq->tx_ring = (struct hns3_desc *)tx_mz->addr;
+	txq->tx_ring_phys_addr = tx_mz->iova;
+
+	hns3_dbg(hw, "No.%d tx descriptors iova 0x%" PRIx64, q_info->idx,
+		 txq->tx_ring_phys_addr);
+
+	/* Clear tx bd */
+	desc = txq->tx_ring;
+	for (i = 0; i < txq->nb_tx_desc; i++) {
+		desc->tx.tp_fe_sc_vld_ra_ri = 0;
+		desc++;
+	}
+
+	return txq;
+}
+
+static int
+hns3_fake_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
+			 uint16_t nb_desc, unsigned int socket_id)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_queue_info q_info;
+	struct hns3_tx_queue *txq;
+	uint16_t nb_tx_q;
+
+	if (hw->fkq_data.tx_queues[idx] != NULL) {
+		hns3_tx_queue_release(hw->fkq_data.tx_queues[idx]);
+		hw->fkq_data.tx_queues[idx] = NULL;
+	}
+
+	q_info.idx = idx;
+	q_info.socket_id = socket_id;
+	q_info.nb_desc = nb_desc;
+	q_info.type = "hns3 fake TX queue";
+	q_info.ring_name = "tx_fake_ring";
+	txq = hns3_alloc_txq_and_dma_zone(dev, &q_info);
+	if (txq == NULL) {
+		hns3_err(hw, "Failed to setup No.%d fake tx ring.", idx);
+		return -ENOMEM;
+	}
+
+	/* Don't need alloc sw_ring, because upper applications don't use it */
+	txq->sw_ring = NULL;
+
+	txq->hns = hns;
+	txq->tx_deferred_start = false;
+	txq->port_id = dev->data->port_id;
+	txq->configured = true;
+	nb_tx_q = dev->data->nb_tx_queues;
+	txq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
+				(nb_tx_q + idx) * HNS3_TQP_REG_SIZE);
+
+	rte_spinlock_lock(&hw->lock);
+	hw->fkq_data.tx_queues[idx] = txq;
+	rte_spinlock_unlock(&hw->lock);
+
+	return 0;
+}
+
+static int
+hns3_fake_rx_queue_config(struct hns3_hw *hw, uint16_t nb_queues)
+{
+	uint16_t old_nb_queues = hw->fkq_data.nb_fake_rx_queues;
+	void **rxq;
+	uint16_t i;
+
+	if (hw->fkq_data.rx_queues == NULL && nb_queues != 0) {
+		/* first time configuration */
+		uint32_t size;
+		size = sizeof(hw->fkq_data.rx_queues[0]) * nb_queues;
+		hw->fkq_data.rx_queues = rte_zmalloc("fake_rx_queues", size,
+						     RTE_CACHE_LINE_SIZE);
+		if (hw->fkq_data.rx_queues == NULL) {
+			hw->fkq_data.nb_fake_rx_queues = 0;
+			return -ENOMEM;
+		}
+	} else if (hw->fkq_data.rx_queues != NULL && nb_queues != 0) {
+		/* re-configure */
+		rxq = hw->fkq_data.rx_queues;
+		for (i = nb_queues; i < old_nb_queues; i++)
+			hns3_dev_rx_queue_release(rxq[i]);
+
+		rxq = rte_realloc(rxq, sizeof(rxq[0]) * nb_queues,
+				  RTE_CACHE_LINE_SIZE);
+		if (rxq == NULL)
+			return -ENOMEM;
+		if (nb_queues > old_nb_queues) {
+			uint16_t new_qs = nb_queues - old_nb_queues;
+			memset(rxq + old_nb_queues, 0, sizeof(rxq[0]) * new_qs);
+		}
+
+		hw->fkq_data.rx_queues = rxq;
+	} else if (hw->fkq_data.rx_queues != NULL && nb_queues == 0) {
+		rxq = hw->fkq_data.rx_queues;
+		for (i = nb_queues; i < old_nb_queues; i++)
+			hns3_dev_rx_queue_release(rxq[i]);
+
+		rte_free(hw->fkq_data.rx_queues);
+		hw->fkq_data.rx_queues = NULL;
+	}
+
+	hw->fkq_data.nb_fake_rx_queues = nb_queues;
+
+	return 0;
+}
+
+static int
+hns3_fake_tx_queue_config(struct hns3_hw *hw, uint16_t nb_queues)
+{
+	uint16_t old_nb_queues = hw->fkq_data.nb_fake_tx_queues;
+	void **txq;
+	uint16_t i;
+
+	if (hw->fkq_data.tx_queues == NULL && nb_queues != 0) {
+		/* first time configuration */
+		uint32_t size;
+		size = sizeof(hw->fkq_data.tx_queues[0]) * nb_queues;
+		hw->fkq_data.tx_queues = rte_zmalloc("fake_tx_queues", size,
+						     RTE_CACHE_LINE_SIZE);
+		if (hw->fkq_data.tx_queues == NULL) {
+			hw->fkq_data.nb_fake_tx_queues = 0;
+			return -ENOMEM;
+		}
+	} else if (hw->fkq_data.tx_queues != NULL && nb_queues != 0) {
+		/* re-configure */
+		txq = hw->fkq_data.tx_queues;
+		for (i = nb_queues; i < old_nb_queues; i++)
+			hns3_dev_tx_queue_release(txq[i]);
+		txq = rte_realloc(txq, sizeof(txq[0]) * nb_queues,
+				  RTE_CACHE_LINE_SIZE);
+		if (txq == NULL)
+			return -ENOMEM;
+		if (nb_queues > old_nb_queues) {
+			uint16_t new_qs = nb_queues - old_nb_queues;
+			memset(txq + old_nb_queues, 0, sizeof(txq[0]) * new_qs);
+		}
+
+		hw->fkq_data.tx_queues = txq;
+	} else if (hw->fkq_data.tx_queues != NULL && nb_queues == 0) {
+		txq = hw->fkq_data.tx_queues;
+		for (i = nb_queues; i < old_nb_queues; i++)
+			hns3_dev_tx_queue_release(txq[i]);
+
+		rte_free(hw->fkq_data.tx_queues);
+		hw->fkq_data.tx_queues = NULL;
+	}
+	hw->fkq_data.nb_fake_tx_queues = nb_queues;
+
+	return 0;
+}
+
+int
+hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,
+			      uint16_t nb_tx_q)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint16_t rx_need_add_nb_q;
+	uint16_t tx_need_add_nb_q;
+	uint16_t port_id;
+	uint16_t q;
+	int ret;
+
+	/* Setup new number of fake RX/TX queues and reconfigure device. */
+	hw->cfg_max_queues = RTE_MAX(nb_rx_q, nb_tx_q);
+	rx_need_add_nb_q = hw->cfg_max_queues - nb_rx_q;
+	tx_need_add_nb_q = hw->cfg_max_queues - nb_tx_q;
+	ret = hns3_fake_rx_queue_config(hw, rx_need_add_nb_q);
+	if (ret) {
+		hns3_err(hw, "Fail to configure fake rx queues: %d", ret);
+		goto cfg_fake_rx_q_fail;
+	}
+
+	ret = hns3_fake_tx_queue_config(hw, tx_need_add_nb_q);
+	if (ret) {
+		hns3_err(hw, "Fail to configure fake rx queues: %d", ret);
+		goto cfg_fake_tx_q_fail;
+	}
+
+	/* Allocate and set up fake RX queue per Ethernet port. */
+	port_id = hw->data->port_id;
+	for (q = 0; q < rx_need_add_nb_q; q++) {
+		ret = hns3_fake_rx_queue_setup(dev, q, HNS3_MIN_RING_DESC,
+					       rte_eth_dev_socket_id(port_id));
+		if (ret)
+			goto setup_fake_rx_q_fail;
+	}
+
+	/* Allocate and set up fake TX queue per Ethernet port. */
+	for (q = 0; q < tx_need_add_nb_q; q++) {
+		ret = hns3_fake_tx_queue_setup(dev, q, HNS3_MIN_RING_DESC,
+					       rte_eth_dev_socket_id(port_id));
+		if (ret)
+			goto setup_fake_tx_q_fail;
+	}
+
+	return 0;
+
+setup_fake_tx_q_fail:
+setup_fake_rx_q_fail:
+	(void)hns3_fake_tx_queue_config(hw, 0);
+cfg_fake_tx_q_fail:
+	(void)hns3_fake_rx_queue_config(hw, 0);
+cfg_fake_rx_q_fail:
+	hw->cfg_max_queues = 0;
+
+	return ret;
+}
+
 void
 hns3_dev_release_mbufs(struct hns3_adapter *hns)
 {
@@ -571,17 +1183,58 @@ hns3_dev_release_mbufs(struct hns3_adapter *hns)
 		}
 }
 
+static int
+hns3_rx_buf_len_calc(struct rte_mempool *mp, uint16_t *rx_buf_len)
+{
+	uint16_t vld_buf_size;
+	uint16_t num_hw_specs;
+	uint16_t i;
+
+	/*
+	 * hns3 network engine only support to set 4 typical specification, and
+	 * different buffer size will affect the max packet_len and the max
+	 * number of segmentation when hw gro is turned on in receive side. The
+	 * relationship between them is as follows:
+	 *      rx_buf_size     |  max_gro_pkt_len  |  max_gro_nb_seg
+	 * ---------------------|-------------------|----------------
+	 * HNS3_4K_BD_BUF_SIZE  |        60KB       |       15
+	 * HNS3_2K_BD_BUF_SIZE  |        62KB       |       31
+	 * HNS3_1K_BD_BUF_SIZE  |        63KB       |       63
+	 * HNS3_512_BD_BUF_SIZE |      31.5KB       |       63
+	 */
+	static const uint16_t hw_rx_buf_size[] = {
+		HNS3_4K_BD_BUF_SIZE,
+		HNS3_2K_BD_BUF_SIZE,
+		HNS3_1K_BD_BUF_SIZE,
+		HNS3_512_BD_BUF_SIZE
+	};
+
+	vld_buf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) -
+			RTE_PKTMBUF_HEADROOM);
+
+	if (vld_buf_size < HNS3_MIN_BD_BUF_SIZE)
+		return -EINVAL;
+
+	num_hw_specs = RTE_DIM(hw_rx_buf_size);
+	for (i = 0; i < num_hw_specs; i++) {
+		if (vld_buf_size >= hw_rx_buf_size[i]) {
+			*rx_buf_len = hw_rx_buf_size[i];
+			break;
+		}
+	}
+	return 0;
+}
+
 int
 hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		    unsigned int socket_id, const struct rte_eth_rxconf *conf,
 		    struct rte_mempool *mp)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
-	const struct rte_memzone *rx_mz;
 	struct hns3_hw *hw = &hns->hw;
+	struct hns3_queue_info q_info;
 	struct hns3_rx_queue *rxq;
-	unsigned int desc_size = sizeof(struct hns3_desc);
-	unsigned int rx_desc;
+	uint16_t rx_buf_size;
 	int rx_entry_len;
 
 	if (dev->data->dev_started) {
@@ -596,26 +1249,42 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		return -EINVAL;
 	}
 
+	if (conf->rx_drop_en == 0)
+		hns3_warn(hw, "if there are no available Rx descriptors,"
+			  "incoming packets are always dropped. input parameter"
+			  " conf->rx_drop_en(%u) is uneffective.",
+			  conf->rx_drop_en);
+
 	if (dev->data->rx_queues[idx]) {
 		hns3_rx_queue_release(dev->data->rx_queues[idx]);
 		dev->data->rx_queues[idx] = NULL;
 	}
 
-	rxq = rte_zmalloc_socket("hns3 RX queue", sizeof(struct hns3_rx_queue),
-				 RTE_CACHE_LINE_SIZE, socket_id);
+	q_info.idx = idx;
+	q_info.socket_id = socket_id;
+	q_info.nb_desc = nb_desc;
+	q_info.type = "hns3 RX queue";
+	q_info.ring_name = "rx_ring";
+
+	if (hns3_rx_buf_len_calc(mp, &rx_buf_size)) {
+		hns3_err(hw, "rxq mbufs' data room size:%u is not enough! "
+				"minimal data room size:%u.",
+				rte_pktmbuf_data_room_size(mp),
+				HNS3_MIN_BD_BUF_SIZE + RTE_PKTMBUF_HEADROOM);
+		return -EINVAL;
+	}
+
+	rxq = hns3_alloc_rxq_and_dma_zone(dev, &q_info);
 	if (rxq == NULL) {
-		hns3_err(hw, "Failed to allocate memory for rx queue!");
+		hns3_err(hw,
+			 "Failed to alloc mem and reserve DMA mem for rx ring!");
 		return -ENOMEM;
 	}
 
 	rxq->hns = hns;
 	rxq->mb_pool = mp;
-	rxq->nb_rx_desc = nb_desc;
-	rxq->queue_id = idx;
-	if (conf->rx_free_thresh <= 0)
-		rxq->rx_free_thresh = DEFAULT_RX_FREE_THRESH;
-	else
-		rxq->rx_free_thresh = conf->rx_free_thresh;
+	rxq->rx_free_thresh = (conf->rx_free_thresh > 0) ?
+		conf->rx_free_thresh : HNS3_DEFAULT_RX_FREE_THRESH;
 	rxq->rx_deferred_start = conf->rx_deferred_start;
 
 	rx_entry_len = sizeof(struct hns3_entry) * rxq->nb_rx_desc;
@@ -627,34 +1296,18 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		return -ENOMEM;
 	}
 
-	/* Allocate rx ring hardware descriptors. */
-	rx_desc = rxq->nb_rx_desc * desc_size;
-	rx_mz = rte_eth_dma_zone_reserve(dev, "rx_ring", idx, rx_desc,
-					 HNS3_RING_BASE_ALIGN, socket_id);
-	if (rx_mz == NULL) {
-		hns3_err(hw, "Failed to reserve DMA memory for No.%d rx ring!",
-			 idx);
-		hns3_rx_queue_release(rxq);
-		return -ENOMEM;
-	}
-	rxq->mz = rx_mz;
-	rxq->rx_ring = (struct hns3_desc *)rx_mz->addr;
-	rxq->rx_ring_phys_addr = rx_mz->iova;
-
-	hns3_dbg(hw, "No.%d rx descriptors iova 0x%" PRIx64, idx,
-		 rxq->rx_ring_phys_addr);
-
 	rxq->next_to_use = 0;
-	rxq->next_to_clean = 0;
-	rxq->nb_rx_hold = 0;
+	rxq->rx_free_hold = 0;
 	rxq->pkt_first_seg = NULL;
 	rxq->pkt_last_seg = NULL;
 	rxq->port_id = dev->data->port_id;
+	rxq->pvid_state = hw->port_base_vlan_cfg.state;
 	rxq->configured = true;
 	rxq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
 				idx * HNS3_TQP_REG_SIZE);
-	rxq->rx_buf_len = hw->rx_buf_len;
-	rxq->non_vld_descs = 0;
+	rxq->io_head_reg = (volatile void *)((char *)rxq->io_base +
+			   HNS3_RING_RX_HEAD_REG);
+	rxq->rx_buf_len = rx_buf_size;
 	rxq->l2_errors = 0;
 	rxq->pkt_len_errors = 0;
 	rxq->l3_csum_erros = 0;
@@ -683,9 +1336,9 @@ rxd_pkt_info_to_pkt_type(uint32_t pkt_info, uint32_t ol_info)
 
 	static const uint32_t l2table[HNS3_L2TBL_NUM] = {
 		RTE_PTYPE_L2_ETHER,
-		RTE_PTYPE_L2_ETHER_VLAN,
 		RTE_PTYPE_L2_ETHER_QINQ,
-		0
+		RTE_PTYPE_L2_ETHER_VLAN,
+		RTE_PTYPE_L2_ETHER_VLAN
 	};
 
 	static const uint32_t l3table[HNS3_L3TBL_NUM] = {
@@ -797,16 +1450,6 @@ hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	return NULL;
 }
 
-static void
-hns3_clean_rx_buffers(struct hns3_rx_queue *rxq, int count)
-{
-	rxq->next_to_use += count;
-	if (rxq->next_to_use >= rxq->nb_rx_desc)
-		rxq->next_to_use -= rxq->nb_rx_desc;
-
-	hns3_write_dev(rxq, HNS3_RING_RX_HEAD_REG, count);
-}
-
 static int
 hns3_handle_bdinfo(struct hns3_rx_queue *rxq, struct rte_mbuf *rxm,
 		   uint32_t bd_base_info, uint32_t l234_info,
@@ -878,16 +1521,67 @@ hns3_rx_set_cksum_flag(struct rte_mbuf *rxm, uint64_t packet_type,
 	}
 }
 
+static inline void
+hns3_rxd_to_vlan_tci(struct hns3_rx_queue *rxq, struct rte_mbuf *mb,
+		     uint32_t l234_info, const struct hns3_desc *rxd)
+{
+#define HNS3_STRP_STATUS_NUM		0x4
+
+#define HNS3_NO_STRP_VLAN_VLD		0x0
+#define HNS3_INNER_STRP_VLAN_VLD	0x1
+#define HNS3_OUTER_STRP_VLAN_VLD	0x2
+	uint32_t strip_status;
+	uint32_t report_mode;
+
+	/*
+	 * Since HW limitation, the vlan tag will always be inserted into RX
+	 * descriptor when strip the tag from packet, driver needs to determine
+	 * reporting which tag to mbuf according to the PVID configuration
+	 * and vlan striped status.
+	 */
+	static const uint32_t report_type[][HNS3_STRP_STATUS_NUM] = {
+		{
+			HNS3_NO_STRP_VLAN_VLD,
+			HNS3_OUTER_STRP_VLAN_VLD,
+			HNS3_INNER_STRP_VLAN_VLD,
+			HNS3_OUTER_STRP_VLAN_VLD
+		},
+		{
+			HNS3_NO_STRP_VLAN_VLD,
+			HNS3_NO_STRP_VLAN_VLD,
+			HNS3_NO_STRP_VLAN_VLD,
+			HNS3_INNER_STRP_VLAN_VLD
+		}
+	};
+	strip_status = hns3_get_field(l234_info, HNS3_RXD_STRP_TAGP_M,
+				      HNS3_RXD_STRP_TAGP_S);
+	report_mode = report_type[rxq->pvid_state][strip_status];
+	switch (report_mode) {
+	case HNS3_NO_STRP_VLAN_VLD:
+		mb->vlan_tci = 0;
+		return;
+	case HNS3_INNER_STRP_VLAN_VLD:
+		mb->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
+		mb->vlan_tci = rte_le_to_cpu_16(rxd->rx.vlan_tag);
+		return;
+	case HNS3_OUTER_STRP_VLAN_VLD:
+		mb->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
+		mb->vlan_tci = rte_le_to_cpu_16(rxd->rx.ot_vlan_tag);
+		return;
+	}
+}
+
 uint16_t
 hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 {
+	volatile struct hns3_desc *rx_ring;  /* RX ring (desc) */
+	volatile struct hns3_desc *rxdp;     /* pointer of the current desc */
 	struct hns3_rx_queue *rxq;      /* RX queue */
-	struct hns3_desc *rx_ring;      /* RX ring (desc) */
 	struct hns3_entry *sw_ring;
 	struct hns3_entry *rxe;
-	struct hns3_desc *rxdp;         /* pointer of the current desc */
 	struct rte_mbuf *first_seg;
 	struct rte_mbuf *last_seg;
+	struct hns3_desc rxd;
 	struct rte_mbuf *nmb;           /* pointer of the new mbuf */
 	struct rte_mbuf *rxm;
 	struct rte_eth_dev *dev;
@@ -901,32 +1595,88 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 	uint16_t pkt_len;
 	uint16_t nb_rx;
 	uint16_t rx_id;
-	int num;                        /* num of desc in ring */
 	int ret;
 
 	nb_rx = 0;
 	nb_rx_bd = 0;
 	rxq = rx_queue;
-	dev = &rte_eth_devices[rxq->port_id];
 
-	rx_id = rxq->next_to_clean;
+	rx_id = rxq->next_to_use;
 	rx_ring = rxq->rx_ring;
+	sw_ring = rxq->sw_ring;
 	first_seg = rxq->pkt_first_seg;
 	last_seg = rxq->pkt_last_seg;
-	sw_ring = rxq->sw_ring;
 
-	/* Get num of packets in descriptor ring */
-	num = hns3_read_dev(rxq, HNS3_RING_RX_FBDNUM_REG);
-	while (nb_rx_bd < num && nb_rx < nb_pkts) {
+	while (nb_rx < nb_pkts) {
 		rxdp = &rx_ring[rx_id];
 		bd_base_info = rte_le_to_cpu_32(rxdp->rx.bd_base_info);
-		if (unlikely(!hns3_get_bit(bd_base_info, HNS3_RXD_VLD_B))) {
-			rxq->non_vld_descs++;
+		if (unlikely(!hns3_get_bit(bd_base_info, HNS3_RXD_VLD_B)))
 			break;
-		}
+		/*
+		 * The interactive process between software and hardware of
+		 * receiving a new packet in hns3 network engine:
+		 * 1. Hardware network engine firstly writes the packet content
+		 *    to the memory pointed by the 'addr' field of the Rx Buffer
+		 *    Descriptor, secondly fills the result of parsing the
+		 *    packet include the valid field into the Rx Buffer
+		 *    Descriptor in one write operation.
+		 * 2. Driver reads the Rx BD's valid field in the loop to check
+		 *    whether it's valid, if valid then assign a new address to
+		 *    the addr field, clear the valid field, get the other
+		 *    information of the packet by parsing Rx BD's other fields,
+		 *    finally write back the number of Rx BDs processed by the
+		 *    driver to the HNS3_RING_RX_HEAD_REG register to inform
+		 *    hardware.
+		 * In the above process, the ordering is very important. We must
+		 * make sure that CPU read Rx BD's other fields only after the
+		 * Rx BD is valid.
+		 *
+		 * There are two type of re-ordering: compiler re-ordering and
+		 * CPU re-ordering under the ARMv8 architecture.
+		 * 1. we use volatile to deal with compiler re-ordering, so you
+		 *    can see that rx_ring/rxdp defined with volatile.
+		 * 2. we commonly use memory barrier to deal with CPU
+		 *    re-ordering, but the cost is high.
+		 *
+		 * In order to solve the high cost of using memory barrier, we
+		 * use the data dependency order under the ARMv8 architecture,
+		 * for example:
+		 *      instr01: load A
+		 *      instr02: load B <- A
+		 * the instr02 will always execute after instr01.
+		 *
+		 * To construct the data dependency ordering, we use the
+		 * following assignment:
+		 *      rxd = rxdp[(bd_base_info & (1u << HNS3_RXD_VLD_B)) -
+		 *                 (1u<<HNS3_RXD_VLD_B)]
+		 * Using gcc compiler under the ARMv8 architecture, the related
+		 * assembly code example as follows:
+		 * note: (1u << HNS3_RXD_VLD_B) equal 0x10
+		 *      instr01: ldr w26, [x22, #28]  --read bd_base_info
+		 *      instr02: and w0, w26, #0x10   --calc bd_base_info & 0x10
+		 *      instr03: sub w0, w0, #0x10    --calc (bd_base_info &
+		 *                                            0x10) - 0x10
+		 *      instr04: add x0, x22, x0, lsl #5 --calc copy source addr
+		 *      instr05: ldp x2, x3, [x0]
+		 *      instr06: stp x2, x3, [x29, #256] --copy BD's [0 ~ 15]B
+		 *      instr07: ldp x4, x5, [x0, #16]
+		 *      instr08: stp x4, x5, [x29, #272] --copy BD's [16 ~ 31]B
+		 * the instr05~08 depend on x0's value, x0 depent on w26's
+		 * value, the w26 is the bd_base_info, this form the data
+		 * dependency ordering.
+		 * note: if BD is valid, (bd_base_info & (1u<<HNS3_RXD_VLD_B)) -
+		 *       (1u<<HNS3_RXD_VLD_B) will always zero, so the
+		 *       assignment is correct.
+		 *
+		 * So we use the data dependency ordering instead of memory
+		 * barrier to improve receive performance.
+		 */
+		rxd = rxdp[(bd_base_info & (1u << HNS3_RXD_VLD_B)) -
+			   (1u << HNS3_RXD_VLD_B)];
 
 		nmb = rte_mbuf_raw_alloc(rxq->mb_pool);
 		if (unlikely(nmb == NULL)) {
+			dev = &rte_eth_devices[rxq->port_id];
 			dev->data->rx_mbuf_alloc_failed++;
 			break;
 		}
@@ -934,7 +1684,7 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		nb_rx_bd++;
 		rxe = &sw_ring[rx_id];
 		rx_id++;
-		if (rx_id == rxq->nb_rx_desc)
+		if (unlikely(rx_id == rxq->nb_rx_desc))
 			rx_id = 0;
 
 		rte_prefetch0(sw_ring[rx_id].mbuf);
@@ -947,14 +1697,13 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		rxe->mbuf = nmb;
 
 		dma_addr = rte_cpu_to_le_64(rte_mbuf_data_iova_default(nmb));
-		rxdp->addr = dma_addr;
 		rxdp->rx.bd_base_info = 0;
+		rxdp->addr = dma_addr;
 
-		rte_cio_rmb();
 		/* Load remained descriptor data and extract necessary fields */
-		data_len = (uint16_t)(rte_le_to_cpu_16(rxdp->rx.size));
-		l234_info = rte_le_to_cpu_32(rxdp->rx.l234_info);
-		ol_info = rte_le_to_cpu_32(rxdp->rx.ol_info);
+		data_len = (uint16_t)(rte_le_to_cpu_16(rxd.rx.size));
+		l234_info = rte_le_to_cpu_32(rxd.rx.l234_info);
+		ol_info = rte_le_to_cpu_32(rxd.rx.ol_info);
 
 		if (first_seg == NULL) {
 			first_seg = rxm;
@@ -973,14 +1722,14 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		}
 
 		/* The last buffer of the received packet */
-		pkt_len = (uint16_t)(rte_le_to_cpu_16(rxdp->rx.pkt_len));
+		pkt_len = (uint16_t)(rte_le_to_cpu_16(rxd.rx.pkt_len));
 		first_seg->pkt_len = pkt_len;
 		first_seg->port = rxq->port_id;
-		first_seg->hash.rss = rte_le_to_cpu_32(rxdp->rx.rss_hash);
-		first_seg->ol_flags |= PKT_RX_RSS_HASH;
+		first_seg->hash.rss = rte_le_to_cpu_32(rxd.rx.rss_hash);
+		first_seg->ol_flags = PKT_RX_RSS_HASH;
 		if (unlikely(hns3_get_bit(bd_base_info, HNS3_RXD_LUM_B))) {
 			first_seg->hash.fdir.hi =
-				rte_le_to_cpu_32(rxdp->rx.fd_id);
+				rte_le_to_cpu_32(rxd.rx.fd_id);
 			first_seg->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
 		}
 		rxm->next = NULL;
@@ -994,12 +1743,11 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 								  ol_info);
 
 		if (bd_base_info & BIT(HNS3_RXD_L3L4P_B))
-			hns3_rx_set_cksum_flag(rxm, first_seg->packet_type,
+			hns3_rx_set_cksum_flag(first_seg,
+					       first_seg->packet_type,
 					       cksum_err);
+		hns3_rxd_to_vlan_tci(rxq, first_seg, l234_info, &rxd);
 
-		first_seg->vlan_tci = rte_le_to_cpu_16(rxdp->rx.vlan_tag);
-		first_seg->vlan_tci_outer =
-			rte_le_to_cpu_16(rxdp->rx.ot_vlan_tag);
 		rx_pkts[nb_rx++] = first_seg;
 		first_seg = NULL;
 		continue;
@@ -1008,10 +1756,15 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		first_seg = NULL;
 	}
 
-	rxq->next_to_clean = rx_id;
+	rxq->next_to_use = rx_id;
 	rxq->pkt_first_seg = first_seg;
 	rxq->pkt_last_seg = last_seg;
-	hns3_clean_rx_buffers(rxq, nb_rx_bd);
+
+	rxq->rx_free_hold += nb_rx_bd;
+	if (rxq->rx_free_hold > rxq->rx_free_thresh) {
+		hns3_write_reg_opt(rxq->io_head_reg, rxq->rx_free_hold);
+		rxq->rx_free_hold = 0;
+	}
 
 	return nb_rx;
 }
@@ -1021,14 +1774,10 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		    unsigned int socket_id, const struct rte_eth_txconf *conf)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
-	const struct rte_memzone *tx_mz;
 	struct hns3_hw *hw = &hns->hw;
+	struct hns3_queue_info q_info;
 	struct hns3_tx_queue *txq;
-	struct hns3_desc *desc;
-	unsigned int desc_size = sizeof(struct hns3_desc);
-	unsigned int tx_desc;
 	int tx_entry_len;
-	int i;
 
 	if (dev->data->dev_started) {
 		hns3_err(hw, "tx_queue_setup after dev_start no supported");
@@ -1047,17 +1796,19 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		dev->data->tx_queues[idx] = NULL;
 	}
 
-	txq = rte_zmalloc_socket("hns3 TX queue", sizeof(struct hns3_tx_queue),
-				 RTE_CACHE_LINE_SIZE, socket_id);
+	q_info.idx = idx;
+	q_info.socket_id = socket_id;
+	q_info.nb_desc = nb_desc;
+	q_info.type = "hns3 TX queue";
+	q_info.ring_name = "tx_ring";
+	txq = hns3_alloc_txq_and_dma_zone(dev, &q_info);
 	if (txq == NULL) {
-		hns3_err(hw, "Failed to allocate memory for tx queue!");
+		hns3_err(hw,
+			 "Failed to alloc mem and reserve DMA mem for tx ring!");
 		return -ENOMEM;
 	}
 
-	txq->nb_tx_desc = nb_desc;
-	txq->queue_id = idx;
 	txq->tx_deferred_start = conf->tx_deferred_start;
-
 	tx_entry_len = sizeof(struct hns3_entry) * txq->nb_tx_desc;
 	txq->sw_ring = rte_zmalloc_socket("hns3 TX sw ring", tx_entry_len,
 					  RTE_CACHE_LINE_SIZE, socket_id);
@@ -1067,35 +1818,12 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 		return -ENOMEM;
 	}
 
-	/* Allocate tx ring hardware descriptors. */
-	tx_desc = txq->nb_tx_desc * desc_size;
-	tx_mz = rte_eth_dma_zone_reserve(dev, "tx_ring", idx, tx_desc,
-					 HNS3_RING_BASE_ALIGN, socket_id);
-	if (tx_mz == NULL) {
-		hns3_err(hw, "Failed to reserve DMA memory for No.%d tx ring!",
-			 idx);
-		hns3_tx_queue_release(txq);
-		return -ENOMEM;
-	}
-	txq->mz = tx_mz;
-	txq->tx_ring = (struct hns3_desc *)tx_mz->addr;
-	txq->tx_ring_phys_addr = tx_mz->iova;
-
-	hns3_dbg(hw, "No.%d tx descriptors iova 0x%" PRIx64, idx,
-		 txq->tx_ring_phys_addr);
-
-	/* Clear tx bd */
-	desc = txq->tx_ring;
-	for (i = 0; i < txq->nb_tx_desc; i++) {
-		desc->tx.tp_fe_sc_vld_ra_ri = 0;
-		desc++;
-	}
-
 	txq->hns = hns;
 	txq->next_to_use = 0;
 	txq->next_to_clean = 0;
-	txq->tx_bd_ready   = txq->nb_tx_desc;
+	txq->tx_bd_ready = txq->nb_tx_desc - 1;
 	txq->port_id = dev->data->port_id;
+	txq->pvid_state = hw->port_base_vlan_cfg.state;
 	txq->configured = true;
 	txq->io_base = (void *)((char *)hw->io_base + HNS3_TQP_REG_OFFSET +
 				idx * HNS3_TQP_REG_SIZE);
@@ -1106,19 +1834,6 @@ hns3_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc,
 	return 0;
 }
 
-static inline int
-tx_ring_dist(struct hns3_tx_queue *txq, int begin, int end)
-{
-	return (end - begin + txq->nb_tx_desc) % txq->nb_tx_desc;
-}
-
-static inline int
-tx_ring_space(struct hns3_tx_queue *txq)
-{
-	return txq->nb_tx_desc -
-		tx_ring_dist(txq, txq->next_to_clean, txq->next_to_use) - 1;
-}
-
 static inline void
 hns3_queue_xmit(struct hns3_tx_queue *txq, uint32_t buf_num)
 {
@@ -1137,11 +1852,10 @@ hns3_tx_free_useless_buffer(struct hns3_tx_queue *txq)
 	struct rte_mbuf *mbuf;
 
 	while ((!hns3_get_bit(desc->tx.tp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B)) &&
-		(tx_next_use != tx_next_clean || tx_bd_ready < tx_bd_max)) {
+		tx_next_use != tx_next_clean) {
 		mbuf = tx_bak_pkt->mbuf;
 		if (mbuf) {
-			mbuf->next = NULL;
-			rte_pktmbuf_free(mbuf);
+			rte_pktmbuf_free_seg(mbuf);
 			tx_bak_pkt->mbuf = NULL;
 		}
 
@@ -1243,6 +1957,20 @@ hns3_tx_alloc_mbufs(struct hns3_tx_queue *txq, struct rte_mempool *mb_pool,
 	return 0;
 }
 
+static inline void
+hns3_pktmbuf_copy_hdr(struct rte_mbuf *new_pkt, struct rte_mbuf *old_pkt)
+{
+	new_pkt->ol_flags = old_pkt->ol_flags;
+	new_pkt->pkt_len = rte_pktmbuf_pkt_len(old_pkt);
+	new_pkt->outer_l2_len = old_pkt->outer_l2_len;
+	new_pkt->outer_l3_len = old_pkt->outer_l3_len;
+	new_pkt->l2_len = old_pkt->l2_len;
+	new_pkt->l3_len = old_pkt->l3_len;
+	new_pkt->l4_len = old_pkt->l4_len;
+	new_pkt->vlan_tci_outer = old_pkt->vlan_tci_outer;
+	new_pkt->vlan_tci = old_pkt->vlan_tci;
+}
+
 static int
 hns3_reassemble_tx_pkts(void *tx_queue, struct rte_mbuf *tx_pkt,
 			struct rte_mbuf **new_pkt)
@@ -1266,9 +1994,11 @@ hns3_reassemble_tx_pkts(void *tx_queue, struct rte_mbuf *tx_pkt,
 
 	mb_pool = tx_pkt->pool;
 	buf_size = tx_pkt->buf_len - RTE_PKTMBUF_HEADROOM;
-	nb_new_buf = (tx_pkt->pkt_len - 1) / buf_size + 1;
+	nb_new_buf = (rte_pktmbuf_pkt_len(tx_pkt) - 1) / buf_size + 1;
+	if (nb_new_buf > HNS3_MAX_TX_BD_PER_PKT)
+		return -EINVAL;
 
-	last_buf_len = tx_pkt->pkt_len % buf_size;
+	last_buf_len = rte_pktmbuf_pkt_len(tx_pkt) % buf_size;
 	if (last_buf_len == 0)
 		last_buf_len = buf_size;
 
@@ -1280,7 +2010,7 @@ hns3_reassemble_tx_pkts(void *tx_queue, struct rte_mbuf *tx_pkt,
 	/* Copy the original packet content to the new mbufs */
 	temp = tx_pkt;
 	s = rte_pktmbuf_mtod(temp, char *);
-	len_s = temp->data_len;
+	len_s = rte_pktmbuf_data_len(temp);
 	temp_new = new_mbuf;
 	for (i = 0; i < nb_new_buf; i++) {
 		d = rte_pktmbuf_mtod(temp_new, char *);
@@ -1303,13 +2033,14 @@ hns3_reassemble_tx_pkts(void *tx_queue, struct rte_mbuf *tx_pkt,
 				if (temp == NULL)
 					break;
 				s = rte_pktmbuf_mtod(temp, char *);
-				len_s = temp->data_len;
+				len_s = rte_pktmbuf_data_len(temp);
 			}
 		}
 
 		temp_new->data_len = buf_len;
 		temp_new = temp_new->next;
 	}
+	hns3_pktmbuf_copy_hdr(new_mbuf, tx_pkt);
 
 	/* free original mbufs */
 	rte_pktmbuf_free(tx_pkt);
@@ -1320,180 +2051,211 @@ hns3_reassemble_tx_pkts(void *tx_queue, struct rte_mbuf *tx_pkt,
 }
 
 static void
-hns3_parse_outer_params(uint64_t ol_flags, uint32_t *ol_type_vlan_len_msec)
+hns3_parse_outer_params(struct rte_mbuf *m, uint32_t *ol_type_vlan_len_msec)
 {
 	uint32_t tmp = *ol_type_vlan_len_msec;
+	uint64_t ol_flags = m->ol_flags;
 
 	/* (outer) IP header type */
 	if (ol_flags & PKT_TX_OUTER_IPV4) {
-		/* OL3 header size, defined in 4 bytes */
-		hns3_set_field(tmp, HNS3_TXD_L3LEN_M, HNS3_TXD_L3LEN_S,
-			       sizeof(struct rte_ipv4_hdr) >> HNS3_L3_LEN_UNIT);
 		if (ol_flags & PKT_TX_OUTER_IP_CKSUM)
-			hns3_set_field(tmp, HNS3_TXD_OL3T_M,
-				       HNS3_TXD_OL3T_S, HNS3_OL3T_IPV4_CSUM);
+			tmp |= hns3_gen_field_val(HNS3_TXD_OL3T_M,
+					HNS3_TXD_OL3T_S, HNS3_OL3T_IPV4_CSUM);
 		else
-			hns3_set_field(tmp, HNS3_TXD_OL3T_M, HNS3_TXD_OL3T_S,
-				       HNS3_OL3T_IPV4_NO_CSUM);
+			tmp |= hns3_gen_field_val(HNS3_TXD_OL3T_M,
+				HNS3_TXD_OL3T_S, HNS3_OL3T_IPV4_NO_CSUM);
 	} else if (ol_flags & PKT_TX_OUTER_IPV6) {
-		hns3_set_field(tmp, HNS3_TXD_OL3T_M, HNS3_TXD_OL3T_S,
-			       HNS3_OL3T_IPV6);
-		/* OL3 header size, defined in 4 bytes */
-		hns3_set_field(tmp, HNS3_TXD_L3LEN_M, HNS3_TXD_L3LEN_S,
-			       sizeof(struct rte_ipv6_hdr) >> HNS3_L3_LEN_UNIT);
+		tmp |= hns3_gen_field_val(HNS3_TXD_OL3T_M, HNS3_TXD_OL3T_S,
+					HNS3_OL3T_IPV6);
 	}
-
+	/* OL3 header size, defined in 4 bytes */
+	tmp |= hns3_gen_field_val(HNS3_TXD_L3LEN_M, HNS3_TXD_L3LEN_S,
+				m->outer_l3_len >> HNS3_L3_LEN_UNIT);
 	*ol_type_vlan_len_msec = tmp;
 }
 
 static int
-hns3_parse_inner_params(uint64_t ol_flags, uint32_t *ol_type_vlan_len_msec,
-			struct rte_net_hdr_lens *hdr_lens)
+hns3_parse_inner_params(struct rte_mbuf *m, uint32_t *ol_type_vlan_len_msec,
+			uint32_t *type_cs_vlan_tso_len)
 {
-	uint32_t tmp = *ol_type_vlan_len_msec;
-	uint8_t l4_len;
-
-	/* OL2 header size, defined in 2 bytes */
-	hns3_set_field(tmp, HNS3_TXD_L2LEN_M, HNS3_TXD_L2LEN_S,
-		       sizeof(struct rte_ether_hdr) >> HNS3_L2_LEN_UNIT);
+#define HNS3_NVGRE_HLEN 8
+	uint32_t tmp_outer = *ol_type_vlan_len_msec;
+	uint32_t tmp_inner = *type_cs_vlan_tso_len;
+	uint64_t ol_flags = m->ol_flags;
+	uint16_t inner_l2_len;
 
-	/* L4TUNT: L4 Tunneling Type */
 	switch (ol_flags & PKT_TX_TUNNEL_MASK) {
 	case PKT_TX_TUNNEL_GENEVE:
 	case PKT_TX_TUNNEL_VXLAN:
-		/* MAC in UDP tunnelling packet, include VxLAN */
-		hns3_set_field(tmp, HNS3_TXD_TUNTYPE_M, HNS3_TXD_TUNTYPE_S,
-			       HNS3_TUN_MAC_IN_UDP);
+		/* MAC in UDP tunnelling packet, include VxLAN and GENEVE */
+		tmp_outer |= hns3_gen_field_val(HNS3_TXD_TUNTYPE_M,
+				HNS3_TXD_TUNTYPE_S, HNS3_TUN_MAC_IN_UDP);
 		/*
-		 * OL4 header size, defined in 4 Bytes, it contains outer
-		 * L4(UDP) length and tunneling length.
+		 * The inner l2 length of mbuf is the sum of outer l4 length,
+		 * tunneling header length and inner l2 length for a tunnel
+		 * packect. But in hns3 tx descriptor, the tunneling header
+		 * length is contained in the field of outer L4 length.
+		 * Therefore, driver need to calculate the outer L4 length and
+		 * inner L2 length.
 		 */
-		hns3_set_field(tmp, HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
-			       (uint8_t)RTE_ETHER_VXLAN_HLEN >>
-			       HNS3_L4_LEN_UNIT);
+		tmp_outer |= hns3_gen_field_val(HNS3_TXD_L4LEN_M,
+						HNS3_TXD_L4LEN_S,
+						(uint8_t)RTE_ETHER_VXLAN_HLEN >>
+						HNS3_L4_LEN_UNIT);
+
+		inner_l2_len = m->l2_len - RTE_ETHER_VXLAN_HLEN;
 		break;
 	case PKT_TX_TUNNEL_GRE:
-		hns3_set_field(tmp, HNS3_TXD_TUNTYPE_M, HNS3_TXD_TUNTYPE_S,
-			       HNS3_TUN_NVGRE);
+		tmp_outer |= hns3_gen_field_val(HNS3_TXD_TUNTYPE_M,
+					HNS3_TXD_TUNTYPE_S, HNS3_TUN_NVGRE);
 		/*
-		 * OL4 header size, defined in 4 Bytes, it contains outer
-		 * L4(GRE) length and tunneling length.
+		 * For NVGRE tunnel packect, the outer L4 is empty. So only
+		 * fill the NVGRE header length to the outer L4 field.
 		 */
-		l4_len = hdr_lens->l4_len + hdr_lens->tunnel_len;
-		hns3_set_field(tmp, HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
-			       l4_len >> HNS3_L4_LEN_UNIT);
+		tmp_outer |= hns3_gen_field_val(HNS3_TXD_L4LEN_M,
+				HNS3_TXD_L4LEN_S,
+				(uint8_t)HNS3_NVGRE_HLEN >> HNS3_L4_LEN_UNIT);
+
+		inner_l2_len = m->l2_len - HNS3_NVGRE_HLEN;
 		break;
 	default:
 		/* For non UDP / GRE tunneling, drop the tunnel packet */
 		return -EINVAL;
 	}
 
-	*ol_type_vlan_len_msec = tmp;
+	tmp_inner |= hns3_gen_field_val(HNS3_TXD_L2LEN_M, HNS3_TXD_L2LEN_S,
+					inner_l2_len >> HNS3_L2_LEN_UNIT);
+	/* OL2 header size, defined in 2 bytes */
+	tmp_outer |= hns3_gen_field_val(HNS3_TXD_L2LEN_M, HNS3_TXD_L2LEN_S,
+					m->outer_l2_len >> HNS3_L2_LEN_UNIT);
+
+	*type_cs_vlan_tso_len = tmp_inner;
+	*ol_type_vlan_len_msec = tmp_outer;
 
 	return 0;
 }
 
 static int
-hns3_parse_tunneling_params(struct hns3_tx_queue *txq, uint16_t tx_desc_id,
-			    uint64_t ol_flags,
-			    struct rte_net_hdr_lens *hdr_lens)
+hns3_parse_tunneling_params(struct hns3_tx_queue *txq, struct rte_mbuf *m,
+			    uint16_t tx_desc_id)
 {
 	struct hns3_desc *tx_ring = txq->tx_ring;
 	struct hns3_desc *desc = &tx_ring[tx_desc_id];
-	uint32_t value = 0;
+	uint32_t tmp_outer = 0;
+	uint32_t tmp_inner = 0;
 	int ret;
 
-	hns3_parse_outer_params(ol_flags, &value);
-	ret = hns3_parse_inner_params(ol_flags, &value, hdr_lens);
-	if (ret)
-		return -EINVAL;
+	/*
+	 * The tunnel header is contained in the inner L2 header field of the
+	 * mbuf, but for hns3 descriptor, it is contained in the outer L4. So,
+	 * there is a need that switching between them. To avoid multiple
+	 * calculations, the length of the L2 header include the outer and
+	 * inner, will be filled during the parsing of tunnel packects.
+	 */
+	if (!(m->ol_flags & PKT_TX_TUNNEL_MASK)) {
+		/*
+		 * For non tunnel type the tunnel type id is 0, so no need to
+		 * assign a value to it. Only the inner(normal) L2 header length
+		 * is assigned.
+		 */
+		tmp_inner |= hns3_gen_field_val(HNS3_TXD_L2LEN_M,
+			       HNS3_TXD_L2LEN_S, m->l2_len >> HNS3_L2_LEN_UNIT);
+	} else {
+		/*
+		 * If outer csum is not offload, the outer length may be filled
+		 * with 0. And the length of the outer header is added to the
+		 * inner l2_len. It would lead a cksum error. So driver has to
+		 * calculate the header length.
+		 */
+		if (unlikely(!(m->ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
+					m->outer_l2_len == 0)) {
+			struct rte_net_hdr_lens hdr_len;
+			(void)rte_net_get_ptype(m, &hdr_len,
+					RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK);
+			m->outer_l3_len = hdr_len.l3_len;
+			m->outer_l2_len = hdr_len.l2_len;
+			m->l2_len = m->l2_len - hdr_len.l2_len - hdr_len.l3_len;
+		}
+		hns3_parse_outer_params(m, &tmp_outer);
+		ret = hns3_parse_inner_params(m, &tmp_outer, &tmp_inner);
+		if (ret)
+			return -EINVAL;
+	}
 
-	desc->tx.ol_type_vlan_len_msec |= rte_cpu_to_le_32(value);
+	desc->tx.ol_type_vlan_len_msec = rte_cpu_to_le_32(tmp_outer);
+	desc->tx.type_cs_vlan_tso_len = rte_cpu_to_le_32(tmp_inner);
 
 	return 0;
 }
 
 static void
-hns3_parse_l3_cksum_params(uint64_t ol_flags, uint32_t *type_cs_vlan_tso_len)
+hns3_parse_l3_cksum_params(struct rte_mbuf *m, uint32_t *type_cs_vlan_tso_len)
 {
+	uint64_t ol_flags = m->ol_flags;
+	uint32_t l3_type;
 	uint32_t tmp;
 
+	tmp = *type_cs_vlan_tso_len;
+	if (ol_flags & PKT_TX_IPV4)
+		l3_type = HNS3_L3T_IPV4;
+	else if (ol_flags & PKT_TX_IPV6)
+		l3_type = HNS3_L3T_IPV6;
+	else
+		l3_type = HNS3_L3T_NONE;
+
+	/* inner(/normal) L3 header size, defined in 4 bytes */
+	tmp |= hns3_gen_field_val(HNS3_TXD_L3LEN_M, HNS3_TXD_L3LEN_S,
+					m->l3_len >> HNS3_L3_LEN_UNIT);
+
+	tmp |= hns3_gen_field_val(HNS3_TXD_L3T_M, HNS3_TXD_L3T_S, l3_type);
+
 	/* Enable L3 checksum offloads */
-	if (ol_flags & PKT_TX_IPV4) {
-		tmp = *type_cs_vlan_tso_len;
-		hns3_set_field(tmp, HNS3_TXD_L3T_M, HNS3_TXD_L3T_S,
-			       HNS3_L3T_IPV4);
-		/* inner(/normal) L3 header size, defined in 4 bytes */
-		hns3_set_field(tmp, HNS3_TXD_L3LEN_M, HNS3_TXD_L3LEN_S,
-			       sizeof(struct rte_ipv4_hdr) >> HNS3_L3_LEN_UNIT);
-		if (ol_flags & PKT_TX_IP_CKSUM)
-			hns3_set_bit(tmp, HNS3_TXD_L3CS_B, 1);
-		*type_cs_vlan_tso_len = tmp;
-	} else if (ol_flags & PKT_TX_IPV6) {
-		tmp = *type_cs_vlan_tso_len;
-		/* L3T, IPv6 don't do checksum */
-		hns3_set_field(tmp, HNS3_TXD_L3T_M, HNS3_TXD_L3T_S,
-			       HNS3_L3T_IPV6);
-		/* inner(/normal) L3 header size, defined in 4 bytes */
-		hns3_set_field(tmp, HNS3_TXD_L3LEN_M, HNS3_TXD_L3LEN_S,
-			       sizeof(struct rte_ipv6_hdr) >> HNS3_L3_LEN_UNIT);
-		*type_cs_vlan_tso_len = tmp;
-	}
+	if (ol_flags & PKT_TX_IP_CKSUM)
+		tmp |= BIT(HNS3_TXD_L3CS_B);
+	*type_cs_vlan_tso_len = tmp;
 }
 
 static void
-hns3_parse_l4_cksum_params(uint64_t ol_flags, uint32_t *type_cs_vlan_tso_len)
+hns3_parse_l4_cksum_params(struct rte_mbuf *m, uint32_t *type_cs_vlan_tso_len)
 {
+	uint64_t ol_flags = m->ol_flags;
 	uint32_t tmp;
-
 	/* Enable L4 checksum offloads */
 	switch (ol_flags & PKT_TX_L4_MASK) {
 	case PKT_TX_TCP_CKSUM:
 		tmp = *type_cs_vlan_tso_len;
-		hns3_set_field(tmp, HNS3_TXD_L4T_M, HNS3_TXD_L4T_S,
-			       HNS3_L4T_TCP);
-		hns3_set_bit(tmp, HNS3_TXD_L4CS_B, 1);
-		hns3_set_field(tmp, HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
-			       sizeof(struct rte_tcp_hdr) >> HNS3_L4_LEN_UNIT);
-		*type_cs_vlan_tso_len = tmp;
+		tmp |= hns3_gen_field_val(HNS3_TXD_L4T_M, HNS3_TXD_L4T_S,
+					HNS3_L4T_TCP);
 		break;
 	case PKT_TX_UDP_CKSUM:
 		tmp = *type_cs_vlan_tso_len;
-		hns3_set_field(tmp, HNS3_TXD_L4T_M, HNS3_TXD_L4T_S,
-			       HNS3_L4T_UDP);
-		hns3_set_bit(tmp, HNS3_TXD_L4CS_B, 1);
-		hns3_set_field(tmp, HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
-			       sizeof(struct rte_udp_hdr) >> HNS3_L4_LEN_UNIT);
-		*type_cs_vlan_tso_len = tmp;
+		tmp |= hns3_gen_field_val(HNS3_TXD_L4T_M, HNS3_TXD_L4T_S,
+					HNS3_L4T_UDP);
 		break;
 	case PKT_TX_SCTP_CKSUM:
 		tmp = *type_cs_vlan_tso_len;
-		hns3_set_field(tmp, HNS3_TXD_L4T_M, HNS3_TXD_L4T_S,
-			       HNS3_L4T_SCTP);
-		hns3_set_bit(tmp, HNS3_TXD_L4CS_B, 1);
-		hns3_set_field(tmp, HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
-			       sizeof(struct rte_sctp_hdr) >> HNS3_L4_LEN_UNIT);
-		*type_cs_vlan_tso_len = tmp;
+		tmp |= hns3_gen_field_val(HNS3_TXD_L4T_M, HNS3_TXD_L4T_S,
+					HNS3_L4T_SCTP);
 		break;
 	default:
-		break;
+		return;
 	}
+	tmp |= BIT(HNS3_TXD_L4CS_B);
+	tmp |= hns3_gen_field_val(HNS3_TXD_L4LEN_M, HNS3_TXD_L4LEN_S,
+					m->l4_len >> HNS3_L4_LEN_UNIT);
+	*type_cs_vlan_tso_len = tmp;
 }
 
 static void
-hns3_txd_enable_checksum(struct hns3_tx_queue *txq, uint16_t tx_desc_id,
-			 uint64_t ol_flags)
+hns3_txd_enable_checksum(struct hns3_tx_queue *txq, struct rte_mbuf *m,
+			 uint16_t tx_desc_id)
 {
 	struct hns3_desc *tx_ring = txq->tx_ring;
 	struct hns3_desc *desc = &tx_ring[tx_desc_id];
 	uint32_t value = 0;
 
-	/* inner(/normal) L2 header size, defined in 2 bytes */
-	hns3_set_field(value, HNS3_TXD_L2LEN_M, HNS3_TXD_L2LEN_S,
-		       sizeof(struct rte_ether_hdr) >> HNS3_L2_LEN_UNIT);
-
-	hns3_parse_l3_cksum_params(ol_flags, &value);
-	hns3_parse_l4_cksum_params(ol_flags, &value);
+	hns3_parse_l3_cksum_params(m, &value);
+	hns3_parse_l4_cksum_params(m, &value);
 
 	desc->tx.type_cs_vlan_tso_len |= rte_cpu_to_le_32(value);
 }
@@ -1509,12 +2271,6 @@ hns3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
 	for (i = 0; i < nb_pkts; i++) {
 		m = tx_pkts[i];
 
-		/* check the size of packet */
-		if (m->pkt_len < HNS3_MIN_FRAME_LEN) {
-			rte_errno = EINVAL;
-			return i;
-		}
-
 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
 		ret = rte_validate_tx_offload(m);
 		if (ret != 0) {
@@ -1534,18 +2290,23 @@ hns3_prep_pkts(__rte_unused void *tx_queue, struct rte_mbuf **tx_pkts,
 
 static int
 hns3_parse_cksum(struct hns3_tx_queue *txq, uint16_t tx_desc_id,
-		 const struct rte_mbuf *m, struct rte_net_hdr_lens *hdr_lens)
+		 struct rte_mbuf *m)
 {
-	/* Fill in tunneling parameters if necessary */
-	if (m->ol_flags & PKT_TX_TUNNEL_MASK) {
-		(void)rte_net_get_ptype(m, hdr_lens, RTE_PTYPE_ALL_MASK);
-		if (hns3_parse_tunneling_params(txq, tx_desc_id, m->ol_flags,
-						hdr_lens))
+	struct hns3_desc *tx_ring = txq->tx_ring;
+	struct hns3_desc *desc = &tx_ring[tx_desc_id];
+
+	/* Enable checksum offloading */
+	if (m->ol_flags & HNS3_TX_CKSUM_OFFLOAD_MASK) {
+		/* Fill in tunneling parameters if necessary */
+		if (hns3_parse_tunneling_params(txq, m, tx_desc_id))
 			return -EINVAL;
+
+		hns3_txd_enable_checksum(txq, m, tx_desc_id);
+	} else {
+		/* clear the control bit */
+		desc->tx.type_cs_vlan_tso_len  = 0;
+		desc->tx.ol_type_vlan_len_msec = 0;
 	}
-	/* Enable checksum offloading */
-	if (m->ol_flags & HNS3_TX_CKSUM_OFFLOAD_MASK)
-		hns3_txd_enable_checksum(txq, tx_desc_id, m->ol_flags);
 
 	return 0;
 }
@@ -1553,17 +2314,13 @@ hns3_parse_cksum(struct hns3_tx_queue *txq, uint16_t tx_desc_id,
 uint16_t
 hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
-	struct rte_net_hdr_lens hdr_lens = {0};
 	struct hns3_tx_queue *txq = tx_queue;
 	struct hns3_entry *tx_bak_pkt;
 	struct rte_mbuf *new_pkt;
 	struct rte_mbuf *tx_pkt;
 	struct rte_mbuf *m_seg;
-	struct rte_mbuf *temp;
 	uint32_t nb_hold = 0;
-	uint16_t tx_next_clean;
 	uint16_t tx_next_use;
-	uint16_t tx_bd_ready;
 	uint16_t tx_pkt_num;
 	uint16_t tx_bd_max;
 	uint16_t nb_buf;
@@ -1572,16 +2329,10 @@ hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 	/* free useless buffer */
 	hns3_tx_free_useless_buffer(txq);
-	tx_bd_ready = txq->tx_bd_ready;
-	if (tx_bd_ready == 0)
-		return 0;
 
-	tx_next_clean = txq->next_to_clean;
 	tx_next_use   = txq->next_to_use;
 	tx_bd_max     = txq->nb_tx_desc;
-	tx_bak_pkt = &txq->sw_ring[tx_next_clean];
-
-	tx_pkt_num = (tx_bd_ready < nb_pkts) ? tx_bd_ready : nb_pkts;
+	tx_pkt_num = nb_pkts;
 
 	/* send packets */
 	tx_bak_pkt = &txq->sw_ring[tx_next_use];
@@ -1590,7 +2341,7 @@ hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 		nb_buf = tx_pkt->nb_segs;
 
-		if (nb_buf > tx_ring_space(txq)) {
+		if (nb_buf > txq->tx_bd_ready) {
 			if (nb_tx == 0)
 				return 0;
 
@@ -1629,15 +2380,14 @@ hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			nb_buf = m_seg->nb_segs;
 		}
 
-		if (hns3_parse_cksum(txq, tx_next_use, m_seg, &hdr_lens))
+		if (hns3_parse_cksum(txq, tx_next_use, m_seg))
 			goto end_of_tx;
 
 		i = 0;
 		do {
 			fill_desc(txq, tx_next_use, m_seg, (i == 0), 0);
-			temp = m_seg->next;
 			tx_bak_pkt->mbuf = m_seg;
-			m_seg = temp;
+			m_seg = m_seg->next;
 			tx_next_use++;
 			tx_bak_pkt++;
 			if (tx_next_use >= tx_bd_max) {
@@ -1650,15 +2400,13 @@ hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 		nb_hold += i;
 		txq->next_to_use = tx_next_use;
+		txq->tx_bd_ready -= i;
 	}
 
 end_of_tx:
 
-	if (likely(nb_tx)) {
+	if (likely(nb_tx))
 		hns3_queue_xmit(txq, nb_hold);
-		txq->next_to_clean = tx_next_clean;
-		txq->tx_bd_ready   = tx_bd_ready - nb_hold;
-	}
 
 	return nb_tx;
 }
diff --git a/dpdk/drivers/net/hns3/hns3_rxtx.h b/dpdk/drivers/net/hns3/hns3_rxtx.h
index daf51f4095..88a75843b3 100644
--- a/dpdk/drivers/net/hns3/hns3_rxtx.h
+++ b/dpdk/drivers/net/hns3/hns3_rxtx.h
@@ -5,11 +5,20 @@
 #ifndef _HNS3_RXTX_H_
 #define _HNS3_RXTX_H_
 
-#define	HNS3_MIN_RING_DESC	32
+#define	HNS3_MIN_RING_DESC	64
 #define	HNS3_MAX_RING_DESC	32768
 #define HNS3_DEFAULT_RING_DESC  1024
 #define	HNS3_ALIGN_RING_DESC	32
 #define HNS3_RING_BASE_ALIGN	128
+#define HNS3_DEFAULT_RX_FREE_THRESH	32
+
+#define HNS3_512_BD_BUF_SIZE	512
+#define HNS3_1K_BD_BUF_SIZE	1024
+#define HNS3_2K_BD_BUF_SIZE	2048
+#define HNS3_4K_BD_BUF_SIZE	4096
+
+#define HNS3_MIN_BD_BUF_SIZE	HNS3_512_BD_BUF_SIZE
+#define HNS3_MAX_BD_BUF_SIZE	HNS3_4K_BD_BUF_SIZE
 
 #define HNS3_BD_SIZE_512_TYPE			0
 #define HNS3_BD_SIZE_1024_TYPE			1
@@ -222,6 +231,7 @@ struct hns3_entry {
 
 struct hns3_rx_queue {
 	void *io_base;
+	volatile void *io_head_reg;
 	struct hns3_adapter *hns;
 	struct rte_mempool *mb_pool;
 	struct hns3_desc *rx_ring;
@@ -235,17 +245,24 @@ struct hns3_rx_queue {
 	uint16_t queue_id;
 	uint16_t port_id;
 	uint16_t nb_rx_desc;
-	uint16_t nb_rx_hold;
-	uint16_t rx_tail;
-	uint16_t next_to_clean;
 	uint16_t next_to_use;
 	uint16_t rx_buf_len;
+	/*
+	 * threshold for the number of BDs waited to passed to hardware. If the
+	 * number exceeds the threshold, driver will pass these BDs to hardware.
+	 */
 	uint16_t rx_free_thresh;
+	uint16_t rx_free_hold;   /* num of BDs waited to passed to hardware */
+
+	/*
+	 * port based vlan configuration state.
+	 * value range: HNS3_PORT_BASE_VLAN_DISABLE / HNS3_PORT_BASE_VLAN_ENABLE
+	 */
+	uint16_t pvid_state;
 
 	bool rx_deferred_start; /* don't start this queue in dev start */
 	bool configured;        /* indicate if rx queue has been configured */
 
-	uint64_t non_vld_descs; /* num of non valid rx descriptors */
 	uint64_t l2_errors;
 	uint64_t pkt_len_errors;
 	uint64_t l3_csum_erros;
@@ -269,19 +286,28 @@ struct hns3_tx_queue {
 	uint16_t next_to_use;
 	uint16_t tx_bd_ready;
 
+	/*
+	 * port based vlan configuration state.
+	 * value range: HNS3_PORT_BASE_VLAN_DISABLE / HNS3_PORT_BASE_VLAN_ENABLE
+	 */
+	uint16_t pvid_state;
+
 	bool tx_deferred_start; /* don't start this queue in dev start */
 	bool configured;        /* indicate if tx queue has been configured */
 };
 
+struct hns3_queue_info {
+	const char *type;   /* point to queue memory name */
+	const char *ring_name;  /* point to hardware ring name */
+	uint16_t idx;
+	uint16_t nb_desc;
+	unsigned int socket_id;
+};
+
 #define HNS3_TX_CKSUM_OFFLOAD_MASK ( \
-	PKT_TX_OUTER_IPV6 | \
-	PKT_TX_OUTER_IPV4 | \
 	PKT_TX_OUTER_IP_CKSUM | \
-	PKT_TX_IPV6 | \
-	PKT_TX_IPV4 | \
 	PKT_TX_IP_CKSUM | \
-	PKT_TX_L4_MASK | \
-	PKT_TX_TUNNEL_MASK)
+	PKT_TX_L4_MASK)
 
 enum hns3_cksum_status {
 	HNS3_CKSUM_NONE = 0,
@@ -295,6 +321,10 @@ void hns3_dev_rx_queue_release(void *queue);
 void hns3_dev_tx_queue_release(void *queue);
 void hns3_free_all_queues(struct rte_eth_dev *dev);
 int hns3_reset_all_queues(struct hns3_adapter *hns);
+void hns3_dev_all_rx_queue_intr_enable(struct hns3_hw *hw, bool en);
+int hns3_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, uint16_t queue_id);
+int hns3_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id);
+void hns3_enable_all_queues(struct hns3_hw *hw, bool en);
 int hns3_start_queues(struct hns3_adapter *hns, bool reset_queue);
 int hns3_stop_queues(struct hns3_adapter *hns, bool reset_queue);
 void hns3_dev_release_mbufs(struct hns3_adapter *hns);
@@ -311,4 +341,12 @@ uint16_t hns3_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 			uint16_t nb_pkts);
 const uint32_t *hns3_dev_supported_ptypes_get(struct rte_eth_dev *dev);
 void hns3_set_rxtx_function(struct rte_eth_dev *eth_dev);
+void hns3_set_queue_intr_gl(struct hns3_hw *hw, uint16_t queue_id,
+			    uint8_t gl_idx, uint16_t gl_value);
+void hns3_set_queue_intr_rl(struct hns3_hw *hw, uint16_t queue_id,
+			    uint16_t rl_value);
+int hns3_set_fake_rx_or_tx_queues(struct rte_eth_dev *dev, uint16_t nb_rx_q,
+				  uint16_t nb_tx_q);
+void hns3_update_all_queues_pvid_state(struct hns3_hw *hw);
+
 #endif /* _HNS3_RXTX_H_ */
diff --git a/dpdk/drivers/net/hns3/hns3_stats.c b/dpdk/drivers/net/hns3/hns3_stats.c
index 9948beb179..d2ef722cfb 100644
--- a/dpdk/drivers/net/hns3/hns3_stats.c
+++ b/dpdk/drivers/net/hns3/hns3_stats.c
@@ -219,8 +219,6 @@ static const struct hns3_xstats_name_offset hns3_reset_stats_strings[] = {
 
 /* The statistic of errors in Rx BD */
 static const struct hns3_xstats_name_offset hns3_rx_bd_error_strings[] = {
-	{"NONE_VALIDATED_DESCRIPTORS",
-		HNS3_RX_BD_ERROR_STATS_FIELD_OFFSET(non_vld_descs)},
 	{"RX_PKT_LEN_ERRORS",
 		HNS3_RX_BD_ERROR_STATS_FIELD_OFFSET(pkt_len_errors)},
 	{"L2_RX_ERRORS",
@@ -492,6 +490,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 		if (ret) {
 			hns3_err(hw, "Failed to reset RX No.%d queue stat: %d",
 				 i, ret);
+			return ret;
 		}
 
 		hns3_cmd_setup_basic_desc(&desc_reset, HNS3_OPC_QUERY_TX_STATUS,
@@ -502,20 +501,19 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 		if (ret) {
 			hns3_err(hw, "Failed to reset TX No.%d queue stat: %d",
 				 i, ret);
+			return ret;
 		}
 	}
 
-	/* Clear Rx BD and Tx error stats */
+	/*
+	 * Clear soft stats of rx error packet which will be dropped
+	 * in driver.
+	 */
 	for (i = 0; i != eth_dev->data->nb_rx_queues; ++i) {
 		rxq = eth_dev->data->rx_queues[i];
 		if (rxq) {
 			rxq->pkt_len_errors = 0;
-			rxq->non_vld_descs = 0;
 			rxq->l2_errors = 0;
-			rxq->l3_csum_erros = 0;
-			rxq->l4_csum_erros = 0;
-			rxq->ol3_csum_erros = 0;
-			rxq->ol4_csum_erros = 0;
 		}
 	}
 
@@ -524,7 +522,7 @@ hns3_stats_reset(struct rte_eth_dev *eth_dev)
 	return 0;
 }
 
-static void
+static int
 hns3_mac_stats_reset(__rte_unused struct rte_eth_dev *dev)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
@@ -533,10 +531,14 @@ hns3_mac_stats_reset(__rte_unused struct rte_eth_dev *dev)
 	int ret;
 
 	ret = hns3_query_update_mac_stats(dev);
-	if (ret)
+	if (ret) {
 		hns3_err(hw, "Clear Mac stats fail : %d", ret);
+		return ret;
+	}
 
 	memset(mac_stats, 0, sizeof(struct hns3_mac_stats));
+
+	return 0;
 }
 
 /* This function calculates the number of xstats based on the current config */
@@ -593,9 +595,9 @@ hns3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	if (!hns->is_vf) {
 		/* Update Mac stats */
 		ret = hns3_query_update_mac_stats(dev);
-		if (ret) {
+		if (ret < 0) {
 			hns3_err(hw, "Update Mac stats fail : %d", ret);
-			return 0;
+			return ret;
 		}
 
 		/* Get MAC stats from hw->hw_xstats.mac_stats struct */
@@ -752,9 +754,13 @@ hns3_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids,
 	char *addr;
 	int ret;
 
-	if (ids == NULL || size < cnt_stats)
+	if (ids == NULL && values == NULL)
 		return cnt_stats;
 
+	if (ids == NULL)
+		if (size < cnt_stats)
+			return cnt_stats;
+
 	/* Update tqp stats by read register */
 	ret = hns3_update_tqp_stats(hw);
 	if (ret) {
@@ -802,6 +808,15 @@ hns3_dev_xstats_get_by_id(struct rte_eth_dev *dev, const uint64_t *ids,
 		}
 	}
 
+	if (ids == NULL && values != NULL) {
+		for (i = 0; i < cnt_stats; i++)
+			memcpy(&values[i], &values_copy[i], sizeof(values[i]));
+
+		rte_free(values_copy);
+
+		return cnt_stats;
+	}
+
 	for (i = 0; i < size; i++) {
 		if (ids[i] >= cnt_stats) {
 			hns3_err(hw, "ids[%d] (%" PRIx64 ") is invalid, "
@@ -850,9 +865,16 @@ hns3_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,
 	uint16_t i, j;
 	uint64_t len;
 
-	if (ids == NULL || xstats_names == NULL)
+	if (xstats_names == NULL)
 		return cnt_stats;
 
+	if (ids == NULL) {
+		if (size < cnt_stats)
+			return cnt_stats;
+
+		return hns3_dev_xstats_get_names(dev, xstats_names, cnt_stats);
+	}
+
 	len = cnt_stats * sizeof(struct rte_eth_xstat_name);
 	xstats_names_copy = rte_zmalloc("hns3_xstats_names", len, 0);
 	if (xstats_names_copy == NULL) {
@@ -911,17 +933,37 @@ hns3_dev_xstats_reset(struct rte_eth_dev *dev)
 {
 	struct hns3_adapter *hns = dev->data->dev_private;
 	struct hns3_pf *pf = &hns->pf;
+	struct hns3_rx_queue *rxq;
+	int ret;
+	int i;
 
 	/* Clear tqp stats */
-	(void)hns3_stats_reset(dev);
+	ret = hns3_stats_reset(dev);
+	if (ret)
+		return ret;
+
 	/* Clear reset stats */
 	memset(&hns->hw.reset.stats, 0, sizeof(struct hns3_reset_stats));
 
+	/* Clear Rx checksum error stats */
+	for (i = 0; i < dev->data->nb_rx_queues; ++i) {
+		rxq = dev->data->rx_queues[i];
+		if (rxq) {
+			rxq->l3_csum_erros = 0;
+			rxq->l4_csum_erros = 0;
+			rxq->ol3_csum_erros = 0;
+			rxq->ol4_csum_erros = 0;
+		}
+	}
+
 	if (hns->is_vf)
 		return 0;
 
 	/* HW registers are cleared on read */
-	hns3_mac_stats_reset(dev);
+	ret = hns3_mac_stats_reset(dev);
+	if (ret)
+		return ret;
+
 	/* Clear error stats */
 	memset(&pf->abn_int_stats, 0, sizeof(struct hns3_err_msix_intr_stats));
 
diff --git a/dpdk/drivers/net/hns3/hns3_stats.h b/dpdk/drivers/net/hns3/hns3_stats.h
index 365bae083d..34c76be21e 100644
--- a/dpdk/drivers/net/hns3/hns3_stats.h
+++ b/dpdk/drivers/net/hns3/hns3_stats.h
@@ -141,8 +141,8 @@ int hns3_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 			      struct rte_eth_xstat_name *xstats_names,
 			      __rte_unused unsigned int size);
 int hns3_dev_xstats_get_by_id(struct rte_eth_dev *dev,
-			      __rte_unused const uint64_t *ids,
-			      __rte_unused uint64_t *values,
+			      const uint64_t *ids,
+			      uint64_t *values,
 			      uint32_t size);
 int hns3_dev_xstats_get_names_by_id(struct rte_eth_dev *dev,
 				    struct rte_eth_xstat_name *xstats_names,
diff --git a/dpdk/drivers/net/i40e/Makefile b/dpdk/drivers/net/i40e/Makefile
index 435eb511ad..4ea58bd9e7 100644
--- a/dpdk/drivers/net/i40e/Makefile
+++ b/dpdk/drivers/net/i40e/Makefile
@@ -72,7 +72,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_dcb.c
 
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_ethdev.c
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_PMD) += i40e_rxtx.c
-ifeq ($(CONFIG_RTE_ARCH_ARM64),y)
+ifneq ($(filter y,$(CONFIG_RTE_ARCH_ARM) $(CONFIG_RTE_ARCH_ARM64)),)
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_INC_VECTOR) += i40e_rxtx_vec_neon.c
 else ifeq ($(CONFIG_RTE_ARCH_PPC_64),y)
 SRCS-$(CONFIG_RTE_LIBRTE_I40E_INC_VECTOR) += i40e_rxtx_vec_altivec.c
diff --git a/dpdk/drivers/net/i40e/base/README b/dpdk/drivers/net/i40e/base/README
index 8a5339cfff..b46593566b 100644
--- a/dpdk/drivers/net/i40e/base/README
+++ b/dpdk/drivers/net/i40e/base/README
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
+ * Copyright(c) 2017-2020 Intel Corporation
  */
 
 Intel® I40E driver
diff --git a/dpdk/drivers/net/i40e/base/i40e_adminq.c b/dpdk/drivers/net/i40e/base/i40e_adminq.c
index 38214a3731..584da0383c 100644
--- a/dpdk/drivers/net/i40e/base/i40e_adminq.c
+++ b/dpdk/drivers/net/i40e/base/i40e_adminq.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "i40e_status.h"
@@ -835,7 +835,7 @@ enum i40e_status_code i40e_asq_send_command(struct i40e_hw *hw,
 	if (val >= hw->aq.num_asq_entries) {
 		i40e_debug(hw, I40E_DEBUG_AQ_MESSAGE,
 			   "AQTX: head overrun at %d\n", val);
-		status = I40E_ERR_QUEUE_EMPTY;
+		status = I40E_ERR_ADMIN_QUEUE_FULL;
 		goto asq_send_command_error;
 	}
 
diff --git a/dpdk/drivers/net/i40e/base/i40e_adminq.h b/dpdk/drivers/net/i40e/base/i40e_adminq.h
index 769d84809e..6ce262ad4b 100644
--- a/dpdk/drivers/net/i40e/base/i40e_adminq.h
+++ b/dpdk/drivers/net/i40e/base/i40e_adminq.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_ADMINQ_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_adminq_cmd.h b/dpdk/drivers/net/i40e/base/i40e_adminq_cmd.h
index b459be9212..48f93313bd 100644
--- a/dpdk/drivers/net/i40e/base/i40e_adminq_cmd.h
+++ b/dpdk/drivers/net/i40e/base/i40e_adminq_cmd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_ADMINQ_CMD_H_
@@ -1215,7 +1215,7 @@ struct i40e_aqc_set_vsi_promiscuous_modes {
 #define I40E_AQC_SET_VSI_PROMISC_BROADCAST	0x04
 #define I40E_AQC_SET_VSI_DEFAULT		0x08
 #define I40E_AQC_SET_VSI_PROMISC_VLAN		0x10
-#define I40E_AQC_SET_VSI_PROMISC_TX		0x8000
+#define I40E_AQC_SET_VSI_PROMISC_RX_ONLY	0x8000
 	__le16	seid;
 #define I40E_AQC_VSI_PROM_CMD_SEID_MASK		0x3FF
 	__le16	vlan_tag;
diff --git a/dpdk/drivers/net/i40e/base/i40e_alloc.h b/dpdk/drivers/net/i40e/base/i40e_alloc.h
index 4fc1860155..ae14e4d932 100644
--- a/dpdk/drivers/net/i40e/base/i40e_alloc.h
+++ b/dpdk/drivers/net/i40e/base/i40e_alloc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_ALLOC_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_common.c b/dpdk/drivers/net/i40e/base/i40e_common.c
index 37911a99e5..50812eb80e 100644
--- a/dpdk/drivers/net/i40e/base/i40e_common.c
+++ b/dpdk/drivers/net/i40e/base/i40e_common.c
@@ -1,7 +1,9 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
+#include <inttypes.h>
+
 #include "i40e_type.h"
 #include "i40e_adminq.h"
 #include "i40e_prototype.h"
@@ -1700,19 +1702,22 @@ enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
 		status = i40e_asq_send_command(hw, &desc, abilities,
 					       abilities_size, cmd_details);
 
-		if (status != I40E_SUCCESS)
-			break;
-
-		if (hw->aq.asq_last_status == I40E_AQ_RC_EIO) {
+		switch (hw->aq.asq_last_status) {
+		case I40E_AQ_RC_EIO:
 			status = I40E_ERR_UNKNOWN_PHY;
 			break;
-		} else if (hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) {
+		case I40E_AQ_RC_EAGAIN:
 			i40e_msec_delay(1);
 			total_delay++;
 			status = I40E_ERR_TIMEOUT;
+			break;
+		/* also covers I40E_AQ_RC_OK */
+		default:
+			break;
 		}
-	} while ((hw->aq.asq_last_status != I40E_AQ_RC_OK) &&
-		 (total_delay < max_delay));
+
+	} while ((hw->aq.asq_last_status == I40E_AQ_RC_EAGAIN) &&
+		(total_delay < max_delay));
 
 	if (status != I40E_SUCCESS)
 		return status;
@@ -2025,8 +2030,8 @@ enum i40e_status_code i40e_aq_get_link_info(struct i40e_hw *hw,
 	     hw->aq.fw_min_ver < 40)) && hw_link_info->phy_type == 0xE)
 		hw_link_info->phy_type = I40E_PHY_TYPE_10GBASE_SFPP_CU;
 
-	if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
-	    hw->aq.api_min_ver >= 7) {
+	if (hw->flags & I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE &&
+	    hw->mac.type != I40E_MAC_X722) {
 		__le32 tmp;
 
 		i40e_memcpy(&tmp, resp->link_type, sizeof(tmp),
@@ -2219,6 +2224,22 @@ enum i40e_status_code i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
 	return status;
 }
 
+/**
+ * i40e_hw_ver_ge
+ * @hw: pointer to the hw struct
+ * @maj: api major value
+ * @min: api minor value
+ *
+ * Assert whether current HW api version is greater/equal than provided.
+ **/
+static bool i40e_hw_ver_ge(struct i40e_hw *hw, u16 maj, u16 min)
+{
+	if (hw->aq.api_maj_ver > maj ||
+	    (hw->aq.api_maj_ver == maj && hw->aq.api_min_ver >= min))
+		return true;
+	return false;
+}
+
 /**
  * i40e_aq_add_vsi
  * @hw: pointer to the hw struct
@@ -2344,18 +2365,16 @@ enum i40e_status_code i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
 
 	if (set) {
 		flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
-		if (rx_only_promisc &&
-		    (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) ||
-		     (hw->aq.api_maj_ver > 1)))
-			flags |= I40E_AQC_SET_VSI_PROMISC_TX;
+		if (rx_only_promisc && i40e_hw_ver_ge(hw, 1, 5))
+			flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
 	}
 
 	cmd->promiscuous_flags = CPU_TO_LE16(flags);
 
 	cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
-	if (((hw->aq.api_maj_ver >= 1) && (hw->aq.api_min_ver >= 5)) ||
-	     (hw->aq.api_maj_ver > 1))
-		cmd->valid_flags |= CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_TX);
+	if (i40e_hw_ver_ge(hw, 1, 5))
+		cmd->valid_flags |=
+			CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
 
 	cmd->seid = CPU_TO_LE16(seid);
 	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
@@ -2487,11 +2506,17 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
 	i40e_fill_default_direct_cmd_desc(&desc,
 					i40e_aqc_opc_set_vsi_promiscuous_modes);
 
-	if (enable)
+	if (enable) {
 		flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
+		if (i40e_hw_ver_ge(hw, 1, 5))
+			flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
+	}
 
 	cmd->promiscuous_flags = CPU_TO_LE16(flags);
 	cmd->valid_flags = CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
+	if (i40e_hw_ver_ge(hw, 1, 5))
+		cmd->valid_flags |=
+			CPU_TO_LE16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
 	cmd->seid = CPU_TO_LE16(seid);
 	cmd->vlan_tag = CPU_TO_LE16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
 
@@ -2883,9 +2908,16 @@ enum i40e_status_code i40e_update_link_info(struct i40e_hw *hw)
 		if (status)
 			return status;
 
-		hw->phy.link_info.req_fec_info =
-			abilities.fec_cfg_curr_mod_ext_info &
-			(I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS);
+		if (abilities.fec_cfg_curr_mod_ext_info &
+		    I40E_AQ_ENABLE_FEC_AUTO)
+			hw->phy.link_info.req_fec_info =
+				(I40E_AQ_REQUEST_FEC_KR |
+				 I40E_AQ_REQUEST_FEC_RS);
+		else
+			hw->phy.link_info.req_fec_info =
+				abilities.fec_cfg_curr_mod_ext_info &
+				(I40E_AQ_REQUEST_FEC_KR |
+				 I40E_AQ_REQUEST_FEC_RS);
 
 		i40e_memcpy(hw->phy.link_info.module_type, &abilities.module_type,
 			sizeof(hw->phy.link_info.module_type), I40E_NONDMA_TO_NONDMA);
@@ -3960,7 +3992,7 @@ STATIC void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
 			p->wr_csr_prot = (u64)number;
 			p->wr_csr_prot |= (u64)logical_id << 32;
 			i40e_debug(hw, I40E_DEBUG_INIT,
-				   "HW Capability: wr_csr_prot = 0x%llX\n\n",
+				   "HW Capability: wr_csr_prot = 0x%" PRIX64 "\n\n",
 				   (p->wr_csr_prot & 0xffff));
 			break;
 		case I40E_AQ_CAP_ID_NVM_MGMT:
@@ -4300,7 +4332,7 @@ enum i40e_status_code i40e_aq_set_lldp_mib(struct i40e_hw *hw,
 
 	cmd->type = mib_type;
 	cmd->length = CPU_TO_LE16(buff_size);
-	cmd->address_high = CPU_TO_LE32(I40E_HI_WORD((u64)buff));
+	cmd->address_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buff));
 	cmd->address_low =  CPU_TO_LE32(I40E_LO_DWORD((u64)buff));
 
 	status = i40e_asq_send_command(hw, &desc, buff, buff_size, cmd_details);
diff --git a/dpdk/drivers/net/i40e/base/i40e_dcb.c b/dpdk/drivers/net/i40e/base/i40e_dcb.c
index a26f82b3a6..5a1f9903a5 100644
--- a/dpdk/drivers/net/i40e/base/i40e_dcb.c
+++ b/dpdk/drivers/net/i40e/base/i40e_dcb.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "i40e_adminq.h"
@@ -1212,7 +1212,8 @@ enum i40e_status_code i40e_set_dcb_config(struct i40e_hw *hw)
 
 /**
  * i40e_dcb_config_to_lldp - Convert Dcbconfig to MIB format
- * @hw: pointer to the hw struct
+ * @lldpmib: pointer to mib to be output
+ * @miblen: pointer to u16 for length of lldpmib
  * @dcbcfg: store for LLDPDU data
  *
  * send DCB configuration to FW
diff --git a/dpdk/drivers/net/i40e/base/i40e_dcb.h b/dpdk/drivers/net/i40e/base/i40e_dcb.h
index 85b0eed3ad..8d36fce430 100644
--- a/dpdk/drivers/net/i40e/base/i40e_dcb.h
+++ b/dpdk/drivers/net/i40e/base/i40e_dcb.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_DCB_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_devids.h b/dpdk/drivers/net/i40e/base/i40e_devids.h
index f3c59bdea9..64cfe2bb26 100644
--- a/dpdk/drivers/net/i40e/base/i40e_devids.h
+++ b/dpdk/drivers/net/i40e/base/i40e_devids.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_DEVIDS_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_diag.c b/dpdk/drivers/net/i40e/base/i40e_diag.c
index 3ccbea4829..b3c4cfd3aa 100644
--- a/dpdk/drivers/net/i40e/base/i40e_diag.c
+++ b/dpdk/drivers/net/i40e/base/i40e_diag.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "i40e_diag.h"
diff --git a/dpdk/drivers/net/i40e/base/i40e_diag.h b/dpdk/drivers/net/i40e/base/i40e_diag.h
index 4434fc960b..cb59285d9c 100644
--- a/dpdk/drivers/net/i40e/base/i40e_diag.h
+++ b/dpdk/drivers/net/i40e/base/i40e_diag.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_DIAG_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_hmc.c b/dpdk/drivers/net/i40e/base/i40e_hmc.c
index 11c9ae2072..a47d6e0d79 100644
--- a/dpdk/drivers/net/i40e/base/i40e_hmc.c
+++ b/dpdk/drivers/net/i40e/base/i40e_hmc.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "i40e_osdep.h"
diff --git a/dpdk/drivers/net/i40e/base/i40e_hmc.h b/dpdk/drivers/net/i40e/base/i40e_hmc.h
index 289264ed99..f9aad7dc31 100644
--- a/dpdk/drivers/net/i40e/base/i40e_hmc.h
+++ b/dpdk/drivers/net/i40e/base/i40e_hmc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_HMC_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_lan_hmc.c b/dpdk/drivers/net/i40e/base/i40e_lan_hmc.c
index 0afee49b13..d3969396f0 100644
--- a/dpdk/drivers/net/i40e/base/i40e_lan_hmc.c
+++ b/dpdk/drivers/net/i40e/base/i40e_lan_hmc.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "i40e_osdep.h"
diff --git a/dpdk/drivers/net/i40e/base/i40e_lan_hmc.h b/dpdk/drivers/net/i40e/base/i40e_lan_hmc.h
index e531ec490a..aa5dceb792 100644
--- a/dpdk/drivers/net/i40e/base/i40e_lan_hmc.h
+++ b/dpdk/drivers/net/i40e/base/i40e_lan_hmc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_LAN_HMC_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_nvm.c b/dpdk/drivers/net/i40e/base/i40e_nvm.c
index 6c8ca87718..16aebd077f 100644
--- a/dpdk/drivers/net/i40e/base/i40e_nvm.c
+++ b/dpdk/drivers/net/i40e/base/i40e_nvm.c
@@ -1,7 +1,9 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
+#include <inttypes.h>
+
 #include "i40e_prototype.h"
 
 /**
@@ -77,7 +79,7 @@ enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw,
 
 	if (ret_code)
 		i40e_debug(hw, I40E_DEBUG_NVM,
-			   "NVM acquire type %d failed time_left=%llu ret=%d aq_err=%d\n",
+			   "NVM acquire type %d failed time_left=%" PRIu64 " ret=%d aq_err=%d\n",
 			   access, time_left, ret_code, hw->aq.asq_last_status);
 
 	if (ret_code && time_left) {
@@ -99,7 +101,7 @@ enum i40e_status_code i40e_acquire_nvm(struct i40e_hw *hw,
 		if (ret_code != I40E_SUCCESS) {
 			hw->nvm.hw_semaphore_timeout = 0;
 			i40e_debug(hw, I40E_DEBUG_NVM,
-				   "NVM acquire timed out, wait %llu ms before trying again. status=%d aq_err=%d\n",
+				   "NVM acquire timed out, wait %" PRIu64 " ms before trying again. status=%d aq_err=%d\n",
 				   time_left, ret_code, hw->aq.asq_last_status);
 		}
 	}
@@ -1203,7 +1205,7 @@ STATIC enum i40e_status_code i40e_nvmupd_state_writing(struct i40e_hw *hw,
 		gtime = rd32(hw, I40E_GLVFGEN_TIMER);
 		if (gtime >= hw->nvm.hw_semaphore_timeout) {
 			i40e_debug(hw, I40E_DEBUG_ALL,
-				   "NVMUPD: write semaphore expired (%d >= %lld), retrying\n",
+				   "NVMUPD: write semaphore expired (%d >= %" PRIu64 "), retrying\n",
 				   gtime, hw->nvm.hw_semaphore_timeout);
 			i40e_release_nvm(hw);
 			status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
diff --git a/dpdk/drivers/net/i40e/base/i40e_osdep.h b/dpdk/drivers/net/i40e/base/i40e_osdep.h
index 8a2d82a8d0..ebd6872400 100644
--- a/dpdk/drivers/net/i40e/base/i40e_osdep.h
+++ b/dpdk/drivers/net/i40e/base/i40e_osdep.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_OSDEP_H_
@@ -133,6 +133,14 @@ static inline uint32_t i40e_read_addr(volatile void *addr)
 	return rte_le_to_cpu_32(I40E_PCI_REG(addr));
 }
 
+#define I40E_PCI_REG64(reg)		rte_read64(reg)
+#define I40E_PCI_REG64_ADDR(a, reg) \
+	((volatile uint64_t *)((char *)(a)->hw_addr + (reg)))
+static inline uint64_t i40e_read64_addr(volatile void *addr)
+{
+	return rte_le_to_cpu_64(I40E_PCI_REG64(addr));
+}
+
 #define I40E_PCI_REG_WRITE(reg, value)		\
 	rte_write32((rte_cpu_to_le_32(value)), reg)
 #define I40E_PCI_REG_WRITE_RELAXED(reg, value)	\
@@ -145,6 +153,8 @@ static inline uint32_t i40e_read_addr(volatile void *addr)
 #define I40E_WRITE_REG(hw, reg, value) \
 	I40E_PCI_REG_WRITE(I40E_PCI_REG_ADDR((hw), (reg)), (value))
 
+#define I40E_READ_REG64(hw, reg) i40e_read64_addr(I40E_PCI_REG64_ADDR((hw), (reg)))
+
 #define rd32(a, reg) i40e_read_addr(I40E_PCI_REG_ADDR((a), (reg)))
 #define wr32(a, reg, value) \
 	I40E_PCI_REG_WRITE(I40E_PCI_REG_ADDR((a), (reg)), (value))
diff --git a/dpdk/drivers/net/i40e/base/i40e_prototype.h b/dpdk/drivers/net/i40e/base/i40e_prototype.h
index 0cf006dadc..f356834206 100644
--- a/dpdk/drivers/net/i40e/base/i40e_prototype.h
+++ b/dpdk/drivers/net/i40e/base/i40e_prototype.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_PROTOTYPE_H_
@@ -496,6 +496,10 @@ i40e_virtchnl_link_speed(enum i40e_aq_link_speed link_speed)
 		return VIRTCHNL_LINK_SPEED_100MB;
 	case I40E_LINK_SPEED_1GB:
 		return VIRTCHNL_LINK_SPEED_1GB;
+	case I40E_LINK_SPEED_2_5GB:
+		return VIRTCHNL_LINK_SPEED_2_5GB;
+	case I40E_LINK_SPEED_5GB:
+		return VIRTCHNL_LINK_SPEED_5GB;
 	case I40E_LINK_SPEED_10GB:
 		return VIRTCHNL_LINK_SPEED_10GB;
 	case I40E_LINK_SPEED_40GB:
diff --git a/dpdk/drivers/net/i40e/base/i40e_register.h b/dpdk/drivers/net/i40e/base/i40e_register.h
index e93ec3f58f..2408dcb117 100644
--- a/dpdk/drivers/net/i40e/base/i40e_register.h
+++ b/dpdk/drivers/net/i40e/base/i40e_register.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_REGISTER_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_status.h b/dpdk/drivers/net/i40e/base/i40e_status.h
index 1dad4f4b83..cd72169f14 100644
--- a/dpdk/drivers/net/i40e/base/i40e_status.h
+++ b/dpdk/drivers/net/i40e/base/i40e_status.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_STATUS_H_
diff --git a/dpdk/drivers/net/i40e/base/i40e_type.h b/dpdk/drivers/net/i40e/base/i40e_type.h
index 06863d772d..cc72cc0d58 100644
--- a/dpdk/drivers/net/i40e/base/i40e_type.h
+++ b/dpdk/drivers/net/i40e/base/i40e_type.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _I40E_TYPE_H_
@@ -79,8 +79,8 @@ typedef void (*I40E_ADMINQ_CALLBACK)(struct i40e_hw *, struct i40e_aq_desc *);
 #define I40E_HI_BYTE(x)		((u8)(((x) >> 8) & 0xFF))
 #define I40E_LO_BYTE(x)		((u8)((x) & 0xFF))
 
-/* Number of Transmit Descriptors must be a multiple of 8. */
-#define I40E_REQ_TX_DESCRIPTOR_MULTIPLE	8
+/* Number of Transmit Descriptors must be a multiple of 32. */
+#define I40E_REQ_TX_DESCRIPTOR_MULTIPLE	32
 /* Number of Receive Descriptors must be a multiple of 32 if
  * the number of descriptors is greater than 32.
  */
diff --git a/dpdk/drivers/net/i40e/base/meson.build b/dpdk/drivers/net/i40e/base/meson.build
index 3dee8c9754..bfc38ae1a0 100644
--- a/dpdk/drivers/net/i40e/base/meson.build
+++ b/dpdk/drivers/net/i40e/base/meson.build
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2017 Intel Corporation
+# Copyright(c) 2017-2020 Intel Corporation
 
 sources = [
 	'i40e_adminq.c',
diff --git a/dpdk/drivers/net/i40e/base/virtchnl.h b/dpdk/drivers/net/i40e/base/virtchnl.h
index 88096cb45c..acd7b7eb88 100644
--- a/dpdk/drivers/net/i40e/base/virtchnl.h
+++ b/dpdk/drivers/net/i40e/base/virtchnl.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _VIRTCHNL_H_
@@ -47,12 +47,14 @@ enum virtchnl_status_code {
 	VIRTCHNL_STATUS_NOT_SUPPORTED			= -64,
 };
 
+#define VIRTCHNL_LINK_SPEED_2_5GB_SHIFT		0x0
 #define VIRTCHNL_LINK_SPEED_100MB_SHIFT		0x1
 #define VIRTCHNL_LINK_SPEED_1000MB_SHIFT	0x2
 #define VIRTCHNL_LINK_SPEED_10GB_SHIFT		0x3
 #define VIRTCHNL_LINK_SPEED_40GB_SHIFT		0x4
 #define VIRTCHNL_LINK_SPEED_20GB_SHIFT		0x5
 #define VIRTCHNL_LINK_SPEED_25GB_SHIFT		0x6
+#define VIRTCHNL_LINK_SPEED_5GB_SHIFT		0x7
 
 enum virtchnl_link_speed {
 	VIRTCHNL_LINK_SPEED_UNKNOWN	= 0,
@@ -62,6 +64,8 @@ enum virtchnl_link_speed {
 	VIRTCHNL_LINK_SPEED_40GB	= BIT(VIRTCHNL_LINK_SPEED_40GB_SHIFT),
 	VIRTCHNL_LINK_SPEED_20GB	= BIT(VIRTCHNL_LINK_SPEED_20GB_SHIFT),
 	VIRTCHNL_LINK_SPEED_25GB	= BIT(VIRTCHNL_LINK_SPEED_25GB_SHIFT),
+	VIRTCHNL_LINK_SPEED_2_5GB	= BIT(VIRTCHNL_LINK_SPEED_2_5GB_SHIFT),
+	VIRTCHNL_LINK_SPEED_5GB		= BIT(VIRTCHNL_LINK_SPEED_5GB_SHIFT),
 };
 
 /* for hsplit_0 field of Rx HMC context */
@@ -229,7 +233,8 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
 #define VIRTCHNL_VF_OFFLOAD_ENCAP		0X00100000
 #define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM		0X00200000
 #define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM	0X00400000
-
+/* Define below the capability flags that are not offloads */
+#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED		0x00000080
 #define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \
 			       VIRTCHNL_VF_OFFLOAD_VLAN | \
 			       VIRTCHNL_VF_OFFLOAD_RSS_PF)
@@ -518,10 +523,23 @@ enum virtchnl_event_codes {
 struct virtchnl_pf_event {
 	enum virtchnl_event_codes event;
 	union {
+		/* If the PF driver does not support the new speed reporting
+		 * capabilities then use link_event else use link_event_adv to
+		 * get the speed and link information. The ability to understand
+		 * new speeds is indicated by setting the capability flag
+		 * VIRTCHNL_VF_CAP_ADV_LINK_SPEED in vf_cap_flags parameter
+		 * in virtchnl_vf_resource struct and can be used to determine
+		 * which link event struct to use below.
+		 */
 		struct {
 			enum virtchnl_link_speed link_speed;
 			bool link_status;
 		} link_event;
+		struct {
+			/* link_speed provided in Mbps */
+			u32 link_speed;
+			u8 link_status;
+		} link_event_adv;
 	} event_data;
 
 	int severity;
diff --git a/dpdk/drivers/net/i40e/i40e_ethdev.c b/dpdk/drivers/net/i40e/i40e_ethdev.c
index 5999c964bd..2e23631211 100644
--- a/dpdk/drivers/net/i40e/i40e_ethdev.c
+++ b/dpdk/drivers/net/i40e/i40e_ethdev.c
@@ -47,6 +47,8 @@
 #define ETH_I40E_VF_MSG_CFG		"vf_msg_cfg"
 
 #define I40E_CLEAR_PXE_WAIT_MS     200
+#define I40E_VSI_TSR_QINQ_STRIP		0x4010
+#define I40E_VSI_TSR(_i)	(0x00050800 + ((_i) * 4))
 
 /* Maximun number of capability elements */
 #define I40E_MAX_CAP_ELE_NUM       128
@@ -775,6 +777,21 @@ static inline void i40e_config_automask(struct i40e_pf *pf)
 	I40E_WRITE_REG(hw, I40E_GLINT_CTL, val);
 }
 
+static inline void i40e_clear_automask(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint32_t val;
+
+	val = I40E_READ_REG(hw, I40E_GLINT_CTL);
+	val &= ~(I40E_GLINT_CTL_DIS_AUTOMASK_PF0_MASK |
+		 I40E_GLINT_CTL_DIS_AUTOMASK_VF0_MASK);
+
+	if (!pf->support_multi_driver)
+		val &= ~I40E_GLINT_CTL_DIS_AUTOMASK_N_MASK;
+
+	I40E_WRITE_REG(hw, I40E_GLINT_CTL, val);
+}
+
 #define I40E_FLOW_CONTROL_ETHERTYPE  0x8808
 
 /*
@@ -1442,8 +1459,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void *init_params __rte_unused)
 		PMD_INIT_LOG(ERR, "Failed to init adminq: %d", ret);
 		return -EIO;
 	}
-	/* Firmware of SFP x722 does not support adminq option */
-	if (hw->device_id == I40E_DEV_ID_SFP_X722)
+	/* Firmware of SFP x722 does not support 802.1ad frames ability */
+	if (hw->device_id == I40E_DEV_ID_SFP_X722 ||
+		hw->device_id == I40E_DEV_ID_SFP_I_X722)
 		hw->flags &= ~I40E_HW_FLAG_802_1AD_CAPABLE;
 
 	PMD_INIT_LOG(INFO, "FW %d.%d API %d.%d NVM %02d.%02d.%02d eetrack %04x",
@@ -2005,7 +2023,7 @@ __vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t msix_vect,
 	I40E_WRITE_FLUSH(hw);
 }
 
-void
+int
 i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx)
 {
 	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2025,10 +2043,14 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx)
 
 	/* VF bind interrupt */
 	if (vsi->type == I40E_VSI_SRIOV) {
+		if (vsi->nb_msix == 0) {
+			PMD_DRV_LOG(ERR, "No msix resource");
+			return -EINVAL;
+		}
 		__vsi_queues_bind_intr(vsi, msix_vect,
 				       vsi->base_queue, vsi->nb_qps,
 				       itr_idx);
-		return;
+		return 0;
 	}
 
 	/* PF & VMDq bind interrupt */
@@ -2045,7 +2067,10 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx)
 	}
 
 	for (i = 0; i < vsi->nb_used_qps; i++) {
-		if (nb_msix <= 1) {
+		if (vsi->nb_msix == 0) {
+			PMD_DRV_LOG(ERR, "No msix resource");
+			return -EINVAL;
+		} else if (nb_msix <= 1) {
 			if (!rte_intr_allow_others(intr_handle))
 				/* allow to share MISC_VEC_ID */
 				msix_vect = I40E_MISC_VEC_ID;
@@ -2070,9 +2095,11 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx)
 		msix_vect++;
 		nb_msix--;
 	}
+
+	return 0;
 }
 
-static void
+void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
 	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2099,7 +2126,7 @@ i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 	I40E_WRITE_FLUSH(hw);
 }
 
-static void
+void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
 	struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2241,6 +2268,9 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct rte_eth_conf *conf = &dev->data->dev_conf;
 
+	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK |
+		     I40E_AQ_PHY_LINK_ENABLED;
+
 	if (conf->link_speeds == ETH_LINK_SPEED_AUTONEG) {
 		conf->link_speeds = ETH_LINK_SPEED_40G |
 				    ETH_LINK_SPEED_25G |
@@ -2248,11 +2278,12 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
 				    ETH_LINK_SPEED_10G |
 				    ETH_LINK_SPEED_1G |
 				    ETH_LINK_SPEED_100M;
+
+		abilities |= I40E_AQ_PHY_AN_ENABLED;
+	} else {
+		abilities &= ~I40E_AQ_PHY_AN_ENABLED;
 	}
 	speed = i40e_parse_link_speeds(conf->link_speeds);
-	abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK |
-		     I40E_AQ_PHY_AN_ENABLED |
-		     I40E_AQ_PHY_LINK_ENABLED;
 
 	return i40e_phy_conf_link(hw, abilities, speed, true);
 }
@@ -2268,16 +2299,10 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	uint32_t intr_vector = 0;
 	struct i40e_vsi *vsi;
+	uint16_t nb_rxq, nb_txq;
 
 	hw->adapter_stopped = 0;
 
-	if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
-		PMD_INIT_LOG(ERR,
-		"Invalid link_speeds for port %u, autonegotiation disabled",
-			      dev->data->port_id);
-		return -EINVAL;
-	}
-
 	rte_intr_disable(intr_handle);
 
 	if ((rte_intr_cap_multiple(intr_handle) ||
@@ -2306,35 +2331,38 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	ret = i40e_dev_rxtx_init(pf);
 	if (ret != I40E_SUCCESS) {
 		PMD_DRV_LOG(ERR, "Failed to init rx/tx queues");
-		goto err_up;
+		return ret;
 	}
 
 	/* Map queues with MSIX interrupt */
 	main_vsi->nb_used_qps = dev->data->nb_rx_queues -
 		pf->nb_cfg_vmdq_vsi * RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
-	i40e_vsi_queues_bind_intr(main_vsi, I40E_ITR_INDEX_DEFAULT);
+	ret = i40e_vsi_queues_bind_intr(main_vsi, I40E_ITR_INDEX_DEFAULT);
+	if (ret < 0)
+		return ret;
 	i40e_vsi_enable_queues_intr(main_vsi);
 
 	/* Map VMDQ VSI queues with MSIX interrupt */
 	for (i = 0; i < pf->nb_cfg_vmdq_vsi; i++) {
 		pf->vmdq[i].vsi->nb_used_qps = RTE_LIBRTE_I40E_QUEUE_NUM_PER_VM;
-		i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi,
-					  I40E_ITR_INDEX_DEFAULT);
+		ret = i40e_vsi_queues_bind_intr(pf->vmdq[i].vsi,
+						I40E_ITR_INDEX_DEFAULT);
+		if (ret < 0)
+			return ret;
 		i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
 	}
 
-	/* enable FDIR MSIX interrupt */
-	if (pf->fdir.fdir_vsi) {
-		i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi,
-					  I40E_ITR_INDEX_NONE);
-		i40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi);
+	/* Enable all queues which have been configured */
+	for (nb_rxq = 0; nb_rxq < dev->data->nb_rx_queues; nb_rxq++) {
+		ret = i40e_dev_rx_queue_start(dev, nb_rxq);
+		if (ret)
+			goto rx_err;
 	}
 
-	/* Enable all queues which have been configured */
-	ret = i40e_dev_switch_queues(pf, TRUE);
-	if (ret != I40E_SUCCESS) {
-		PMD_DRV_LOG(ERR, "Failed to enable VSI");
-		goto err_up;
+	for (nb_txq = 0; nb_txq < dev->data->nb_tx_queues; nb_txq++) {
+		ret = i40e_dev_tx_queue_start(dev, nb_txq);
+		if (ret)
+			goto tx_err;
 	}
 
 	/* Enable receiving broadcast packets */
@@ -2364,7 +2392,7 @@ i40e_dev_start(struct rte_eth_dev *dev)
 		ret = i40e_aq_set_lb_modes(hw, dev->data->dev_conf.lpbk_mode, NULL);
 		if (ret != I40E_SUCCESS) {
 			PMD_DRV_LOG(ERR, "fail to set loopback link");
-			goto err_up;
+			goto tx_err;
 		}
 	}
 
@@ -2372,7 +2400,7 @@ i40e_dev_start(struct rte_eth_dev *dev)
 	ret = i40e_apply_link_speed(dev);
 	if (I40E_SUCCESS != ret) {
 		PMD_DRV_LOG(ERR, "Fail to apply link setting");
-		goto err_up;
+		goto tx_err;
 	}
 
 	if (!rte_intr_allow_others(intr_handle)) {
@@ -2415,9 +2443,12 @@ i40e_dev_start(struct rte_eth_dev *dev)
 
 	return I40E_SUCCESS;
 
-err_up:
-	i40e_dev_switch_queues(pf, FALSE);
-	i40e_dev_clear_queues(dev);
+tx_err:
+	for (i = 0; i < nb_txq; i++)
+		i40e_dev_tx_queue_stop(dev, i);
+rx_err:
+	for (i = 0; i < nb_rxq; i++)
+		i40e_dev_rx_queue_stop(dev, i);
 
 	return ret;
 }
@@ -2441,7 +2472,11 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	}
 
 	/* Disable all queues */
-	i40e_dev_switch_queues(pf, FALSE);
+	for (i = 0; i < dev->data->nb_tx_queues; i++)
+		i40e_dev_tx_queue_stop(dev, i);
+
+	for (i = 0; i < dev->data->nb_rx_queues; i++)
+		i40e_dev_rx_queue_stop(dev, i);
 
 	/* un-map queues with interrupt registers */
 	i40e_vsi_disable_queues_intr(main_vsi);
@@ -2452,10 +2487,6 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 		i40e_vsi_queues_unbind_intr(pf->vmdq[i].vsi);
 	}
 
-	if (pf->fdir.fdir_vsi) {
-		i40e_vsi_queues_unbind_intr(pf->fdir.fdir_vsi);
-		i40e_vsi_disable_queues_intr(pf->fdir.fdir_vsi);
-	}
 	/* Clear all queues and release memory */
 	i40e_dev_clear_queues(dev);
 
@@ -2594,7 +2625,7 @@ i40e_dev_close(struct rte_eth_dev *dev)
 	do {
 		ret = rte_intr_callback_unregister(intr_handle,
 				i40e_dev_interrupt_handler, dev);
-		if (ret >= 0) {
+		if (ret >= 0 || ret == -ENOENT) {
 			break;
 		} else if (ret != -EAGAIN) {
 			PMD_INIT_LOG(ERR,
@@ -2617,6 +2648,8 @@ i40e_dev_close(struct rte_eth_dev *dev)
 	/* Remove all Traffic Manager configuration */
 	i40e_tm_conf_uninit(dev);
 
+	i40e_clear_automask(pf);
+
 	hw->adapter_closed = 1;
 }
 
@@ -2919,6 +2952,21 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static void
+i40e_stat_update_48_in_64(struct i40e_hw *hw, uint32_t hireg,
+			  uint32_t loreg, bool offset_loaded, uint64_t *offset,
+			  uint64_t *stat, uint64_t *prev_stat)
+{
+	i40e_stat_update_48(hw, hireg, loreg, offset_loaded, offset, stat);
+	/* enlarge the limitation when statistics counters overflowed */
+	if (offset_loaded) {
+		if (I40E_RXTX_BYTES_L_48_BIT(*prev_stat) > *stat)
+			*stat += (uint64_t)1 << I40E_48_BIT_WIDTH;
+		*stat += I40E_RXTX_BYTES_H_16_BIT(*prev_stat);
+	}
+	*prev_stat = *stat;
+}
+
 /* Get all the statistics of a VSI */
 void
 i40e_update_vsi_stats(struct i40e_vsi *vsi)
@@ -2928,9 +2976,9 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi)
 	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
 	int idx = rte_le_to_cpu_16(vsi->info.stat_counter_idx);
 
-	i40e_stat_update_48(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx),
-			    vsi->offset_loaded, &oes->rx_bytes,
-			    &nes->rx_bytes);
+	i40e_stat_update_48_in_64(hw, I40E_GLV_GORCH(idx), I40E_GLV_GORCL(idx),
+				  vsi->offset_loaded, &oes->rx_bytes,
+				  &nes->rx_bytes, &vsi->prev_rx_bytes);
 	i40e_stat_update_48(hw, I40E_GLV_UPRCH(idx), I40E_GLV_UPRCL(idx),
 			    vsi->offset_loaded, &oes->rx_unicast,
 			    &nes->rx_unicast);
@@ -2951,9 +2999,9 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi)
 	i40e_stat_update_32(hw, I40E_GLV_RUPP(idx), vsi->offset_loaded,
 			    &oes->rx_unknown_protocol,
 			    &nes->rx_unknown_protocol);
-	i40e_stat_update_48(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx),
-			    vsi->offset_loaded, &oes->tx_bytes,
-			    &nes->tx_bytes);
+	i40e_stat_update_48_in_64(hw, I40E_GLV_GOTCH(idx), I40E_GLV_GOTCL(idx),
+				  vsi->offset_loaded, &oes->tx_bytes,
+				  &nes->tx_bytes, &vsi->prev_tx_bytes);
 	i40e_stat_update_48(hw, I40E_GLV_UPTCH(idx), I40E_GLV_UPTCL(idx),
 			    vsi->offset_loaded, &oes->tx_unicast,
 			    &nes->tx_unicast);
@@ -2995,17 +3043,18 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
 	struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */
 
 	/* Get rx/tx bytes of internal transfer packets */
-	i40e_stat_update_48(hw, I40E_GLV_GORCH(hw->port),
-			I40E_GLV_GORCL(hw->port),
-			pf->offset_loaded,
-			&pf->internal_stats_offset.rx_bytes,
-			&pf->internal_stats.rx_bytes);
-
-	i40e_stat_update_48(hw, I40E_GLV_GOTCH(hw->port),
-			I40E_GLV_GOTCL(hw->port),
-			pf->offset_loaded,
-			&pf->internal_stats_offset.tx_bytes,
-			&pf->internal_stats.tx_bytes);
+	i40e_stat_update_48_in_64(hw, I40E_GLV_GORCH(hw->port),
+				  I40E_GLV_GORCL(hw->port),
+				  pf->offset_loaded,
+				  &pf->internal_stats_offset.rx_bytes,
+				  &pf->internal_stats.rx_bytes,
+				  &pf->internal_prev_rx_bytes);
+	i40e_stat_update_48_in_64(hw, I40E_GLV_GOTCH(hw->port),
+				  I40E_GLV_GOTCL(hw->port),
+				  pf->offset_loaded,
+				  &pf->internal_stats_offset.tx_bytes,
+				  &pf->internal_stats.tx_bytes,
+				  &pf->internal_prev_tx_bytes);
 	/* Get total internal rx packet count */
 	i40e_stat_update_48(hw, I40E_GLV_UPRCH(hw->port),
 			    I40E_GLV_UPRCL(hw->port),
@@ -3045,10 +3094,10 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
 		pf->internal_stats.rx_broadcast) * RTE_ETHER_CRC_LEN;
 
 	/* Get statistics of struct i40e_eth_stats */
-	i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port),
-			    I40E_GLPRT_GORCL(hw->port),
-			    pf->offset_loaded, &os->eth.rx_bytes,
-			    &ns->eth.rx_bytes);
+	i40e_stat_update_48_in_64(hw, I40E_GLPRT_GORCH(hw->port),
+				  I40E_GLPRT_GORCL(hw->port),
+				  pf->offset_loaded, &os->eth.rx_bytes,
+				  &ns->eth.rx_bytes, &pf->prev_rx_bytes);
 	i40e_stat_update_48(hw, I40E_GLPRT_UPRCH(hw->port),
 			    I40E_GLPRT_UPRCL(hw->port),
 			    pf->offset_loaded, &os->eth.rx_unicast,
@@ -3103,10 +3152,10 @@ i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
 			    pf->offset_loaded,
 			    &os->eth.rx_unknown_protocol,
 			    &ns->eth.rx_unknown_protocol);
-	i40e_stat_update_48(hw, I40E_GLPRT_GOTCH(hw->port),
-			    I40E_GLPRT_GOTCL(hw->port),
-			    pf->offset_loaded, &os->eth.tx_bytes,
-			    &ns->eth.tx_bytes);
+	i40e_stat_update_48_in_64(hw, I40E_GLPRT_GOTCH(hw->port),
+				  I40E_GLPRT_GOTCL(hw->port),
+				  pf->offset_loaded, &os->eth.tx_bytes,
+				  &ns->eth.tx_bytes, &pf->prev_tx_bytes);
 	i40e_stat_update_48(hw, I40E_GLPRT_UPTCH(hw->port),
 			    I40E_GLPRT_UPTCL(hw->port),
 			    pf->offset_loaded, &os->eth.tx_unicast,
@@ -3851,6 +3900,39 @@ i40e_vlan_tpid_set(struct rte_eth_dev *dev,
 	return ret;
 }
 
+/* Configure outer vlan stripping on or off in QinQ mode */
+static int
+i40e_vsi_config_outer_vlan_stripping(struct i40e_vsi *vsi, bool on)
+{
+	struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+	int ret = I40E_SUCCESS;
+	uint32_t reg;
+
+	if (vsi->vsi_id >= I40E_MAX_NUM_VSIS) {
+		PMD_DRV_LOG(ERR, "VSI ID exceeds the maximum");
+		return -EINVAL;
+	}
+
+	/* Configure for outer VLAN RX stripping */
+	reg = I40E_READ_REG(hw, I40E_VSI_TSR(vsi->vsi_id));
+
+	if (on)
+		reg |= I40E_VSI_TSR_QINQ_STRIP;
+	else
+		reg &= ~I40E_VSI_TSR_QINQ_STRIP;
+
+	ret = i40e_aq_debug_write_register(hw,
+						   I40E_VSI_TSR(vsi->vsi_id),
+						   reg, NULL);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Failed to update VSI_TSR[%d]",
+				    vsi->vsi_id);
+		return I40E_ERR_CONFIG;
+	}
+
+	return ret;
+}
+
 static int
 i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 {
@@ -3858,11 +3940,6 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	struct i40e_vsi *vsi = pf->main_vsi;
 	struct rte_eth_rxmode *rxmode;
 
-	if (mask & ETH_QINQ_STRIP_MASK) {
-		PMD_DRV_LOG(ERR, "Strip qinq is not supported.");
-		return -ENOTSUP;
-	}
-
 	rxmode = &dev->data->dev_conf.rxmode;
 	if (mask & ETH_VLAN_FILTER_MASK) {
 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER)
@@ -3892,6 +3969,14 @@ i40e_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 			i40e_vsi_config_double_vlan(vsi, FALSE);
 	}
 
+	if (mask & ETH_QINQ_STRIP_MASK) {
+		/* Enable or disable outer VLAN stripping */
+		if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP)
+			i40e_vsi_config_outer_vlan_stripping(vsi, TRUE);
+		else
+			i40e_vsi_config_outer_vlan_stripping(vsi, FALSE);
+	}
+
 	return 0;
 }
 
@@ -4359,7 +4444,6 @@ i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size)
 {
 	struct i40e_pf *pf;
 	struct i40e_hw *hw;
-	int ret;
 
 	if (!vsi || !lut)
 		return -EINVAL;
@@ -4368,12 +4452,16 @@ i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size)
 	hw = I40E_VSI_TO_HW(vsi);
 
 	if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) {
-		ret = i40e_aq_set_rss_lut(hw, vsi->vsi_id,
-					  vsi->type != I40E_VSI_SRIOV,
-					  lut, lut_size);
-		if (ret) {
-			PMD_DRV_LOG(ERR, "Failed to set RSS lookup table");
-			return ret;
+		enum i40e_status_code status;
+
+		status = i40e_aq_set_rss_lut(hw, vsi->vsi_id,
+					     vsi->type != I40E_VSI_SRIOV,
+					     lut, lut_size);
+		if (status) {
+			PMD_DRV_LOG(ERR,
+				    "Failed to update RSS lookup table, error status: %d",
+				    status);
+			return -EIO;
 		}
 	} else {
 		uint32_t *lut_dw = (uint32_t *)lut;
@@ -4930,6 +5018,7 @@ i40e_res_pool_free(struct i40e_res_pool_info *pool,
 {
 	struct pool_entry *entry, *next, *prev, *valid_entry = NULL;
 	uint32_t pool_offset;
+	uint16_t len;
 	int insert;
 
 	if (pool == NULL) {
@@ -4968,12 +5057,13 @@ i40e_res_pool_free(struct i40e_res_pool_info *pool,
 	}
 
 	insert = 0;
+	len = valid_entry->len;
 	/* Try to merge with next one*/
 	if (next != NULL) {
 		/* Merge with next one */
-		if (valid_entry->base + valid_entry->len == next->base) {
+		if (valid_entry->base + len == next->base) {
 			next->base = valid_entry->base;
-			next->len += valid_entry->len;
+			next->len += len;
 			rte_free(valid_entry);
 			valid_entry = next;
 			insert = 1;
@@ -4983,13 +5073,15 @@ i40e_res_pool_free(struct i40e_res_pool_info *pool,
 	if (prev != NULL) {
 		/* Merge with previous one */
 		if (prev->base + prev->len == valid_entry->base) {
-			prev->len += valid_entry->len;
+			prev->len += len;
 			/* If it merge with next one, remove next node */
 			if (insert == 1) {
 				LIST_REMOVE(valid_entry, next);
 				rte_free(valid_entry);
+				valid_entry = NULL;
 			} else {
 				rte_free(valid_entry);
+				valid_entry = NULL;
 				insert = 1;
 			}
 		}
@@ -5005,8 +5097,8 @@ i40e_res_pool_free(struct i40e_res_pool_info *pool,
 			LIST_INSERT_HEAD(&pool->free_list, valid_entry, next);
 	}
 
-	pool->num_free += valid_entry->len;
-	pool->num_alloc -= valid_entry->len;
+	pool->num_free += len;
+	pool->num_alloc -= len;
 
 	return 0;
 }
@@ -5710,10 +5802,14 @@ i40e_vsi_setup(struct i40e_pf *pf,
 		ret = i40e_res_pool_alloc(&pf->msix_pool, 1);
 		if (ret < 0) {
 			PMD_DRV_LOG(ERR, "VSI %d get heap failed %d", vsi->seid, ret);
-			goto fail_queue_alloc;
+			if (type != I40E_VSI_FDIR)
+				goto fail_queue_alloc;
+			vsi->msix_intr = 0;
+			vsi->nb_msix = 0;
+		} else {
+			vsi->msix_intr = ret;
+			vsi->nb_msix = 1;
 		}
-		vsi->msix_intr = ret;
-		vsi->nb_msix = 1;
 	} else {
 		vsi->msix_intr = 0;
 		vsi->nb_msix = 0;
@@ -6062,6 +6158,7 @@ i40e_dev_init_vlan(struct rte_eth_dev *dev)
 
 	/* Apply vlan offload setting */
 	mask = ETH_VLAN_STRIP_MASK |
+	       ETH_QINQ_STRIP_MASK |
 	       ETH_VLAN_FILTER_MASK |
 	       ETH_VLAN_EXTEND_MASK;
 	ret = i40e_vlan_offload_set(dev, mask);
@@ -6277,33 +6374,6 @@ i40e_switch_tx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on)
 	return I40E_SUCCESS;
 }
 
-/* Swith on or off the tx queues */
-static int
-i40e_dev_switch_tx_queues(struct i40e_pf *pf, bool on)
-{
-	struct rte_eth_dev_data *dev_data = pf->dev_data;
-	struct i40e_tx_queue *txq;
-	struct rte_eth_dev *dev = pf->adapter->eth_dev;
-	uint16_t i;
-	int ret;
-
-	for (i = 0; i < dev_data->nb_tx_queues; i++) {
-		txq = dev_data->tx_queues[i];
-		/* Don't operate the queue if not configured or
-		 * if starting only per queue */
-		if (!txq || !txq->q_set || (on && txq->tx_deferred_start))
-			continue;
-		if (on)
-			ret = i40e_dev_tx_queue_start(dev, i);
-		else
-			ret = i40e_dev_tx_queue_stop(dev, i);
-		if ( ret != I40E_SUCCESS)
-			return ret;
-	}
-
-	return I40E_SUCCESS;
-}
-
 int
 i40e_switch_rx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on)
 {
@@ -6355,59 +6425,6 @@ i40e_switch_rx_queue(struct i40e_hw *hw, uint16_t q_idx, bool on)
 
 	return I40E_SUCCESS;
 }
-/* Switch on or off the rx queues */
-static int
-i40e_dev_switch_rx_queues(struct i40e_pf *pf, bool on)
-{
-	struct rte_eth_dev_data *dev_data = pf->dev_data;
-	struct i40e_rx_queue *rxq;
-	struct rte_eth_dev *dev = pf->adapter->eth_dev;
-	uint16_t i;
-	int ret;
-
-	for (i = 0; i < dev_data->nb_rx_queues; i++) {
-		rxq = dev_data->rx_queues[i];
-		/* Don't operate the queue if not configured or
-		 * if starting only per queue */
-		if (!rxq || !rxq->q_set || (on && rxq->rx_deferred_start))
-			continue;
-		if (on)
-			ret = i40e_dev_rx_queue_start(dev, i);
-		else
-			ret = i40e_dev_rx_queue_stop(dev, i);
-		if (ret != I40E_SUCCESS)
-			return ret;
-	}
-
-	return I40E_SUCCESS;
-}
-
-/* Switch on or off all the rx/tx queues */
-int
-i40e_dev_switch_queues(struct i40e_pf *pf, bool on)
-{
-	int ret;
-
-	if (on) {
-		/* enable rx queues before enabling tx queues */
-		ret = i40e_dev_switch_rx_queues(pf, on);
-		if (ret) {
-			PMD_DRV_LOG(ERR, "Failed to switch rx queues");
-			return ret;
-		}
-		ret = i40e_dev_switch_tx_queues(pf, on);
-	} else {
-		/* Stop tx queues before stopping rx queues */
-		ret = i40e_dev_switch_tx_queues(pf, on);
-		if (ret) {
-			PMD_DRV_LOG(ERR, "Failed to switch tx queues");
-			return ret;
-		}
-		ret = i40e_dev_switch_rx_queues(pf, on);
-	}
-
-	return ret;
-}
 
 /* Initialize VSI for TX */
 static int
@@ -6607,9 +6624,13 @@ i40e_stat_update_48(struct i40e_hw *hw,
 {
 	uint64_t new_data;
 
-	new_data = (uint64_t)I40E_READ_REG(hw, loreg);
-	new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) &
-			I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH;
+	if (hw->device_id == I40E_DEV_ID_QEMU) {
+		new_data = (uint64_t)I40E_READ_REG(hw, loreg);
+		new_data |= ((uint64_t)(I40E_READ_REG(hw, hireg) &
+				I40E_16_BIT_MASK)) << I40E_32_BIT_WIDTH;
+	} else {
+		new_data = I40E_READ_REG64(hw, loreg);
+	}
 
 	if (!offset_loaded)
 		*offset = new_data;
@@ -7505,7 +7526,6 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len)
 	uint16_t key_idx = (vsi->type == I40E_VSI_SRIOV) ?
 			   I40E_VFQF_HKEY_MAX_INDEX :
 			   I40E_PFQF_HKEY_MAX_INDEX;
-	int ret = 0;
 
 	if (!key || key_len == 0) {
 		PMD_DRV_LOG(DEBUG, "No key to be configured");
@@ -7518,11 +7538,16 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len)
 
 	if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) {
 		struct i40e_aqc_get_set_rss_key_data *key_dw =
-			(struct i40e_aqc_get_set_rss_key_data *)key;
+				(struct i40e_aqc_get_set_rss_key_data *)key;
+		enum i40e_status_code status =
+				i40e_aq_set_rss_key(hw, vsi->vsi_id, key_dw);
 
-		ret = i40e_aq_set_rss_key(hw, vsi->vsi_id, key_dw);
-		if (ret)
-			PMD_INIT_LOG(ERR, "Failed to configure RSS key via AQ");
+		if (status) {
+			PMD_DRV_LOG(ERR,
+				    "Failed to configure RSS key via AQ, error status: %d",
+				    status);
+			return -EIO;
+		}
 	} else {
 		uint32_t *hash_key = (uint32_t *)key;
 		uint16_t i;
@@ -7542,7 +7567,7 @@ i40e_set_rss_key(struct i40e_vsi *vsi, uint8_t *key, uint8_t key_len)
 		I40E_WRITE_FLUSH(hw);
 	}
 
-	return ret;
+	return 0;
 }
 
 static int
@@ -10411,6 +10436,7 @@ i40e_get_swr_pm_cfg(struct i40e_hw *hw, uint32_t *value)
 		{ I40E_GL_SWR_PM_EF_DEVICE(I40E_DEV_ID_KX_C) },
 		{ I40E_GL_SWR_PM_EF_DEVICE(I40E_DEV_ID_10G_BASE_T) },
 		{ I40E_GL_SWR_PM_EF_DEVICE(I40E_DEV_ID_10G_BASE_T4) },
+		{ I40E_GL_SWR_PM_EF_DEVICE(I40E_DEV_ID_SFP_X722) },
 
 		{ I40E_GL_SWR_PM_SF_DEVICE(I40E_DEV_ID_KX_B) },
 		{ I40E_GL_SWR_PM_SF_DEVICE(I40E_DEV_ID_QSFP_A) },
@@ -10542,7 +10568,6 @@ i40e_configure_registers(struct i40e_hw *hw)
 	}
 }
 
-#define I40E_VSI_TSR(_i)            (0x00050800 + ((_i) * 4))
 #define I40E_VSI_TSR_QINQ_CONFIG    0xc030
 #define I40E_VSI_L2TAGSTXVALID(_i)  (0x00042800 + ((_i) * 4))
 #define I40E_VSI_L2TAGSTXVALID_QINQ 0xab
@@ -12044,7 +12069,7 @@ static int i40e_get_module_eeprom(struct rte_eth_dev *dev,
 		}
 		status = i40e_aq_get_phy_register(hw,
 				I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
-				addr, offset, 1, &value, NULL);
+				addr, 1, offset, &value, NULL);
 		if (status)
 			return -EIO;
 		data[i] = (uint8_t)value;
@@ -12121,7 +12146,7 @@ i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EBUSY;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > I40E_ETH_MAX_LEN)
 		dev_data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
diff --git a/dpdk/drivers/net/i40e/i40e_ethdev.h b/dpdk/drivers/net/i40e/i40e_ethdev.h
index 295ad593b9..91d6830a3c 100644
--- a/dpdk/drivers/net/i40e/i40e_ethdev.h
+++ b/dpdk/drivers/net/i40e/i40e_ethdev.h
@@ -269,6 +269,10 @@ enum i40e_flxpld_layer_idx {
  */
 #define I40E_ETH_OVERHEAD \
 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + I40E_VLAN_TAG_SIZE * 2)
+#define I40E_ETH_MAX_LEN (RTE_ETHER_MTU + I40E_ETH_OVERHEAD)
+
+#define I40E_RXTX_BYTES_H_16_BIT(bytes) ((bytes) & ~I40E_48_BIT_MASK)
+#define I40E_RXTX_BYTES_L_48_BIT(bytes) ((bytes) & I40E_48_BIT_MASK)
 
 struct i40e_adapter;
 struct rte_pci_driver;
@@ -387,6 +391,8 @@ struct i40e_vsi {
 	uint8_t vlan_anti_spoof_on; /* The VLAN anti-spoofing enabled */
 	uint8_t vlan_filter_on; /* The VLAN filter enabled */
 	struct i40e_bw_info bw_info; /* VSI bandwidth information */
+	uint64_t prev_rx_bytes;
+	uint64_t prev_tx_bytes;
 };
 
 struct pool_entry {
@@ -533,17 +539,30 @@ enum i40e_fdir_ip_type {
 	I40E_FDIR_IPTYPE_IPV6,
 };
 
+/**
+ * Structure to store flex pit for flow diretor.
+ */
+struct i40e_fdir_flex_pit {
+	uint8_t src_offset; /* offset in words from the beginning of payload */
+	uint8_t size;       /* size in words */
+	uint8_t dst_offset; /* offset in words of flexible payload */
+};
+
 /* A structure used to contain extend input of flow */
 struct i40e_fdir_flow_ext {
 	uint16_t vlan_tci;
 	uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN];
 	/* It is filled by the flexible payload to match. */
+	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
+	uint8_t raw_id;
 	uint8_t is_vf;   /* 1 for VF, 0 for port dev */
 	uint16_t dst_id; /* VF ID, available when is_vf is 1*/
 	bool inner_ip;   /* If there is inner ip */
 	enum i40e_fdir_ip_type iip_type; /* ip type for inner ip */
 	bool customized_pctype; /* If customized pctype is used */
 	bool pkt_template; /* If raw packet template is used */
+	enum i40e_flxpld_layer_idx layer_idx;
+	struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_LAYER * I40E_MAX_FLXPLD_FIED];
 };
 
 /* A structure used to define the input for a flow director filter entry */
@@ -595,15 +614,6 @@ struct i40e_fdir_filter_conf {
 	struct i40e_fdir_action action;  /* Action taken when match */
 };
 
-/*
- * Structure to store flex pit for flow diretor.
- */
-struct i40e_fdir_flex_pit {
-	uint8_t src_offset;    /* offset in words from the beginning of payload */
-	uint8_t size;          /* size in words */
-	uint8_t dst_offset;    /* offset in words of flexible payload */
-};
-
 struct i40e_fdir_flex_mask {
 	uint8_t word_mask;  /**< Bit i enables word i of flexible payload */
 	uint8_t nb_bitmask;
@@ -1007,6 +1017,10 @@ struct i40e_pf {
 	uint16_t switch_domain_id;
 
 	struct i40e_vf_msg_cfg vf_msg_cfg;
+	uint64_t prev_rx_bytes;
+	uint64_t prev_tx_bytes;
+	uint64_t internal_prev_rx_bytes;
+	uint64_t internal_prev_tx_bytes;
 };
 
 enum pending_msg {
@@ -1051,6 +1065,7 @@ struct i40e_vf {
 	bool promisc_unicast_enabled;
 	bool promisc_multicast_enabled;
 
+	rte_spinlock_t cmd_send_lock;
 	uint32_t version_major; /* Major version number */
 	uint32_t version_minor; /* Minor version number */
 	uint16_t promisc_flags; /* Promiscuous setting */
@@ -1170,8 +1185,9 @@ void i40e_update_vsi_stats(struct i40e_vsi *vsi);
 void i40e_pf_disable_irq0(struct i40e_hw *hw);
 void i40e_pf_enable_irq0(struct i40e_hw *hw);
 int i40e_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
-void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx);
+int i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx);
 void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi);
+void i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi);
 int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,
 			   struct i40e_vsi_vlan_pvid_info *info);
 int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);
@@ -1181,6 +1197,7 @@ uint64_t i40e_parse_hena(const struct i40e_adapter *adapter, uint64_t flags);
 enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf);
 enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf);
 int i40e_fdir_setup(struct i40e_pf *pf);
+void i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi);
 const struct rte_memzone *i40e_memzone_reserve(const char *name,
 					uint32_t len,
 					int socket_id);
diff --git a/dpdk/drivers/net/i40e/i40e_ethdev_vf.c b/dpdk/drivers/net/i40e/i40e_ethdev_vf.c
index 5dba0928b9..9a8d2ed9b6 100644
--- a/dpdk/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/dpdk/drivers/net/i40e/i40e_ethdev_vf.c
@@ -91,7 +91,8 @@ static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
 static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40evf_dev_close(struct rte_eth_dev *dev);
-static int  i40evf_dev_reset(struct rte_eth_dev *dev);
+static int i40evf_dev_reset(struct rte_eth_dev *dev);
+static int i40evf_check_vf_reset_done(struct rte_eth_dev *dev);
 static int i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static int i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev);
 static int i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev);
@@ -262,7 +263,7 @@ i40evf_read_pfmsg(struct rte_eth_dev *dev, struct i40evf_arq_msg_info *data)
 		case VIRTCHNL_EVENT_RESET_IMPENDING:
 			vf->vf_reset = true;
 			vf->pend_msg |= PFMSG_RESET_IMPENDING;
-			PMD_DRV_LOG(INFO, "vf is reseting");
+			PMD_DRV_LOG(INFO, "VF is resetting");
 			break;
 		case VIRTCHNL_EVENT_PF_DRIVER_CLOSE:
 			vf->dev_closed = true;
@@ -316,7 +317,7 @@ _atomic_set_cmd(struct i40e_vf *vf, enum virtchnl_ops ops)
 #define ASQ_DELAY_MS  10
 
 static int
-i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
+_i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
 {
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
@@ -407,6 +408,19 @@ i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
 	return err | vf->cmd_retval;
 }
 
+static int
+i40evf_execute_vf_cmd(struct rte_eth_dev *dev, struct vf_cmd_info *args)
+{
+	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+	int err;
+
+	while (!rte_spinlock_trylock(&vf->cmd_send_lock))
+		rte_delay_us_sleep(50);
+	err = _i40evf_execute_vf_cmd(dev, args);
+	rte_spinlock_unlock(&vf->cmd_send_lock);
+	return err;
+}
+
 /*
  * Check API version with sync wait until version read or fail from admin queue
  */
@@ -467,7 +481,8 @@ i40evf_get_vf_resource(struct rte_eth_dev *dev)
 		       VIRTCHNL_VF_OFFLOAD_RSS_AQ |
 		       VIRTCHNL_VF_OFFLOAD_RSS_REG |
 		       VIRTCHNL_VF_OFFLOAD_VLAN |
-		       VIRTCHNL_VF_OFFLOAD_RX_POLLING;
+		       VIRTCHNL_VF_OFFLOAD_RX_POLLING |
+		       VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
 		args.in_args = (uint8_t *)&caps;
 		args.in_args_size = sizeof(caps);
 	} else {
@@ -518,10 +533,19 @@ i40evf_config_promisc(struct rte_eth_dev *dev,
 
 	err = i40evf_execute_vf_cmd(dev, &args);
 
-	if (err)
+	if (err) {
 		PMD_DRV_LOG(ERR, "fail to execute command "
 			    "CONFIG_PROMISCUOUS_MODE");
-	return err;
+
+		if (err == I40E_NOT_SUPPORTED)
+			return -ENOTSUP;
+
+		return -EAGAIN;
+	}
+
+	vf->promisc_unicast_enabled = enable_unicast;
+	vf->promisc_multicast_enabled = enable_multicast;
+	return 0;
 }
 
 static int
@@ -763,7 +787,6 @@ i40evf_stop_queues(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
 		if (i40evf_dev_tx_queue_stop(dev, i) != 0) {
 			PMD_DRV_LOG(ERR, "Fail to stop queue %u", i);
-			return -1;
 		}
 	}
 
@@ -771,7 +794,6 @@ i40evf_stop_queues(struct rte_eth_dev *dev)
 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
 		if (i40evf_dev_rx_queue_stop(dev, i) != 0) {
 			PMD_DRV_LOG(ERR, "Fail to stop queue %u", i);
-			return -1;
 		}
 	}
 
@@ -1034,8 +1056,18 @@ i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
 	args.out_buffer = vf->aq_resp;
 	args.out_size = I40E_AQ_BUF_SZ;
 	err = i40evf_execute_vf_cmd(dev, &args);
-	if (err)
+	if (err) {
 		PMD_DRV_LOG(ERR, "fail to execute command OP_ADD_VLAN");
+		return err;
+	}
+	/**
+	 * In linux kernel driver on receiving ADD_VLAN it enables
+	 * VLAN_STRIP by default. So reconfigure the vlan_offload
+	 * as it was done by the app earlier.
+	 */
+	err = i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
+	if (err)
+		PMD_DRV_LOG(ERR, "fail to set vlan_strip");
 
 	return err;
 }
@@ -1057,12 +1089,28 @@ i40evf_request_queues(struct rte_eth_dev *dev, uint16_t num)
 	args.out_size = I40E_AQ_BUF_SZ;
 
 	rte_eal_alarm_cancel(i40evf_dev_alarm_handler, dev);
+
 	err = i40evf_execute_vf_cmd(dev, &args);
-	if (err)
+
+	rte_eal_alarm_set(I40EVF_ALARM_INTERVAL, i40evf_dev_alarm_handler, dev);
+
+	if (err != I40E_SUCCESS) {
 		PMD_DRV_LOG(ERR, "fail to execute command OP_REQUEST_QUEUES");
+		return err;
+	}
+
+	/* The PF will issue a reset to the VF when change the number of
+	 * queues. The PF will set I40E_VFGEN_RSTAT to COMPLETE first, then
+	 * wait 10ms and set it to ACTIVE. In this duration, vf may not catch
+	 * the moment that COMPLETE is set. So, for vf, we'll try to wait a
+	 * long time.
+	 */
+	rte_delay_ms(100);
+
+	err = i40evf_check_vf_reset_done(dev);
+	if (err)
+		PMD_DRV_LOG(ERR, "VF is still resetting");
 
-	rte_eal_alarm_set(I40EVF_ALARM_INTERVAL,
-			  i40evf_dev_alarm_handler, dev);
 	return err;
 }
 
@@ -1199,6 +1247,7 @@ i40evf_init_vf(struct rte_eth_dev *dev)
 
 	vf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 	vf->dev_data = dev->data;
+	rte_spinlock_init(&vf->cmd_send_lock);
 	err = i40e_set_mac_type(hw);
 	if (err) {
 		PMD_INIT_LOG(ERR, "set_mac_type failed: %d", err);
@@ -1338,8 +1387,47 @@ i40evf_handle_pf_event(struct rte_eth_dev *dev, uint8_t *msg,
 		break;
 	case VIRTCHNL_EVENT_LINK_CHANGE:
 		PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event");
-		vf->link_up = pf_msg->event_data.link_event.link_status;
-		vf->link_speed = pf_msg->event_data.link_event.link_speed;
+
+		if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
+			vf->link_up =
+				pf_msg->event_data.link_event_adv.link_status;
+
+			switch (pf_msg->event_data.link_event_adv.link_speed) {
+			case ETH_SPEED_NUM_100M:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_100MB;
+				break;
+			case ETH_SPEED_NUM_1G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_1GB;
+				break;
+			case ETH_SPEED_NUM_2_5G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_2_5GB;
+				break;
+			case ETH_SPEED_NUM_5G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_5GB;
+				break;
+			case ETH_SPEED_NUM_10G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_10GB;
+				break;
+			case ETH_SPEED_NUM_20G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_20GB;
+				break;
+			case ETH_SPEED_NUM_25G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_25GB;
+				break;
+			case ETH_SPEED_NUM_40G:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_40GB;
+				break;
+			default:
+				vf->link_speed = VIRTCHNL_LINK_SPEED_UNKNOWN;
+				break;
+			}
+		} else {
+			vf->link_up =
+				pf_msg->event_data.link_event.link_status;
+			vf->link_speed =
+				pf_msg->event_data.link_event.link_speed;
+		}
+
 		break;
 	case VIRTCHNL_EVENT_PF_DRIVER_CLOSE:
 		PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_PF_DRIVER_CLOSE event");
@@ -1492,7 +1580,7 @@ i40evf_dev_init(struct rte_eth_dev *eth_dev)
 	hw->bus.device = pci_dev->addr.devid;
 	hw->bus.func = pci_dev->addr.function;
 	hw->hw_addr = (void *)pci_dev->mem_resource[0].addr;
-	hw->adapter_stopped = 0;
+	hw->adapter_stopped = 1;
 	hw->adapter_closed = 0;
 
 	/* Pass the information to the rte_eth_dev_close() that it should also
@@ -1588,7 +1676,20 @@ i40evf_dev_configure(struct rte_eth_dev *dev)
 	ad->tx_vec_allowed = true;
 
 	if (num_queue_pairs > vf->vsi_res->num_queue_pairs) {
-		int ret = 0;
+		struct i40e_hw *hw;
+		int ret;
+
+		if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
+			PMD_DRV_LOG(ERR,
+				    "For secondary processes, change queue pairs is not supported!");
+			return -ENOTSUP;
+		}
+
+		hw  = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+		if (!hw->adapter_stopped) {
+			PMD_DRV_LOG(ERR, "Device must be stopped first!");
+			return -EBUSY;
+		}
 
 		PMD_DRV_LOG(INFO, "change queue pairs from %u to %u",
 			    vf->vsi_res->num_queue_pairs, num_queue_pairs);
@@ -1772,22 +1873,22 @@ i40evf_rxq_init(struct rte_eth_dev *dev, struct i40e_rx_queue *rxq)
 	 * Check if the jumbo frame and maximum packet length are set correctly
 	 */
 	if (dev_data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
-		if (rxq->max_pkt_len <= RTE_ETHER_MAX_LEN ||
+		if (rxq->max_pkt_len <= I40E_ETH_MAX_LEN ||
 		    rxq->max_pkt_len > I40E_FRAME_SIZE_MAX) {
 			PMD_DRV_LOG(ERR, "maximum packet length must be "
 				"larger than %u and smaller than %u, as jumbo "
-				"frame is enabled", (uint32_t)RTE_ETHER_MAX_LEN,
+				"frame is enabled", (uint32_t)I40E_ETH_MAX_LEN,
 					(uint32_t)I40E_FRAME_SIZE_MAX);
 			return I40E_ERR_CONFIG;
 		}
 	} else {
 		if (rxq->max_pkt_len < RTE_ETHER_MIN_LEN ||
-		    rxq->max_pkt_len > RTE_ETHER_MAX_LEN) {
+		    rxq->max_pkt_len > I40E_ETH_MAX_LEN) {
 			PMD_DRV_LOG(ERR, "maximum packet length must be "
 				"larger than %u and smaller than %u, as jumbo "
 				"frame is disabled",
 				(uint32_t)RTE_ETHER_MIN_LEN,
-				(uint32_t)RTE_ETHER_MAX_LEN);
+				(uint32_t)I40E_ETH_MAX_LEN);
 			return I40E_ERR_CONFIG;
 		}
 	}
@@ -2160,76 +2261,32 @@ static int
 i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-	int ret;
-
-	/* If enabled, just return */
-	if (vf->promisc_unicast_enabled)
-		return 0;
-
-	ret = i40evf_config_promisc(dev, 1, vf->promisc_multicast_enabled);
-	if (ret == 0)
-		vf->promisc_unicast_enabled = TRUE;
-	else
-		ret = -EAGAIN;
 
-	return ret;
+	return i40evf_config_promisc(dev, true, vf->promisc_multicast_enabled);
 }
 
 static int
 i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-	int ret;
-
-	/* If disabled, just return */
-	if (!vf->promisc_unicast_enabled)
-		return 0;
-
-	ret = i40evf_config_promisc(dev, 0, vf->promisc_multicast_enabled);
-	if (ret == 0)
-		vf->promisc_unicast_enabled = FALSE;
-	else
-		ret = -EAGAIN;
 
-	return ret;
+	return i40evf_config_promisc(dev, false, vf->promisc_multicast_enabled);
 }
 
 static int
 i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-	int ret;
 
-	/* If enabled, just return */
-	if (vf->promisc_multicast_enabled)
-		return 0;
-
-	ret = i40evf_config_promisc(dev, vf->promisc_unicast_enabled, 1);
-	if (ret == 0)
-		vf->promisc_multicast_enabled = TRUE;
-	else
-		ret = -EAGAIN;
-
-	return ret;
+	return i40evf_config_promisc(dev, vf->promisc_unicast_enabled, true);
 }
 
 static int
 i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev)
 {
 	struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-	int ret;
-
-	/* If enabled, just return */
-	if (!vf->promisc_multicast_enabled)
-		return 0;
 
-	ret = i40evf_config_promisc(dev, vf->promisc_unicast_enabled, 0);
-	if (ret == 0)
-		vf->promisc_multicast_enabled = FALSE;
-	else
-		ret = -EAGAIN;
-
-	return ret;
+	return i40evf_config_promisc(dev, vf->promisc_unicast_enabled, false);
 }
 
 static int
@@ -2331,6 +2388,7 @@ i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 		stats->imissed = pstats->rx_discards;
 		stats->oerrors = pstats->tx_errors + pstats->tx_discards;
 		stats->ibytes = pstats->rx_bytes;
+		stats->ibytes -= stats->ipackets * RTE_ETHER_CRC_LEN;
 		stats->obytes = pstats->tx_bytes;
 	} else {
 		PMD_DRV_LOG(ERR, "Get statistics failed");
@@ -2351,8 +2409,9 @@ i40evf_dev_close(struct rte_eth_dev *dev)
 	 * it is a workaround solution when work with kernel driver
 	 * and it is not the normal way
 	 */
-	i40evf_dev_promiscuous_disable(dev);
-	i40evf_dev_allmulticast_disable(dev);
+	if (vf->promisc_unicast_enabled || vf->promisc_multicast_enabled)
+		i40evf_config_promisc(dev, false, false);
+
 	rte_eal_alarm_cancel(i40evf_dev_alarm_handler, dev);
 
 	i40evf_reset_vf(dev);
@@ -2747,7 +2806,7 @@ i40evf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EBUSY;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > I40E_ETH_MAX_LEN)
 		dev_data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
diff --git a/dpdk/drivers/net/i40e/i40e_fdir.c b/dpdk/drivers/net/i40e/i40e_fdir.c
index dee007daae..fb9f2c0fce 100644
--- a/dpdk/drivers/net/i40e/i40e_fdir.c
+++ b/dpdk/drivers/net/i40e/i40e_fdir.c
@@ -113,7 +113,7 @@ i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
 #endif
 	rx_ctx.dtype = i40e_header_split_none;
 	rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;
-	rx_ctx.rxmax = RTE_ETHER_MAX_LEN;
+	rx_ctx.rxmax = I40E_ETH_MAX_LEN;
 	rx_ctx.tphrdesc_ena = 1;
 	rx_ctx.tphwdesc_ena = 1;
 	rx_ctx.tphdata_ena = 1;
@@ -222,6 +222,11 @@ i40e_fdir_setup(struct i40e_pf *pf)
 		goto fail_mem;
 	}
 
+	/* enable FDIR MSIX interrupt */
+	vsi->nb_used_qps = 1;
+	i40e_vsi_queues_bind_intr(vsi, I40E_ITR_INDEX_NONE);
+	i40e_vsi_enable_queues_intr(vsi);
+
 	/* reserve memory for the fdir programming packet */
 	snprintf(z_name, sizeof(z_name), "%s_%s_%d",
 			eth_dev->device->driver->name,
@@ -267,12 +272,18 @@ i40e_fdir_teardown(struct i40e_pf *pf)
 	vsi = pf->fdir.fdir_vsi;
 	if (!vsi)
 		return;
+
+	/* disable FDIR MSIX interrupt */
+	i40e_vsi_queues_unbind_intr(vsi);
+	i40e_vsi_disable_queues_intr(vsi);
+
 	int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
 	if (err)
 		PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off");
 	err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
 	if (err)
 		PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off");
+
 	i40e_dev_rx_queue_release(pf->fdir.rxq);
 	pf->fdir.rxq = NULL;
 	i40e_dev_tx_queue_release(pf->fdir.txq);
@@ -1539,6 +1550,153 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
 	return ret;
 }
 
+static int
+i40e_flow_store_flex_pit(struct i40e_pf *pf,
+			 struct i40e_fdir_flex_pit *flex_pit,
+			 enum i40e_flxpld_layer_idx layer_idx,
+			 uint8_t raw_id)
+{
+	uint8_t field_idx;
+
+	field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
+	/* Check if the configuration is conflicted */
+	if (pf->fdir.flex_pit_flag[layer_idx] &&
+	    (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset ||
+	     pf->fdir.flex_set[field_idx].size != flex_pit->size ||
+	     pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset))
+		return -1;
+
+	/* Check if the configuration exists. */
+	if (pf->fdir.flex_pit_flag[layer_idx] &&
+	    (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset &&
+	     pf->fdir.flex_set[field_idx].size == flex_pit->size &&
+	     pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset))
+		return 1;
+
+	pf->fdir.flex_set[field_idx].src_offset =
+		flex_pit->src_offset;
+	pf->fdir.flex_set[field_idx].size =
+		flex_pit->size;
+	pf->fdir.flex_set[field_idx].dst_offset =
+		flex_pit->dst_offset;
+
+	return 0;
+}
+
+static void
+i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
+			    enum i40e_flxpld_layer_idx layer_idx,
+			    uint8_t raw_id)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint32_t flx_pit, flx_ort;
+	uint16_t min_next_off = 0;
+	uint8_t field_idx;
+	uint8_t i;
+
+	if (raw_id) {
+		flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
+			  (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
+			  (layer_idx * I40E_MAX_FLXPLD_FIED);
+		I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort);
+	}
+
+	/* Set flex pit */
+	for (i = 0; i < raw_id; i++) {
+		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
+		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
+				     pf->fdir.flex_set[field_idx].size,
+				     pf->fdir.flex_set[field_idx].dst_offset);
+
+		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
+		min_next_off = pf->fdir.flex_set[field_idx].src_offset +
+			pf->fdir.flex_set[field_idx].size;
+	}
+
+	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
+		/* set the non-used register obeying register's constrain */
+		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
+		flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
+				     NONUSE_FLX_PIT_DEST_OFF);
+		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
+		min_next_off++;
+	}
+
+	pf->fdir.flex_pit_flag[layer_idx] = 1;
+}
+
+static int
+i40e_flow_store_flex_mask(struct i40e_pf *pf,
+			  enum i40e_filter_pctype pctype,
+			  uint8_t *mask)
+{
+	struct i40e_fdir_flex_mask flex_mask;
+	uint8_t nb_bitmask = 0;
+	uint16_t mask_tmp;
+	uint8_t i;
+
+	memset(&flex_mask, 0, sizeof(struct i40e_fdir_flex_mask));
+	for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) {
+		mask_tmp = I40E_WORD(mask[i], mask[i + 1]);
+		if (mask_tmp) {
+			flex_mask.word_mask |=
+				I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
+			if (mask_tmp != UINT16_MAX) {
+				flex_mask.bitmask[nb_bitmask].mask = ~mask_tmp;
+				flex_mask.bitmask[nb_bitmask].offset =
+					i / sizeof(uint16_t);
+				nb_bitmask++;
+				if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD)
+					return -1;
+			}
+		}
+	}
+	flex_mask.nb_bitmask = nb_bitmask;
+
+	if (pf->fdir.flex_mask_flag[pctype] &&
+	    (memcmp(&flex_mask, &pf->fdir.flex_mask[pctype],
+		    sizeof(struct i40e_fdir_flex_mask))))
+		return -2;
+	else if (pf->fdir.flex_mask_flag[pctype] &&
+		 !(memcmp(&flex_mask, &pf->fdir.flex_mask[pctype],
+			  sizeof(struct i40e_fdir_flex_mask))))
+		return 1;
+
+	memcpy(&pf->fdir.flex_mask[pctype], &flex_mask,
+	       sizeof(struct i40e_fdir_flex_mask));
+	return 0;
+}
+
+static void
+i40e_flow_set_fdir_flex_msk(struct i40e_pf *pf,
+			    enum i40e_filter_pctype pctype)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	struct i40e_fdir_flex_mask *flex_mask;
+	uint32_t flxinset, fd_mask;
+	uint8_t i;
+
+	/* Set flex mask */
+	flex_mask = &pf->fdir.flex_mask[pctype];
+	flxinset = (flex_mask->word_mask <<
+		    I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) &
+		I40E_PRTQF_FD_FLXINSET_INSET_MASK;
+	i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset);
+
+	for (i = 0; i < flex_mask->nb_bitmask; i++) {
+		fd_mask = (flex_mask->bitmask[i].mask <<
+			   I40E_PRTQF_FD_MSK_MASK_SHIFT) &
+			   I40E_PRTQF_FD_MSK_MASK_MASK;
+		fd_mask |= ((flex_mask->bitmask[i].offset +
+			     I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
+			    I40E_PRTQF_FD_MSK_OFFSET_SHIFT) &
+				I40E_PRTQF_FD_MSK_OFFSET_MASK;
+		i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask);
+	}
+
+	pf->fdir.flex_mask_flag[pctype] = 1;
+}
+
 /**
  * i40e_flow_add_del_fdir_filter - add or remove a flow director filter.
  * @pf: board private structure
@@ -1552,15 +1710,21 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 {
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	enum i40e_flxpld_layer_idx layer_idx = I40E_FLXPLD_L2_IDX;
 	unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
-	enum i40e_filter_pctype pctype;
 	struct i40e_fdir_info *fdir_info = &pf->fdir;
 	struct i40e_fdir_filter *fdir_filter, *node;
+	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
 	struct i40e_fdir_filter check_filter; /* Check if the filter exists */
+	struct i40e_fdir_flex_pit flex_pit;
+	enum i40e_filter_pctype pctype;
+	bool cfg_flex_pit = true;
+	uint8_t field_idx;
 	int ret = 0;
+	int i;
 
-	if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
-		PMD_DRV_LOG(ERR, "FDIR is not enabled, please check the mode in fdir_conf.");
+	if (pf->fdir.fdir_vsi == NULL) {
+		PMD_DRV_LOG(ERR, "FDIR is not enabled");
 		return -ENOTSUP;
 	}
 
@@ -1623,6 +1787,47 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 	}
 
 	if (add) {
+		if (!filter->input.flow_ext.customized_pctype) {
+			for (i = 0; i < filter->input.flow_ext.raw_id; i++) {
+				layer_idx = filter->input.flow_ext.layer_idx;
+				field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
+				flex_pit = filter->input.flow_ext.flex_pit[field_idx];
+
+				/* Store flex pit to SW */
+				ret = i40e_flow_store_flex_pit(pf, &flex_pit,
+							       layer_idx, i);
+				if (ret < 0) {
+					PMD_DRV_LOG(ERR, "Conflict with the"
+						    " first flexible rule.");
+					return -EINVAL;
+				} else if (ret > 0) {
+					cfg_flex_pit = false;
+				}
+			}
+
+			if (cfg_flex_pit)
+				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
+						filter->input.flow_ext.raw_id);
+
+			/* Store flex mask to SW */
+			for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++)
+				flex_mask[i] =
+					filter->input.flow_ext.flex_mask[i];
+
+			ret = i40e_flow_store_flex_mask(pf, pctype, flex_mask);
+			if (ret == -1) {
+				PMD_DRV_LOG(ERR, "Exceed maximal"
+					    " number of bitmasks");
+				return -EINVAL;
+			} else if (ret == -2) {
+				PMD_DRV_LOG(ERR, "Conflict with the"
+					    " first flexible rule");
+				return -EINVAL;
+			} else if (ret == 0) {
+				i40e_flow_set_fdir_flex_msk(pf, pctype);
+			}
+		}
+
 		fdir_filter = rte_zmalloc("fdir_filter",
 					  sizeof(*fdir_filter), 0);
 		if (fdir_filter == NULL) {
@@ -1636,6 +1841,8 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 			rte_free(fdir_filter);
 	} else {
 		ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);
+		if (ret >= 0)
+			pf->fdir.flex_mask_flag[pctype] = 0;
 	}
 
 	return ret;
diff --git a/dpdk/drivers/net/i40e/i40e_flow.c b/dpdk/drivers/net/i40e/i40e_flow.c
index 61021037c8..4f5f31c802 100644
--- a/dpdk/drivers/net/i40e/i40e_flow.c
+++ b/dpdk/drivers/net/i40e/i40e_flow.c
@@ -26,7 +26,10 @@
 #define I40E_IPV6_TC_MASK	(0xFF << I40E_FDIR_IPv6_TC_OFFSET)
 #define I40E_IPV6_FRAG_HEADER	44
 #define I40E_TENANT_ARRAY_NUM	3
-#define I40E_TCI_MASK		0xFFFF
+#define I40E_VLAN_TCI_MASK	0xFFFF
+#define I40E_VLAN_PRI_MASK	0xE000
+#define I40E_VLAN_CFI_MASK	0x1000
+#define I40E_VLAN_VID_MASK	0x0FFF
 
 static int i40e_flow_validate(struct rte_eth_dev *dev,
 			      const struct rte_flow_attr *attr,
@@ -2172,152 +2175,6 @@ i40e_flow_check_raw_item(const struct rte_flow_item *item,
 	return 0;
 }
 
-static int
-i40e_flow_store_flex_pit(struct i40e_pf *pf,
-			 struct i40e_fdir_flex_pit *flex_pit,
-			 enum i40e_flxpld_layer_idx layer_idx,
-			 uint8_t raw_id)
-{
-	uint8_t field_idx;
-
-	field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
-	/* Check if the configuration is conflicted */
-	if (pf->fdir.flex_pit_flag[layer_idx] &&
-	    (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset ||
-	     pf->fdir.flex_set[field_idx].size != flex_pit->size ||
-	     pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset))
-		return -1;
-
-	/* Check if the configuration exists. */
-	if (pf->fdir.flex_pit_flag[layer_idx] &&
-	    (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset &&
-	     pf->fdir.flex_set[field_idx].size == flex_pit->size &&
-	     pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset))
-		return 1;
-
-	pf->fdir.flex_set[field_idx].src_offset =
-		flex_pit->src_offset;
-	pf->fdir.flex_set[field_idx].size =
-		flex_pit->size;
-	pf->fdir.flex_set[field_idx].dst_offset =
-		flex_pit->dst_offset;
-
-	return 0;
-}
-
-static int
-i40e_flow_store_flex_mask(struct i40e_pf *pf,
-			  enum i40e_filter_pctype pctype,
-			  uint8_t *mask)
-{
-	struct i40e_fdir_flex_mask flex_mask;
-	uint16_t mask_tmp;
-	uint8_t i, nb_bitmask = 0;
-
-	memset(&flex_mask, 0, sizeof(struct i40e_fdir_flex_mask));
-	for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) {
-		mask_tmp = I40E_WORD(mask[i], mask[i + 1]);
-		if (mask_tmp) {
-			flex_mask.word_mask |=
-				I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
-			if (mask_tmp != UINT16_MAX) {
-				flex_mask.bitmask[nb_bitmask].mask = ~mask_tmp;
-				flex_mask.bitmask[nb_bitmask].offset =
-					i / sizeof(uint16_t);
-				nb_bitmask++;
-				if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD)
-					return -1;
-			}
-		}
-	}
-	flex_mask.nb_bitmask = nb_bitmask;
-
-	if (pf->fdir.flex_mask_flag[pctype] &&
-	    (memcmp(&flex_mask, &pf->fdir.flex_mask[pctype],
-		    sizeof(struct i40e_fdir_flex_mask))))
-		return -2;
-	else if (pf->fdir.flex_mask_flag[pctype] &&
-		 !(memcmp(&flex_mask, &pf->fdir.flex_mask[pctype],
-			  sizeof(struct i40e_fdir_flex_mask))))
-		return 1;
-
-	memcpy(&pf->fdir.flex_mask[pctype], &flex_mask,
-	       sizeof(struct i40e_fdir_flex_mask));
-	return 0;
-}
-
-static void
-i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf,
-			    enum i40e_flxpld_layer_idx layer_idx,
-			    uint8_t raw_id)
-{
-	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
-	uint32_t flx_pit, flx_ort;
-	uint8_t field_idx;
-	uint16_t min_next_off = 0;  /* in words */
-	uint8_t i;
-
-	if (raw_id) {
-		flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
-			  (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
-			  (layer_idx * I40E_MAX_FLXPLD_FIED);
-		I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort);
-	}
-
-	/* Set flex pit */
-	for (i = 0; i < raw_id; i++) {
-		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
-		flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
-				     pf->fdir.flex_set[field_idx].size,
-				     pf->fdir.flex_set[field_idx].dst_offset);
-
-		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
-		min_next_off = pf->fdir.flex_set[field_idx].src_offset +
-			pf->fdir.flex_set[field_idx].size;
-	}
-
-	for (; i < I40E_MAX_FLXPLD_FIED; i++) {
-		/* set the non-used register obeying register's constrain */
-		field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
-		flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
-				     NONUSE_FLX_PIT_DEST_OFF);
-		I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
-		min_next_off++;
-	}
-
-	pf->fdir.flex_pit_flag[layer_idx] = 1;
-}
-
-static void
-i40e_flow_set_fdir_flex_msk(struct i40e_pf *pf,
-			    enum i40e_filter_pctype pctype)
-{
-	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
-	struct i40e_fdir_flex_mask *flex_mask;
-	uint32_t flxinset, fd_mask;
-	uint8_t i;
-
-	/* Set flex mask */
-	flex_mask = &pf->fdir.flex_mask[pctype];
-	flxinset = (flex_mask->word_mask <<
-		    I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) &
-		I40E_PRTQF_FD_FLXINSET_INSET_MASK;
-	i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset);
-
-	for (i = 0; i < flex_mask->nb_bitmask; i++) {
-		fd_mask = (flex_mask->bitmask[i].mask <<
-			   I40E_PRTQF_FD_MSK_MASK_SHIFT) &
-			I40E_PRTQF_FD_MSK_MASK_MASK;
-		fd_mask |= ((flex_mask->bitmask[i].offset +
-			     I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
-			    I40E_PRTQF_FD_MSK_OFFSET_SHIFT) &
-			I40E_PRTQF_FD_MSK_OFFSET_MASK;
-		i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask);
-	}
-
-	pf->fdir.flex_mask_flag[pctype] = 1;
-}
-
 static int
 i40e_flow_set_fdir_inset(struct i40e_pf *pf,
 			 enum i40e_filter_pctype pctype,
@@ -2479,19 +2336,16 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 	uint16_t len_arr[I40E_MAX_FLXPLD_FIED];
 	struct i40e_fdir_flex_pit flex_pit;
 	uint8_t next_dst_off = 0;
-	uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN];
 	uint16_t flex_size;
-	bool cfg_flex_pit = true;
-	bool cfg_flex_msk = true;
 	uint16_t outer_tpid;
 	uint16_t ether_type;
 	uint32_t vtc_flow_cpu;
 	bool outer_ip = true;
+	uint8_t field_idx;
 	int ret;
 
 	memset(off_arr, 0, sizeof(off_arr));
 	memset(len_arr, 0, sizeof(len_arr));
-	memset(flex_mask, 0, I40E_FDIR_MAX_FLEX_LEN);
 	outer_tpid = i40e_get_outer_vlan(dev);
 	filter->input.flow_ext.customized_pctype = false;
 	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
@@ -2542,7 +2396,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 				if (next_type == RTE_FLOW_ITEM_TYPE_VLAN ||
 				    ether_type == RTE_ETHER_TYPE_IPV4 ||
 				    ether_type == RTE_ETHER_TYPE_IPV6 ||
-				    ether_type == RTE_ETHER_TYPE_ARP ||
 				    ether_type == outer_tpid) {
 					rte_flow_error_set(error, EINVAL,
 						     RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2565,12 +2418,22 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
 			RTE_ASSERT(!(input_set & I40E_INSET_LAST_ETHER_TYPE));
 			if (vlan_spec && vlan_mask) {
-				if (vlan_mask->tci ==
-				    rte_cpu_to_be_16(I40E_TCI_MASK)) {
-					input_set |= I40E_INSET_VLAN_INNER;
-					filter->input.flow_ext.vlan_tci =
-						vlan_spec->tci;
+				if (vlan_mask->tci !=
+				    rte_cpu_to_be_16(I40E_VLAN_TCI_MASK) &&
+				    vlan_mask->tci !=
+				    rte_cpu_to_be_16(I40E_VLAN_PRI_MASK) &&
+				    vlan_mask->tci !=
+				    rte_cpu_to_be_16(I40E_VLAN_CFI_MASK) &&
+				    vlan_mask->tci !=
+				    rte_cpu_to_be_16(I40E_VLAN_VID_MASK)) {
+					rte_flow_error_set(error, EINVAL,
+						   RTE_FLOW_ERROR_TYPE_ITEM,
+						   item,
+						   "Unsupported TCI mask.");
 				}
+				input_set |= I40E_INSET_VLAN_INNER;
+				filter->input.flow_ext.vlan_tci =
+					vlan_spec->tci;
 			}
 			if (vlan_spec && vlan_mask && vlan_mask->inner_type) {
 				if (vlan_mask->inner_type != RTE_BE16(0xffff)) {
@@ -2587,7 +2450,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
 				if (ether_type == RTE_ETHER_TYPE_IPV4 ||
 				    ether_type == RTE_ETHER_TYPE_IPV6 ||
-				    ether_type == RTE_ETHER_TYPE_ARP ||
 				    ether_type == outer_tpid) {
 					rte_flow_error_set(error, EINVAL,
 						     RTE_FLOW_ERROR_TYPE_ITEM,
@@ -2941,6 +2803,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
 			flex_size = 0;
 			memset(&flex_pit, 0, sizeof(struct i40e_fdir_flex_pit));
+			field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id;
 			flex_pit.size =
 				raw_spec->length / sizeof(uint16_t);
 			flex_pit.dst_offset =
@@ -2967,27 +2830,21 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 				return -rte_errno;
 			}
 
-			/* Store flex pit to SW */
-			ret = i40e_flow_store_flex_pit(pf, &flex_pit,
-						       layer_idx, raw_id);
-			if (ret < 0) {
-				rte_flow_error_set(error, EINVAL,
-				   RTE_FLOW_ERROR_TYPE_ITEM,
-				   item,
-				   "Conflict with the first flexible rule.");
-				return -rte_errno;
-			} else if (ret > 0)
-				cfg_flex_pit = false;
-
 			for (i = 0; i < raw_spec->length; i++) {
 				j = i + next_dst_off;
 				filter->input.flow_ext.flexbytes[j] =
 					raw_spec->pattern[i];
-				flex_mask[j] = raw_mask->pattern[i];
+				filter->input.flow_ext.flex_mask[j] =
+					raw_mask->pattern[i];
 			}
 
 			next_dst_off += raw_spec->length;
 			raw_id++;
+
+			memcpy(&filter->input.flow_ext.flex_pit[field_idx],
+			       &flex_pit, sizeof(struct i40e_fdir_flex_pit));
+			filter->input.flow_ext.layer_idx = layer_idx;
+			filter->input.flow_ext.raw_id = raw_id;
 			break;
 		case RTE_FLOW_ITEM_TYPE_VF:
 			vf_spec = item->spec;
@@ -3043,29 +2900,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 					   "Invalid pattern mask.");
 			return -rte_errno;
 		}
-
-		/* Store flex mask to SW */
-		ret = i40e_flow_store_flex_mask(pf, pctype, flex_mask);
-		if (ret == -1) {
-			rte_flow_error_set(error, EINVAL,
-					   RTE_FLOW_ERROR_TYPE_ITEM,
-					   item,
-					   "Exceed maximal number of bitmasks");
-			return -rte_errno;
-		} else if (ret == -2) {
-			rte_flow_error_set(error, EINVAL,
-					   RTE_FLOW_ERROR_TYPE_ITEM,
-					   item,
-					   "Conflict with the first flexible rule");
-			return -rte_errno;
-		} else if (ret > 0)
-			cfg_flex_msk = false;
-
-		if (cfg_flex_pit)
-			i40e_flow_set_fdir_flex_pit(pf, layer_idx, raw_id);
-
-		if (cfg_flex_msk)
-			i40e_flow_set_fdir_flex_msk(pf, pctype);
 	}
 
 	filter->input.pctype = pctype;
@@ -3208,8 +3042,7 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 
 	cons_filter_type = RTE_ETH_FILTER_FDIR;
 
-	if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT ||
-		pf->fdir.fdir_vsi == NULL) {
+	if (pf->fdir.fdir_vsi == NULL) {
 		/* Enable fdir when fdir flow is added at first time. */
 		ret = i40e_fdir_setup(pf);
 		if (ret != I40E_SUCCESS) {
@@ -3225,10 +3058,12 @@ i40e_flow_parse_fdir_filter(struct rte_eth_dev *dev,
 					   NULL, "Failed to configure fdir.");
 			goto err;
 		}
-
-		dev->data->dev_conf.fdir_conf.mode = RTE_FDIR_MODE_PERFECT;
 	}
 
+	/* If create the first fdir rule, enable fdir check for rx queues */
+	if (TAILQ_EMPTY(&pf->fdir.fdir_list))
+		i40e_fdir_rx_proc_enable(dev, 1);
+
 	return 0;
 err:
 	i40e_fdir_teardown(pf);
@@ -3424,10 +3259,10 @@ i40e_flow_parse_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
 
 			if (vlan_spec && vlan_mask) {
 				if (vlan_mask->tci ==
-				    rte_cpu_to_be_16(I40E_TCI_MASK))
+				    rte_cpu_to_be_16(I40E_VLAN_TCI_MASK))
 					filter->inner_vlan =
 					      rte_be_to_cpu_16(vlan_spec->tci) &
-					      I40E_TCI_MASK;
+					      I40E_VLAN_TCI_MASK;
 				filter_type |= ETH_TUNNEL_FILTER_IVLAN;
 			}
 			break;
@@ -3655,10 +3490,10 @@ i40e_flow_parse_nvgre_pattern(__rte_unused struct rte_eth_dev *dev,
 
 			if (vlan_spec && vlan_mask) {
 				if (vlan_mask->tci ==
-				    rte_cpu_to_be_16(I40E_TCI_MASK))
+				    rte_cpu_to_be_16(I40E_VLAN_TCI_MASK))
 					filter->inner_vlan =
 					      rte_be_to_cpu_16(vlan_spec->tci) &
-					      I40E_TCI_MASK;
+					      I40E_VLAN_TCI_MASK;
 				filter_type |= ETH_TUNNEL_FILTER_IVLAN;
 			}
 			break;
@@ -4179,14 +4014,9 @@ i40e_flow_parse_qinq_pattern(__rte_unused struct rte_eth_dev *dev,
 	}
 
 	/* Get filter specification */
-	if ((o_vlan_mask != NULL) && (o_vlan_mask->tci ==
-			rte_cpu_to_be_16(I40E_TCI_MASK)) &&
-			(i_vlan_mask != NULL) &&
-			(i_vlan_mask->tci == rte_cpu_to_be_16(I40E_TCI_MASK))) {
-		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci)
-			& I40E_TCI_MASK;
-		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci)
-			& I40E_TCI_MASK;
+	if (o_vlan_mask != NULL &&  i_vlan_mask != NULL) {
+		filter->outer_vlan = rte_be_to_cpu_16(o_vlan_spec->tci);
+		filter->inner_vlan = rte_be_to_cpu_16(i_vlan_spec->tci);
 	} else {
 			rte_flow_error_set(error, EINVAL,
 					   RTE_FLOW_ERROR_TYPE_ITEM,
@@ -4280,7 +4110,7 @@ i40e_flow_parse_rss_pattern(__rte_unused struct rte_eth_dev *dev,
 			vlan_mask = item->mask;
 			if (vlan_spec && vlan_mask) {
 				if (vlan_mask->tci ==
-					rte_cpu_to_be_16(I40E_TCI_MASK)) {
+					rte_cpu_to_be_16(I40E_VLAN_TCI_MASK)) {
 					info->region[0].user_priority[0] =
 						(rte_be_to_cpu_16(
 						vlan_spec->tci) >> 13) & 0x7;
@@ -4326,13 +4156,59 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
 	const struct rte_flow_action *act;
 	const struct rte_flow_action_rss *rss;
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct i40e_queue_regions *info = &pf->queue_region;
 	struct i40e_rte_flow_rss_conf *rss_config =
 			&filter->rss_conf;
 	struct i40e_rte_flow_rss_conf *rss_info = &pf->rss_info;
-	uint16_t i, j, n, tmp;
+	uint16_t i, j, n, m, tmp;
 	uint32_t index = 0;
-	uint64_t hf_bit = 1;
+
+	static const struct {
+		uint64_t rss_type;
+		enum i40e_filter_pctype pctype;
+	} pctype_match_table[] = {
+		{ETH_RSS_FRAG_IPV4,
+			I40E_FILTER_PCTYPE_FRAG_IPV4},
+		{ETH_RSS_NONFRAG_IPV4_TCP,
+			I40E_FILTER_PCTYPE_NONF_IPV4_TCP},
+		{ETH_RSS_NONFRAG_IPV4_UDP,
+			I40E_FILTER_PCTYPE_NONF_IPV4_UDP},
+		{ETH_RSS_NONFRAG_IPV4_SCTP,
+			I40E_FILTER_PCTYPE_NONF_IPV4_SCTP},
+		{ETH_RSS_NONFRAG_IPV4_OTHER,
+			I40E_FILTER_PCTYPE_NONF_IPV4_OTHER},
+		{ETH_RSS_FRAG_IPV6,
+			I40E_FILTER_PCTYPE_FRAG_IPV6},
+		{ETH_RSS_NONFRAG_IPV6_TCP,
+			I40E_FILTER_PCTYPE_NONF_IPV6_TCP},
+		{ETH_RSS_NONFRAG_IPV6_UDP,
+			I40E_FILTER_PCTYPE_NONF_IPV6_UDP},
+		{ETH_RSS_NONFRAG_IPV6_SCTP,
+			I40E_FILTER_PCTYPE_NONF_IPV6_SCTP},
+		{ETH_RSS_NONFRAG_IPV6_OTHER,
+			I40E_FILTER_PCTYPE_NONF_IPV6_OTHER},
+		{ETH_RSS_L2_PAYLOAD,
+			I40E_FILTER_PCTYPE_L2_PAYLOAD},
+	};
+
+	static const struct {
+		uint64_t rss_type;
+		enum i40e_filter_pctype pctype;
+	} pctype_match_table_x722[] = {
+		{ETH_RSS_NONFRAG_IPV4_TCP,
+			I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK},
+		{ETH_RSS_NONFRAG_IPV4_UDP,
+			I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP},
+		{ETH_RSS_NONFRAG_IPV4_UDP,
+			I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP},
+		{ETH_RSS_NONFRAG_IPV6_TCP,
+			I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK},
+		{ETH_RSS_NONFRAG_IPV6_UDP,
+			I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP},
+		{ETH_RSS_NONFRAG_IPV6_UDP,
+			I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP},
+	};
 
 	NEXT_ITEM_OF_ACTION(act, actions, index);
 	rss = act->conf;
@@ -4350,14 +4226,27 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
 	}
 
 	if (action_flag) {
-		for (n = 0; n < 64; n++) {
-			if (rss->types & (hf_bit << n)) {
-				conf_info->region[0].hw_flowtype[0] = n;
+		for (j = 0; j < RTE_DIM(pctype_match_table); j++) {
+			if (rss->types & pctype_match_table[j].rss_type) {
+				conf_info->region[0].hw_flowtype[0] =
+					(uint8_t)pctype_match_table[j].pctype;
 				conf_info->region[0].flowtype_num = 1;
 				conf_info->queue_region_number = 1;
 				break;
 			}
 		}
+
+		if (hw->mac.type == I40E_MAC_X722)
+			for (j = 0; j < RTE_DIM(pctype_match_table_x722); j++) {
+				if (rss->types &
+				    pctype_match_table_x722[j].rss_type) {
+					m = conf_info->region[0].flowtype_num;
+					conf_info->region[0].hw_flowtype[m] =
+						pctype_match_table_x722[j].pctype;
+					conf_info->region[0].flowtype_num++;
+					conf_info->queue_region_number = 1;
+				}
+			}
 	}
 
 	/**
@@ -4455,9 +4344,9 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
 					info->region[i].user_priority_num++;
 				}
 
-				j = info->region[i].flowtype_num;
-				tmp = conf_info->region[n].hw_flowtype[0];
-				if (conf_info->region[n].flowtype_num) {
+				for (m = 0; m < conf_info->region[n].flowtype_num; m++) {
+					j = info->region[i].flowtype_num;
+					tmp = conf_info->region[n].hw_flowtype[m];
 					info->region[i].hw_flowtype[j] = tmp;
 					info->region[i].flowtype_num++;
 				}
@@ -4470,9 +4359,9 @@ i40e_flow_parse_rss_action(struct rte_eth_dev *dev,
 					info->region[i].user_priority_num++;
 				}
 
-				j = info->region[i].flowtype_num;
-				tmp = conf_info->region[n].hw_flowtype[0];
-				if (conf_info->region[n].flowtype_num) {
+				for (m = 0; m < conf_info->region[n].flowtype_num; m++) {
+					j = info->region[i].flowtype_num;
+					tmp = conf_info->region[n].hw_flowtype[m];
 					info->region[i].hw_flowtype[j] = tmp;
 					info->region[i].flowtype_num++;
 				}
@@ -4796,9 +4685,6 @@ i40e_flow_destroy(struct rte_eth_dev *dev,
 
 		/* If the last flow is destroyed, disable fdir. */
 		if (!ret && TAILQ_EMPTY(&pf->fdir.fdir_list)) {
-			i40e_fdir_teardown(pf);
-			dev->data->dev_conf.fdir_conf.mode =
-				   RTE_FDIR_MODE_NONE;
 			i40e_fdir_rx_proc_enable(dev, 0);
 		}
 		break;
@@ -4956,9 +4842,6 @@ i40e_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
 		return -rte_errno;
 	}
 
-	/* Disable FDIR processing as all FDIR rules are now flushed */
-	i40e_fdir_rx_proc_enable(dev, 0);
-
 	return ret;
 }
 
@@ -4992,11 +4875,14 @@ i40e_flow_flush_fdir_filter(struct i40e_pf *pf)
 		}
 
 		for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
-		     pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++)
+		     pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) {
 			pf->fdir.inset_flag[pctype] = 0;
-	}
+			pf->fdir.flex_mask_flag[pctype] = 0;
+		}
 
-	i40e_fdir_teardown(pf);
+		/* Disable FDIR processing as all FDIR rules are now flushed */
+		i40e_fdir_rx_proc_enable(dev, 0);
+	}
 
 	return ret;
 }
diff --git a/dpdk/drivers/net/i40e/i40e_rxtx.c b/dpdk/drivers/net/i40e/i40e_rxtx.c
index 17dc8c78f7..352fb426df 100644
--- a/dpdk/drivers/net/i40e/i40e_rxtx.c
+++ b/dpdk/drivers/net/i40e/i40e_rxtx.c
@@ -989,6 +989,24 @@ i40e_set_tso_ctx(struct rte_mbuf *mbuf, union i40e_tx_offload tx_offload)
 	return ctx_desc;
 }
 
+/* HW requires that Tx buffer size ranges from 1B up to (16K-1)B. */
+#define I40E_MAX_DATA_PER_TXD \
+	(I40E_TXD_QW1_TX_BUF_SZ_MASK >> I40E_TXD_QW1_TX_BUF_SZ_SHIFT)
+/* Calculate the number of TX descriptors needed for each pkt */
+static inline uint16_t
+i40e_calc_pkt_desc(struct rte_mbuf *tx_pkt)
+{
+	struct rte_mbuf *txd = tx_pkt;
+	uint16_t count = 0;
+
+	while (txd != NULL) {
+		count += DIV_ROUND_UP(txd->data_len, I40E_MAX_DATA_PER_TXD);
+		txd = txd->next;
+	}
+
+	return count;
+}
+
 uint16_t
 i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
@@ -1021,7 +1039,7 @@ i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 	/* Check if the descriptor ring needs to be cleaned. */
 	if (txq->nb_tx_free < txq->tx_free_thresh)
-		i40e_xmit_cleanup(txq);
+		(void)i40e_xmit_cleanup(txq);
 
 	for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
 		td_cmd = 0;
@@ -1046,8 +1064,15 @@ i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		 * The number of descriptors that must be allocated for
 		 * a packet equals to the number of the segments of that
 		 * packet plus 1 context descriptor if needed.
+		 * Recalculate the needed tx descs when TSO enabled in case
+		 * the mbuf data size exceeds max data size that hw allows
+		 * per tx desc.
 		 */
-		nb_used = (uint16_t)(tx_pkt->nb_segs + nb_ctx);
+		if (ol_flags & PKT_TX_TCP_SEG)
+			nb_used = (uint16_t)(i40e_calc_pkt_desc(tx_pkt) +
+					     nb_ctx);
+		else
+			nb_used = (uint16_t)(tx_pkt->nb_segs + nb_ctx);
 		tx_last = (uint16_t)(tx_id + nb_used - 1);
 
 		/* Circular ring */
@@ -1160,6 +1185,24 @@ i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			slen = m_seg->data_len;
 			buf_dma_addr = rte_mbuf_data_iova(m_seg);
 
+			while ((ol_flags & PKT_TX_TCP_SEG) &&
+				unlikely(slen > I40E_MAX_DATA_PER_TXD)) {
+				txd->buffer_addr =
+					rte_cpu_to_le_64(buf_dma_addr);
+				txd->cmd_type_offset_bsz =
+					i40e_build_ctob(td_cmd,
+					td_offset, I40E_MAX_DATA_PER_TXD,
+					td_tag);
+
+				buf_dma_addr += I40E_MAX_DATA_PER_TXD;
+				slen -= I40E_MAX_DATA_PER_TXD;
+
+				txe->last_id = tx_last;
+				tx_id = txe->next_id;
+				txe = txn;
+				txd = &txr[tx_id];
+				txn = &sw_ring[txe->next_id];
+			}
 			PMD_TX_LOG(DEBUG, "mbuf: %p, TDD[%u]:\n"
 				"buf_dma_addr: %#"PRIx64";\n"
 				"td_cmd: %#x;\n"
@@ -1205,7 +1248,8 @@ i40e_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		   (unsigned) txq->port_id, (unsigned) txq->queue_id,
 		   (unsigned) tx_id, (unsigned) nb_tx);
 
-	I40E_PCI_REG_WRITE(txq->qtx_tail, tx_id);
+	rte_cio_wmb();
+	I40E_PCI_REG_WRITE_RELAXED(txq->qtx_tail, tx_id);
 	txq->tx_tail = tx_id;
 
 	return nb_tx;
@@ -1527,6 +1571,15 @@ i40e_dev_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	PMD_INIT_FUNC_TRACE();
 
 	rxq = dev->data->rx_queues[rx_queue_id];
+	if (!rxq || !rxq->q_set) {
+		PMD_DRV_LOG(ERR, "RX queue %u not available or setup",
+			    rx_queue_id);
+		return -EINVAL;
+	}
+
+	if (rxq->rx_deferred_start)
+		PMD_DRV_LOG(WARNING, "RX queue %u is deferrd start",
+			    rx_queue_id);
 
 	err = i40e_alloc_rx_queue_mbufs(rxq);
 	if (err) {
@@ -1559,6 +1612,11 @@ i40e_dev_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	rxq = dev->data->rx_queues[rx_queue_id];
+	if (!rxq || !rxq->q_set) {
+		PMD_DRV_LOG(ERR, "RX queue %u not available or setup",
+				rx_queue_id);
+		return -EINVAL;
+	}
 
 	/*
 	 * rx_queue_id is queue id application refers to, while
@@ -1587,6 +1645,15 @@ i40e_dev_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 	PMD_INIT_FUNC_TRACE();
 
 	txq = dev->data->tx_queues[tx_queue_id];
+	if (!txq || !txq->q_set) {
+		PMD_DRV_LOG(ERR, "TX queue %u is not available or setup",
+			    tx_queue_id);
+		return -EINVAL;
+	}
+
+	if (txq->tx_deferred_start)
+		PMD_DRV_LOG(WARNING, "TX queue %u is deferrd start",
+			    tx_queue_id);
 
 	/*
 	 * tx_queue_id is queue id application refers to, while
@@ -1611,6 +1678,11 @@ i40e_dev_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
 	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	txq = dev->data->tx_queues[tx_queue_id];
+	if (!txq || !txq->q_set) {
+		PMD_DRV_LOG(ERR, "TX queue %u is not available or setup",
+			tx_queue_id);
+		return -EINVAL;
+	}
 
 	/*
 	 * tx_queue_id is queue id application refers to, while
@@ -2617,23 +2689,23 @@ i40e_rx_queue_config(struct i40e_rx_queue *rxq)
 		RTE_MIN((uint32_t)(hw->func_caps.rx_buf_chain_len *
 			rxq->rx_buf_len), data->dev_conf.rxmode.max_rx_pkt_len);
 	if (data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
-		if (rxq->max_pkt_len <= RTE_ETHER_MAX_LEN ||
+		if (rxq->max_pkt_len <= I40E_ETH_MAX_LEN ||
 			rxq->max_pkt_len > I40E_FRAME_SIZE_MAX) {
 			PMD_DRV_LOG(ERR, "maximum packet length must "
 				    "be larger than %u and smaller than %u,"
 				    "as jumbo frame is enabled",
-				    (uint32_t)RTE_ETHER_MAX_LEN,
+				    (uint32_t)I40E_ETH_MAX_LEN,
 				    (uint32_t)I40E_FRAME_SIZE_MAX);
 			return I40E_ERR_CONFIG;
 		}
 	} else {
 		if (rxq->max_pkt_len < RTE_ETHER_MIN_LEN ||
-			rxq->max_pkt_len > RTE_ETHER_MAX_LEN) {
+			rxq->max_pkt_len > I40E_ETH_MAX_LEN) {
 			PMD_DRV_LOG(ERR, "maximum packet length must be "
 				    "larger than %u and smaller than %u, "
 				    "as jumbo frame is disabled",
 				    (uint32_t)RTE_ETHER_MIN_LEN,
-				    (uint32_t)RTE_ETHER_MAX_LEN);
+				    (uint32_t)I40E_ETH_MAX_LEN);
 			return I40E_ERR_CONFIG;
 		}
 	}
diff --git a/dpdk/drivers/net/i40e/i40e_rxtx_vec_altivec.c b/dpdk/drivers/net/i40e/i40e_rxtx_vec_altivec.c
index 310ce1ee2d..39f4d60ca8 100644
--- a/dpdk/drivers/net/i40e/i40e_rxtx_vec_altivec.c
+++ b/dpdk/drivers/net/i40e/i40e_rxtx_vec_altivec.c
@@ -13,7 +13,7 @@
 #include "i40e_rxtx.h"
 #include "i40e_rxtx_vec_common.h"
 
-#include <altivec.h>
+#include <rte_altivec.h>
 
 #pragma GCC diagnostic ignored "-Wcast-qual"
 
@@ -188,11 +188,13 @@ desc_to_ptype_v(vector unsigned long descs[4], struct rte_mbuf **rx_pkts,
 		ptype_tbl[(*(vector unsigned char *)&ptype1)[8]];
 }
 
- /* Notice:
-  * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
-  * - nb_pkts > RTE_I40E_VPMD_RX_BURST, only scan RTE_I40E_VPMD_RX_BURST
-  *   numbers of DD bits
-  */
+/**
+ * vPMD raw receive routine, only accept(nb_pkts >= RTE_I40E_DESCS_PER_LOOP)
+ *
+ * Notice:
+ * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
+ * - floor align nb_pkts to a RTE_I40E_DESCS_PER_LOOP power-of-two
+ */
 static inline uint16_t
 _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		   uint16_t nb_pkts, uint8_t *split_packet)
@@ -214,9 +216,6 @@ _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		};
 	vector unsigned long dd_check, eop_check;
 
-	/* nb_pkts shall be less equal than RTE_I40E_MAX_RX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, RTE_I40E_MAX_RX_BURST);
-
 	/* nb_pkts has to be floor-aligned to RTE_I40E_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_I40E_DESCS_PER_LOOP);
 
@@ -459,15 +458,15 @@ i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
- /* vPMD receive routine that reassembles scattered packets
-  * Notice:
-  * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
-  * - nb_pkts > RTE_I40E_VPMD_RX_BURST, only scan RTE_I40E_VPMD_RX_BURST
-  *   numbers of DD bits
-  */
-uint16_t
-i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-			     uint16_t nb_pkts)
+/**
+ * vPMD receive routine that reassembles single burst of 32 scattered packets
+ *
+ * Notice:
+ * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
+ */
+static uint16_t
+i40e_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
 {
 	struct i40e_rx_queue *rxq = rx_queue;
 	uint8_t split_flags[RTE_I40E_VPMD_RX_BURST] = {0};
@@ -500,6 +499,32 @@ i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			     uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > RTE_I40E_VPMD_RX_BURST) {
+		uint16_t burst;
+
+		burst = i40e_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      RTE_I40E_VPMD_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < RTE_I40E_VPMD_RX_BURST)
+			return retval;
+	}
+
+	return retval + i40e_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      nb_pkts);
+}
+
 static inline void
 vtx1(volatile struct i40e_tx_desc *txdp,
 	struct rte_mbuf *pkt, uint64_t flags)
diff --git a/dpdk/drivers/net/i40e/i40e_rxtx_vec_avx2.c b/dpdk/drivers/net/i40e/i40e_rxtx_vec_avx2.c
index 3bcef13638..1a8cd56484 100644
--- a/dpdk/drivers/net/i40e/i40e_rxtx_vec_avx2.c
+++ b/dpdk/drivers/net/i40e/i40e_rxtx_vec_avx2.c
@@ -342,24 +342,32 @@ _recv_raw_pkts_vec_avx2(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	 */
 	const __m256i l3_l4_flags_shuf = _mm256_set_epi8(0, 0, 0, 0, 0, 0, 0, 0,
 			/* shift right 1 bit to make sure it not exceed 255 */
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_EIP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_BAD) >> 1,
-			PKT_RX_IP_CKSUM_BAD >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_GOOD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD  |
+			 PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD  |
+			 PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
+			 PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
+			 PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_L4_CKSUM_BAD  | PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_L4_CKSUM_BAD  | PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
 			/* second 128-bits */
 			0, 0, 0, 0, 0, 0, 0, 0,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_EIP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_BAD) >> 1,
-			PKT_RX_IP_CKSUM_BAD >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_GOOD) >> 1);
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD  |
+			 PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD  |
+			 PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
+			 PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
+			 PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_L4_CKSUM_BAD  | PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_L4_CKSUM_BAD  | PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1);
 
 	const __m256i cksum_mask = _mm256_set1_epi32(
 			PKT_RX_IP_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD |
diff --git a/dpdk/drivers/net/i40e/i40e_rxtx_vec_common.h b/dpdk/drivers/net/i40e/i40e_rxtx_vec_common.h
index 0e6ffa0078..31f73f6054 100644
--- a/dpdk/drivers/net/i40e/i40e_rxtx_vec_common.h
+++ b/dpdk/drivers/net/i40e/i40e_rxtx_vec_common.h
@@ -33,6 +33,7 @@ reassemble_packets(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_bufs,
 			if (!split_flags[buf_idx]) {
 				/* it's the last packet of the set */
 				start->hash = end->hash;
+				start->vlan_tci = end->vlan_tci;
 				start->ol_flags = end->ol_flags;
 				/* we need to strip crc for the whole packet */
 				start->pkt_len -= rxq->crc_len;
diff --git a/dpdk/drivers/net/i40e/i40e_rxtx_vec_neon.c b/dpdk/drivers/net/i40e/i40e_rxtx_vec_neon.c
index deb185fe2f..5cac418cf0 100644
--- a/dpdk/drivers/net/i40e/i40e_rxtx_vec_neon.c
+++ b/dpdk/drivers/net/i40e/i40e_rxtx_vec_neon.c
@@ -6,6 +6,7 @@
 #include <stdint.h>
 #include <rte_ethdev_driver.h>
 #include <rte_malloc.h>
+#include <rte_vect.h>
 
 #include "base/i40e_prototype.h"
 #include "base/i40e_type.h"
@@ -13,7 +14,6 @@
 #include "i40e_rxtx.h"
 #include "i40e_rxtx_vec_common.h"
 
-#include <arm_neon.h>
 
 #pragma GCC diagnostic ignored "-Wcast-qual"
 
@@ -72,8 +72,9 @@ i40e_rxq_rearm(struct i40e_rx_queue *rxq)
 	rx_id = (uint16_t)((rxq->rxrearm_start == 0) ?
 			     (rxq->nb_rx_desc - 1) : (rxq->rxrearm_start - 1));
 
+	rte_cio_wmb();
 	/* Update the tail pointer on the NIC */
-	I40E_PCI_REG_WRITE(rxq->qrx_tail, rx_id);
+	I40E_PCI_REG_WRITE_RELAXED(rxq->qrx_tail, rx_id);
 }
 
 static inline void
@@ -186,11 +187,12 @@ desc_to_ptype_v(uint64x2_t descs[4], struct rte_mbuf **rx_pkts,
 
 }
 
- /*
+/**
+ * vPMD raw receive routine, only accept(nb_pkts >= RTE_I40E_DESCS_PER_LOOP)
+ *
  * Notice:
  * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_I40E_VPMD_RX_BURST, only scan RTE_I40E_VPMD_RX_BURST
- *   numbers of DD bits
+ * - floor align nb_pkts to a RTE_I40E_DESCS_PER_LOOP power-of-two
  */
 static inline uint16_t
 _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
@@ -228,9 +230,6 @@ _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		0, 0, 0       /* ignore non-length fields */
 		};
 
-	/* nb_pkts shall be less equal than RTE_I40E_MAX_RX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, RTE_I40E_MAX_RX_BURST);
-
 	/* nb_pkts has to be floor-aligned to RTE_I40E_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_I40E_DESCS_PER_LOOP);
 
@@ -437,15 +436,15 @@ i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
- /* vPMD receive routine that reassembles scattered packets
+/**
+ * vPMD receive routine that reassembles single burst of 32 scattered packets
+ *
  * Notice:
  * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_I40E_VPMD_RX_BURST, only scan RTE_I40E_VPMD_RX_BURST
- *   numbers of DD bits
  */
-uint16_t
-i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-			     uint16_t nb_pkts)
+static uint16_t
+i40e_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
 {
 
 	struct i40e_rx_queue *rxq = rx_queue;
@@ -480,6 +479,32 @@ i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			     uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > RTE_I40E_VPMD_RX_BURST) {
+		uint16_t burst;
+
+		burst = i40e_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      RTE_I40E_VPMD_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < RTE_I40E_VPMD_RX_BURST)
+			return retval;
+	}
+
+	return retval + i40e_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      nb_pkts);
+}
+
 static inline void
 vtx1(volatile struct i40e_tx_desc *txdp,
 		struct rte_mbuf *pkt, uint64_t flags)
@@ -564,7 +589,8 @@ i40e_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
 
 	txq->tx_tail = tx_id;
 
-	I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
+	rte_cio_wmb();
+	I40E_PCI_REG_WRITE_RELAXED(txq->qtx_tail, tx_id);
 
 	return nb_pkts;
 }
diff --git a/dpdk/drivers/net/i40e/i40e_rxtx_vec_sse.c b/dpdk/drivers/net/i40e/i40e_rxtx_vec_sse.c
index 6ab0bb0d32..b5c5fdb0a2 100644
--- a/dpdk/drivers/net/i40e/i40e_rxtx_vec_sse.c
+++ b/dpdk/drivers/net/i40e/i40e_rxtx_vec_sse.c
@@ -254,16 +254,18 @@ desc_to_olflags_v(struct i40e_rx_queue *rxq, volatile union i40e_rx_desc *rxdp,
 
 	const __m128i l3_l4e_flags = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0,
 			/* shift right 1 bit to make sure it not exceed 255 */
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD  |
 			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_EIP_CKSUM_BAD |
-			 PKT_RX_L4_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_EIP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_BAD) >> 1,
-			PKT_RX_IP_CKSUM_BAD >> 1,
-			(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_GOOD) >> 1);
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD  |
+			 PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
+			 PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
+			 PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_L4_CKSUM_BAD  | PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_L4_CKSUM_BAD  | PKT_RX_IP_CKSUM_GOOD) >> 1,
+			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1);
 
 	/* Unpack "status" from quadword 1, bits 0:32 */
 	vlan0 = _mm_unpackhi_epi32(descs[0], descs[1]);
@@ -342,11 +344,12 @@ desc_to_ptype_v(__m128i descs[4], struct rte_mbuf **rx_pkts,
 	rx_pkts[3]->packet_type = ptype_tbl[_mm_extract_epi8(ptype1, 8)];
 }
 
- /*
+/**
+ * vPMD raw receive routine, only accept(nb_pkts >= RTE_I40E_DESCS_PER_LOOP)
+ *
  * Notice:
  * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_I40E_VPMD_RX_BURST, only scan RTE_I40E_VPMD_RX_BURST
- *   numbers of DD bits
+ * - floor align nb_pkts to a RTE_I40E_DESCS_PER_LOOP power-of-two
  */
 static inline uint16_t
 _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
@@ -378,9 +381,6 @@ _recv_raw_pkts_vec(struct i40e_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 			offsetof(struct rte_mbuf, rx_descriptor_fields1) + 8);
 	__m128i dd_check, eop_check;
 
-	/* nb_pkts shall be less equal than RTE_I40E_MAX_RX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, RTE_I40E_MAX_RX_BURST);
-
 	/* nb_pkts has to be floor-aligned to RTE_I40E_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_I40E_DESCS_PER_LOOP);
 
@@ -605,15 +605,15 @@ i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
- /* vPMD receive routine that reassembles scattered packets
+/**
+ * vPMD receive routine that reassembles single burst of 32 scattered packets
+ *
  * Notice:
  * - nb_pkts < RTE_I40E_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_I40E_VPMD_RX_BURST, only scan RTE_I40E_VPMD_RX_BURST
- *   numbers of DD bits
  */
-uint16_t
-i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-			     uint16_t nb_pkts)
+static uint16_t
+i40e_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
 {
 
 	struct i40e_rx_queue *rxq = rx_queue;
@@ -648,6 +648,32 @@ i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+i40e_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			     uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > RTE_I40E_VPMD_RX_BURST) {
+		uint16_t burst;
+
+		burst = i40e_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      RTE_I40E_VPMD_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < RTE_I40E_VPMD_RX_BURST)
+			return retval;
+	}
+
+	return retval + i40e_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      nb_pkts);
+}
+
 static inline void
 vtx1(volatile struct i40e_tx_desc *txdp,
 		struct rte_mbuf *pkt, uint64_t flags)
diff --git a/dpdk/drivers/net/i40e/i40e_vf_representor.c b/dpdk/drivers/net/i40e/i40e_vf_representor.c
index b07b35c03f..083bc1a5f3 100644
--- a/dpdk/drivers/net/i40e/i40e_vf_representor.c
+++ b/dpdk/drivers/net/i40e/i40e_vf_representor.c
@@ -46,7 +46,8 @@ i40e_vf_representor_dev_infos_get(struct rte_eth_dev *ethdev,
 		DEV_RX_OFFLOAD_QINQ_STRIP |
 		DEV_RX_OFFLOAD_IPV4_CKSUM |
 		DEV_RX_OFFLOAD_UDP_CKSUM |
-		DEV_RX_OFFLOAD_TCP_CKSUM;
+		DEV_RX_OFFLOAD_TCP_CKSUM |
+		DEV_RX_OFFLOAD_VLAN_FILTER;
 	dev_info->tx_offload_capa =
 		DEV_TX_OFFLOAD_MULTI_SEGS  |
 		DEV_TX_OFFLOAD_VLAN_INSERT |
diff --git a/dpdk/drivers/net/i40e/meson.build b/dpdk/drivers/net/i40e/meson.build
index b01babba1f..3d5fc71119 100644
--- a/dpdk/drivers/net/i40e/meson.build
+++ b/dpdk/drivers/net/i40e/meson.build
@@ -45,6 +45,9 @@ if arch_subdir == 'x86'
 				c_args: [cflags, '-mavx2'])
 		objs += i40e_avx2_lib.extract_objects('i40e_rxtx_vec_avx2.c')
 	endif
+elif arch_subdir == 'arm'
+       dpdk_conf.set('RTE_LIBRTE_I40E_INC_VECTOR', 1)
+       sources += files('i40e_rxtx_vec_neon.c')
 endif
 
 install_headers('rte_pmd_i40e.h')
diff --git a/dpdk/drivers/net/i40e/rte_pmd_i40e.c b/dpdk/drivers/net/i40e/rte_pmd_i40e.c
index fdcb1a43e1..cd2ec58df7 100644
--- a/dpdk/drivers/net/i40e/rte_pmd_i40e.c
+++ b/dpdk/drivers/net/i40e/rte_pmd_i40e.c
@@ -2169,7 +2169,6 @@ static int check_invalid_pkt_type(uint32_t pkt_type)
 	    tnl != RTE_PTYPE_TUNNEL_VXLAN &&
 	    tnl != RTE_PTYPE_TUNNEL_NVGRE &&
 	    tnl != RTE_PTYPE_TUNNEL_GENEVE &&
-	    tnl != RTE_PTYPE_TUNNEL_GRENAT &&
 	    tnl != RTE_PTYPE_TUNNEL_GTPC &&
 	    tnl != RTE_PTYPE_TUNNEL_GTPU &&
 	    tnl != RTE_PTYPE_TUNNEL_L2TP)
@@ -2366,6 +2365,9 @@ rte_pmd_i40e_add_vf_mac_addr(uint16_t port, uint16_t vf_id,
 	struct i40e_mac_filter_info mac_filter;
 	int ret;
 
+	if (mac_addr == NULL)
+		return -EINVAL;
+
 	if (i40e_validate_mac_addr((u8 *)mac_addr) != I40E_SUCCESS)
 		return -EINVAL;
 
@@ -3042,6 +3044,9 @@ int rte_pmd_i40e_flow_add_del_packet_template(
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
 
+	if (conf == NULL)
+		return -EINVAL;
+
 	if (!is_i40e_supported(dev))
 		return -ENOTSUP;
 
diff --git a/dpdk/drivers/net/i40e/rte_pmd_i40e.h b/dpdk/drivers/net/i40e/rte_pmd_i40e.h
index 915cdf0763..9929171541 100644
--- a/dpdk/drivers/net/i40e/rte_pmd_i40e.h
+++ b/dpdk/drivers/net/i40e/rte_pmd_i40e.h
@@ -14,7 +14,13 @@
  *
  */
 
-#include <rte_ethdev_driver.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_compat.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
 
 /**
  * Response sent back to i40e driver from user app after callback
@@ -1079,4 +1085,8 @@ __rte_experimental
 int
 rte_pmd_i40e_set_switch_dev(uint16_t port_id, struct rte_eth_dev *switch_dev);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _PMD_I40E_H_ */
diff --git a/dpdk/drivers/net/iavf/base/README b/dpdk/drivers/net/iavf/base/README
index f57e1048ff..bc54ab2809 100644
--- a/dpdk/drivers/net/iavf/base/README
+++ b/dpdk/drivers/net/iavf/base/README
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
+ * Copyright(c) 2019-2020 Intel Corporation
  */
 
 Intel® IAVF driver
diff --git a/dpdk/drivers/net/iavf/base/iavf_adminq.c b/dpdk/drivers/net/iavf/base/iavf_adminq.c
index 1ba8b52219..d6943e8260 100644
--- a/dpdk/drivers/net/iavf/base/iavf_adminq.c
+++ b/dpdk/drivers/net/iavf/base/iavf_adminq.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "iavf_status.h"
@@ -84,6 +84,7 @@ enum iavf_status_code iavf_alloc_adminq_arq_ring(struct iavf_hw *hw)
  **/
 void iavf_free_adminq_asq(struct iavf_hw *hw)
 {
+	iavf_free_virt_mem(hw, &hw->aq.asq.cmd_buf);
 	iavf_free_dma_mem(hw, &hw->aq.asq.desc_buf);
 }
 
@@ -367,7 +368,7 @@ enum iavf_status_code iavf_init_asq(struct iavf_hw *hw)
 	/* initialize base registers */
 	ret_code = iavf_config_asq_regs(hw);
 	if (ret_code != IAVF_SUCCESS)
-		goto init_adminq_free_rings;
+		goto init_config_regs;
 
 	/* success! */
 	hw->aq.asq.count = hw->aq.num_asq_entries;
@@ -375,6 +376,10 @@ enum iavf_status_code iavf_init_asq(struct iavf_hw *hw)
 
 init_adminq_free_rings:
 	iavf_free_adminq_asq(hw);
+	return ret_code;
+
+init_config_regs:
+	iavf_free_asq_bufs(hw);
 
 init_adminq_exit:
 	return ret_code;
@@ -817,6 +822,8 @@ enum iavf_status_code iavf_asq_send_command(struct iavf_hw *hw,
 		cmd_completed = true;
 		if ((enum iavf_admin_queue_err)retval == IAVF_AQ_RC_OK)
 			status = IAVF_SUCCESS;
+		else if ((enum iavf_admin_queue_err)retval == IAVF_AQ_RC_EBUSY)
+			status = IAVF_ERR_NOT_READY;
 		else
 			status = IAVF_ERR_ADMIN_QUEUE_ERROR;
 		hw->aq.asq_last_status = (enum iavf_admin_queue_err)retval;
diff --git a/dpdk/drivers/net/iavf/base/iavf_adminq.h b/dpdk/drivers/net/iavf/base/iavf_adminq.h
index 715621644b..f97fe8818e 100644
--- a/dpdk/drivers/net/iavf/base/iavf_adminq.h
+++ b/dpdk/drivers/net/iavf/base/iavf_adminq.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IAVF_ADMINQ_H_
diff --git a/dpdk/drivers/net/iavf/base/iavf_alloc.h b/dpdk/drivers/net/iavf/base/iavf_alloc.h
index 4ff307d23d..ef5ce080ad 100644
--- a/dpdk/drivers/net/iavf/base/iavf_alloc.h
+++ b/dpdk/drivers/net/iavf/base/iavf_alloc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IAVF_ALLOC_H_
diff --git a/dpdk/drivers/net/iavf/base/iavf_common.c b/dpdk/drivers/net/iavf/base/iavf_common.c
index 916a8388b2..23f18aa2ec 100644
--- a/dpdk/drivers/net/iavf/base/iavf_common.c
+++ b/dpdk/drivers/net/iavf/base/iavf_common.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "iavf_type.h"
diff --git a/dpdk/drivers/net/iavf/base/iavf_devids.h b/dpdk/drivers/net/iavf/base/iavf_devids.h
index 2cd88d62f0..08c523f19e 100644
--- a/dpdk/drivers/net/iavf/base/iavf_devids.h
+++ b/dpdk/drivers/net/iavf/base/iavf_devids.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IAVF_DEVIDS_H_
diff --git a/dpdk/drivers/net/iavf/base/iavf_osdep.h b/dpdk/drivers/net/iavf/base/iavf_osdep.h
index 6480266937..08b312cbd8 100644
--- a/dpdk/drivers/net/iavf/base/iavf_osdep.h
+++ b/dpdk/drivers/net/iavf/base/iavf_osdep.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
+ * Copyright(c) 2017-2020 Intel Corporation
  */
 
 #ifndef _IAVF_OSDEP_H_
diff --git a/dpdk/drivers/net/iavf/base/iavf_status.h b/dpdk/drivers/net/iavf/base/iavf_status.h
index cb91afb017..a981360af6 100644
--- a/dpdk/drivers/net/iavf/base/iavf_status.h
+++ b/dpdk/drivers/net/iavf/base/iavf_status.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IAVF_STATUS_H_
diff --git a/dpdk/drivers/net/iavf/base/virtchnl.h b/dpdk/drivers/net/iavf/base/virtchnl.h
index 50f7c8e49e..fa98417b05 100644
--- a/dpdk/drivers/net/iavf/base/virtchnl.h
+++ b/dpdk/drivers/net/iavf/base/virtchnl.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2013 - 2015 Intel Corporation
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _VIRTCHNL_H_
diff --git a/dpdk/drivers/net/iavf/iavf.h b/dpdk/drivers/net/iavf/iavf.h
index bbd4d75d00..b343f58004 100644
--- a/dpdk/drivers/net/iavf/iavf.h
+++ b/dpdk/drivers/net/iavf/iavf.h
@@ -58,6 +58,7 @@
 #define IAVF_VLAN_TAG_SIZE               4
 #define IAVF_ETH_OVERHEAD \
 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + IAVF_VLAN_TAG_SIZE * 2)
+#define IAVF_ETH_MAX_LEN (RTE_ETHER_MTU + IAVF_ETH_OVERHEAD)
 
 #define IAVF_32_BIT_WIDTH (CHAR_BIT * 4)
 #define IAVF_48_BIT_WIDTH (CHAR_BIT * 6)
@@ -103,8 +104,12 @@ struct iavf_info {
 	bool link_up;
 	uint32_t link_speed;
 
+	/* Multicast addrs */
+	struct rte_ether_addr mc_addrs[IAVF_NUM_MACADDR_MAX];
+	uint16_t mc_addrs_num;   /* Multicast mac addresses number */
+
 	struct iavf_vsi vsi;
-	bool vf_reset;
+	bool vf_reset;	/* true for VF reset pending, false for no VF reset */
 	uint64_t flags;
 
 	uint8_t *rss_lut;
@@ -173,6 +178,17 @@ struct iavf_cmd_info {
 	uint32_t out_size;      /* buffer size for response */
 };
 
+/* notify current command done. Only call in case execute
+ * _atomic_set_cmd successfully.
+ */
+static inline void
+_notify_cmd(struct iavf_info *vf, uint32_t msg_ret)
+{
+	vf->cmd_retval = msg_ret;
+	rte_wmb();
+	vf->pend_cmd = VIRTCHNL_OP_UNKNOWN;
+}
+
 /* clear current command. Only call in case execute
  * _atomic_set_cmd successfully.
  */
@@ -219,4 +235,7 @@ int iavf_config_promisc(struct iavf_adapter *adapter, bool enable_unicast,
 int iavf_add_del_eth_addr(struct iavf_adapter *adapter,
 			 struct rte_ether_addr *addr, bool add);
 int iavf_add_del_vlan(struct iavf_adapter *adapter, uint16_t vlanid, bool add);
+int iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,
+			      struct rte_ether_addr *mc_addrs,
+			      uint32_t mc_addrs_num, bool add);
 #endif /* _IAVF_ETHDEV_H_ */
diff --git a/dpdk/drivers/net/iavf/iavf_ethdev.c b/dpdk/drivers/net/iavf/iavf_ethdev.c
index a39ba1466c..717d6a242c 100644
--- a/dpdk/drivers/net/iavf/iavf_ethdev.c
+++ b/dpdk/drivers/net/iavf/iavf_ethdev.c
@@ -37,6 +37,7 @@ static int iavf_dev_configure(struct rte_eth_dev *dev);
 static int iavf_dev_start(struct rte_eth_dev *dev);
 static void iavf_dev_stop(struct rte_eth_dev *dev);
 static void iavf_dev_close(struct rte_eth_dev *dev);
+static int iavf_dev_reset(struct rte_eth_dev *dev);
 static int iavf_dev_info_get(struct rte_eth_dev *dev,
 			     struct rte_eth_dev_info *dev_info);
 static const uint32_t *iavf_dev_supported_ptypes_get(struct rte_eth_dev *dev);
@@ -72,6 +73,9 @@ static int iavf_dev_rx_queue_intr_enable(struct rte_eth_dev *dev,
 					uint16_t queue_id);
 static int iavf_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
 					 uint16_t queue_id);
+static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+				 struct rte_ether_addr *mc_addr,
+				 uint32_t mc_addrs_num);
 
 int iavf_logtype_init;
 int iavf_logtype_driver;
@@ -96,6 +100,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 	.dev_start                  = iavf_dev_start,
 	.dev_stop                   = iavf_dev_stop,
 	.dev_close                  = iavf_dev_close,
+	.dev_reset                  = iavf_dev_reset,
 	.dev_infos_get              = iavf_dev_info_get,
 	.dev_supported_ptypes_get   = iavf_dev_supported_ptypes_get,
 	.link_update                = iavf_dev_link_update,
@@ -107,6 +112,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 	.allmulticast_disable       = iavf_dev_allmulticast_disable,
 	.mac_addr_add               = iavf_dev_add_mac_addr,
 	.mac_addr_remove            = iavf_dev_del_mac_addr,
+	.set_mc_addr_list           = iavf_set_mc_addr_list,
 	.vlan_filter_set            = iavf_dev_vlan_filter_set,
 	.vlan_offload_set           = iavf_dev_vlan_offload_set,
 	.rx_queue_start             = iavf_dev_rx_queue_start,
@@ -133,30 +139,31 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
 };
 
 static int
-iavf_dev_configure(struct rte_eth_dev *dev)
+iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+		      struct rte_ether_addr *mc_addrs,
+		      uint32_t mc_addrs_num)
 {
-	struct iavf_adapter *ad =
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+	struct iavf_adapter *adapter =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
-	struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
-	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+	int err;
 
-	ad->rx_bulk_alloc_allowed = true;
-	/* Initialize to TRUE. If any of Rx queues doesn't meet the
-	 * vector Rx/Tx preconditions, it will be reset.
-	 */
-	ad->rx_vec_allowed = true;
-	ad->tx_vec_allowed = true;
+	/* flush previous addresses */
+	err = iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+					false);
+	if (err)
+		return err;
 
-	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
-		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+	vf->mc_addrs_num = 0;
+
+	/* add new ones */
+	err = iavf_add_del_mc_addr_list(adapter, mc_addrs, mc_addrs_num, true);
+	if (err)
+		return err;
+
+	vf->mc_addrs_num = mc_addrs_num;
+	memcpy(vf->mc_addrs, mc_addrs, mc_addrs_num * sizeof(*mc_addrs));
 
-	/* Vlan stripping setting */
-	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
-		if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-			iavf_enable_vlan_strip(ad);
-		else
-			iavf_disable_vlan_strip(ad);
-	}
 	return 0;
 }
 
@@ -165,7 +172,7 @@ iavf_init_rss(struct iavf_adapter *adapter)
 {
 	struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(adapter);
 	struct rte_eth_rss_conf *rss_conf;
-	uint8_t i, j, nb_q;
+	uint16_t i, j, nb_q;
 	int ret;
 
 	rss_conf = &adapter->eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
@@ -216,6 +223,41 @@ iavf_init_rss(struct iavf_adapter *adapter)
 	return 0;
 }
 
+static int
+iavf_dev_configure(struct rte_eth_dev *dev)
+{
+	struct iavf_adapter *ad =
+		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
+	struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+
+	ad->rx_bulk_alloc_allowed = true;
+	/* Initialize to TRUE. If any of Rx queues doesn't meet the
+	 * vector Rx/Tx preconditions, it will be reset.
+	 */
+	ad->rx_vec_allowed = true;
+	ad->tx_vec_allowed = true;
+
+	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
+	/* Vlan stripping setting */
+	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
+		if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
+			iavf_enable_vlan_strip(ad);
+		else
+			iavf_disable_vlan_strip(ad);
+	}
+
+	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+		if (iavf_init_rss(ad) != 0) {
+			PMD_DRV_LOG(ERR, "configure rss failed");
+			return -1;
+		}
+	}
+	return 0;
+}
+
 static int
 iavf_init_rxq(struct rte_eth_dev *dev, struct iavf_rx_queue *rxq)
 {
@@ -233,30 +275,30 @@ iavf_init_rxq(struct rte_eth_dev *dev, struct iavf_rx_queue *rxq)
 	 * correctly.
 	 */
 	if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
-		if (max_pkt_len <= RTE_ETHER_MAX_LEN ||
+		if (max_pkt_len <= IAVF_ETH_MAX_LEN ||
 		    max_pkt_len > IAVF_FRAME_SIZE_MAX) {
 			PMD_DRV_LOG(ERR, "maximum packet length must be "
 				    "larger than %u and smaller than %u, "
 				    "as jumbo frame is enabled",
-				    (uint32_t)RTE_ETHER_MAX_LEN,
+				    (uint32_t)IAVF_ETH_MAX_LEN,
 				    (uint32_t)IAVF_FRAME_SIZE_MAX);
 			return -EINVAL;
 		}
 	} else {
 		if (max_pkt_len < RTE_ETHER_MIN_LEN ||
-		    max_pkt_len > RTE_ETHER_MAX_LEN) {
+		    max_pkt_len > IAVF_ETH_MAX_LEN) {
 			PMD_DRV_LOG(ERR, "maximum packet length must be "
 				    "larger than %u and smaller than %u, "
 				    "as jumbo frame is disabled",
 				    (uint32_t)RTE_ETHER_MIN_LEN,
-				    (uint32_t)RTE_ETHER_MAX_LEN);
+				    (uint32_t)IAVF_ETH_MAX_LEN);
 			return -EINVAL;
 		}
 	}
 
 	rxq->max_pkt_len = max_pkt_len;
 	if ((dev_data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_SCATTER) ||
-	    (rxq->max_pkt_len + 2 * IAVF_VLAN_TAG_SIZE) > buf_size) {
+	    rxq->max_pkt_len > buf_size) {
 		dev_data->scattered_rx = 1;
 	}
 	IAVF_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
@@ -361,14 +403,14 @@ static int iavf_config_rx_queues_irqs(struct rte_eth_dev *dev,
 			/* If Rx interrupt is reuquired, and we can use
 			 * multi interrupts, then the vec is from 1
 			 */
-			vf->nb_msix = RTE_MIN(vf->vf_res->max_vectors,
-					      intr_handle->nb_efd);
+			vf->nb_msix = RTE_MIN(intr_handle->nb_efd,
+				 (uint16_t)(vf->vf_res->max_vectors - 1));
 			vf->msix_base = IAVF_RX_VEC_START;
 			vec = IAVF_RX_VEC_START;
 			for (i = 0; i < dev->data->nb_rx_queues; i++) {
 				vf->rxq_map[vec] |= 1 << i;
 				intr_handle->intr_vec[i] = vec++;
-				if (vec >= vf->nb_msix)
+				if (vec >= vf->nb_msix + IAVF_RX_VEC_START)
 					vec = IAVF_RX_VEC_START;
 			}
 			PMD_DRV_LOG(DEBUG,
@@ -436,13 +478,6 @@ iavf_dev_start(struct rte_eth_dev *dev)
 		return -1;
 	}
 
-	if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
-		if (iavf_init_rss(adapter) != 0) {
-			PMD_DRV_LOG(ERR, "configure rss failed");
-			goto err_rss;
-		}
-	}
-
 	if (iavf_configure_queues(adapter) != 0) {
 		PMD_DRV_LOG(ERR, "configure queues failed");
 		goto err_queue;
@@ -461,6 +496,10 @@ iavf_dev_start(struct rte_eth_dev *dev)
 	/* Set all mac addrs */
 	iavf_add_del_all_mac_addr(adapter, TRUE);
 
+	/* Set all multicast addresses */
+	iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+				  true);
+
 	if (iavf_start_queues(dev) != 0) {
 		PMD_DRV_LOG(ERR, "enable queues failed");
 		goto err_mac;
@@ -471,13 +510,13 @@ iavf_dev_start(struct rte_eth_dev *dev)
 err_mac:
 	iavf_add_del_all_mac_addr(adapter, FALSE);
 err_queue:
-err_rss:
 	return -1;
 }
 
 static void
 iavf_dev_stop(struct rte_eth_dev *dev)
 {
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 	struct iavf_adapter *adapter =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -500,6 +539,11 @@ iavf_dev_stop(struct rte_eth_dev *dev)
 
 	/* remove all mac addrs */
 	iavf_add_del_all_mac_addr(adapter, FALSE);
+
+	/* remove all multicast addresses */
+	iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+				  false);
+
 	hw->adapter_stopped = 1;
 }
 
@@ -593,6 +637,8 @@ iavf_dev_link_update(struct rte_eth_dev *dev,
 	struct rte_eth_link new_link;
 	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
+	memset(&new_link, 0, sizeof(new_link));
+
 	/* Only read status info stored in VF, and the info is updated
 	 *  when receive LINK_CHANGE evnet from PF by Virtchnnl.
 	 */
@@ -657,6 +703,8 @@ iavf_dev_promiscuous_enable(struct rte_eth_dev *dev)
 	ret = iavf_config_promisc(adapter, TRUE, vf->promisc_multicast_enabled);
 	if (!ret)
 		vf->promisc_unicast_enabled = TRUE;
+	else if (ret == IAVF_NOT_SUPPORTED)
+		ret = -ENOTSUP;
 	else
 		ret = -EAGAIN;
 
@@ -677,6 +725,8 @@ iavf_dev_promiscuous_disable(struct rte_eth_dev *dev)
 	ret = iavf_config_promisc(adapter, FALSE, vf->promisc_multicast_enabled);
 	if (!ret)
 		vf->promisc_unicast_enabled = FALSE;
+	else if (ret == IAVF_NOT_SUPPORTED)
+		ret = -ENOTSUP;
 	else
 		ret = -EAGAIN;
 
@@ -697,6 +747,8 @@ iavf_dev_allmulticast_enable(struct rte_eth_dev *dev)
 	ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, TRUE);
 	if (!ret)
 		vf->promisc_multicast_enabled = TRUE;
+	else if (ret == IAVF_NOT_SUPPORTED)
+		ret = -ENOTSUP;
 	else
 		ret = -EAGAIN;
 
@@ -717,6 +769,8 @@ iavf_dev_allmulticast_disable(struct rte_eth_dev *dev)
 	ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, FALSE);
 	if (!ret)
 		vf->promisc_multicast_enabled = FALSE;
+	else if (ret == IAVF_NOT_SUPPORTED)
+		ret = -ENOTSUP;
 	else
 		ret = -EAGAIN;
 
@@ -953,7 +1007,7 @@ iavf_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EBUSY;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > IAVF_ETH_MAX_LEN)
 		dev->data->dev_conf.rxmode.offloads |=
 				DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
@@ -978,9 +1032,6 @@ iavf_dev_set_default_mac_addr(struct rte_eth_dev *dev,
 	old_addr = (struct rte_ether_addr *)hw->mac.addr;
 	perm_addr = (struct rte_ether_addr *)hw->mac.perm_addr;
 
-	if (rte_is_same_ether_addr(mac_addr, old_addr))
-		return 0;
-
 	/* If the MAC address is configured by host, skip the setting */
 	if (rte_is_valid_assigned_ether_addr(perm_addr))
 		return -EPERM;
@@ -1068,7 +1119,7 @@ iavf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 	if (ret == 0) {
 		iavf_update_stats(vsi, pstats);
 		stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
-						pstats->rx_broadcast;
+				pstats->rx_broadcast - pstats->rx_discards;
 		stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
 						pstats->tx_unicast;
 		stats->imissed = pstats->rx_discards;
@@ -1079,7 +1130,7 @@ iavf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 	} else {
 		PMD_DRV_LOG(ERR, "Get statistics failed");
 	}
-	return -EIO;
+	return ret;
 }
 
 static int
@@ -1240,6 +1291,7 @@ iavf_init_vf(struct rte_eth_dev *dev)
 			goto err_rss;
 		}
 	}
+
 	return 0;
 err_rss:
 	rte_free(vf->rss_key);
@@ -1388,7 +1440,6 @@ static int
 iavf_dev_uninit(struct rte_eth_dev *dev)
 {
 	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-	struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return -EPERM;
@@ -1396,8 +1447,7 @@ iavf_dev_uninit(struct rte_eth_dev *dev)
 	dev->dev_ops = NULL;
 	dev->rx_pkt_burst = NULL;
 	dev->tx_pkt_burst = NULL;
-	if (hw->adapter_stopped == 0)
-		iavf_dev_close(dev);
+	iavf_dev_close(dev);
 
 	rte_free(vf->vf_res);
 	vf->vsi_res = NULL;
@@ -1415,9 +1465,26 @@ iavf_dev_uninit(struct rte_eth_dev *dev)
 		vf->rss_key = NULL;
 	}
 
+	vf->vf_reset = false;
+
 	return 0;
 }
 
+/*
+ * Reset VF device only to re-initialize resources in PMD layer
+ */
+static int
+iavf_dev_reset(struct rte_eth_dev *dev)
+{
+	int ret;
+
+	ret = iavf_dev_uninit(dev);
+	if (ret)
+		return ret;
+
+	return iavf_dev_init(dev);
+}
+
 static int eth_iavf_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 			     struct rte_pci_device *pci_dev)
 {
diff --git a/dpdk/drivers/net/iavf/iavf_rxtx.c b/dpdk/drivers/net/iavf/iavf_rxtx.c
index 88f79ba379..ae43eb49a6 100644
--- a/dpdk/drivers/net/iavf/iavf_rxtx.c
+++ b/dpdk/drivers/net/iavf/iavf_rxtx.c
@@ -167,6 +167,8 @@ reset_rx_queue(struct iavf_rx_queue *rxq)
 	rxq->nb_rx_hold = 0;
 	rxq->pkt_first_seg = NULL;
 	rxq->pkt_last_seg = NULL;
+	rxq->rxrearm_nb = 0;
+	rxq->rxrearm_start = 0;
 }
 
 static inline void
@@ -1506,7 +1508,7 @@ iavf_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 	/* Check if the descriptor ring needs to be cleaned. */
 	if (txq->nb_free < txq->free_thresh)
-		iavf_xmit_cleanup(txq);
+		(void)iavf_xmit_cleanup(txq);
 
 	for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
 		td_cmd = 0;
diff --git a/dpdk/drivers/net/iavf/iavf_rxtx.h b/dpdk/drivers/net/iavf/iavf_rxtx.h
index 225a0c4c42..60d02c521f 100644
--- a/dpdk/drivers/net/iavf/iavf_rxtx.h
+++ b/dpdk/drivers/net/iavf/iavf_rxtx.h
@@ -28,6 +28,7 @@
 		DEV_TX_OFFLOAD_VLAN_INSERT |		 \
 		DEV_TX_OFFLOAD_SCTP_CKSUM |		 \
 		DEV_TX_OFFLOAD_UDP_CKSUM |		 \
+		DEV_TX_OFFLOAD_TCP_TSO |		 \
 		DEV_TX_OFFLOAD_TCP_CKSUM)
 
 #define DEFAULT_TX_RS_THRESH     32
diff --git a/dpdk/drivers/net/iavf/iavf_rxtx_vec_common.h b/dpdk/drivers/net/iavf/iavf_rxtx_vec_common.h
index a6ba227584..25bb502de2 100644
--- a/dpdk/drivers/net/iavf/iavf_rxtx_vec_common.h
+++ b/dpdk/drivers/net/iavf/iavf_rxtx_vec_common.h
@@ -33,6 +33,7 @@ reassemble_packets(struct iavf_rx_queue *rxq, struct rte_mbuf **rx_bufs,
 			if (!split_flags[buf_idx]) {
 				/* it's the last packet of the set */
 				start->hash = end->hash;
+				start->vlan_tci = end->vlan_tci;
 				start->ol_flags = end->ol_flags;
 				/* we need to strip crc for the whole packet */
 				start->pkt_len -= rxq->crc_len;
diff --git a/dpdk/drivers/net/iavf/iavf_rxtx_vec_sse.c b/dpdk/drivers/net/iavf/iavf_rxtx_vec_sse.c
index 2b16dc1b52..458730e089 100644
--- a/dpdk/drivers/net/iavf/iavf_rxtx_vec_sse.c
+++ b/dpdk/drivers/net/iavf/iavf_rxtx_vec_sse.c
@@ -227,10 +227,12 @@ desc_to_ptype_v(__m128i descs[4], struct rte_mbuf **rx_pkts)
 	rx_pkts[3]->packet_type = type_table[_mm_extract_epi8(ptype1, 8)];
 }
 
-/* Notice:
+/**
+ * vPMD raw receive routine, only accept(nb_pkts >= IAVF_VPMD_DESCS_PER_LOOP)
+ *
+ * Notice:
  * - nb_pkts < IAVF_VPMD_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > IAVF_VPMD_RX_MAX_BURST, only scan IAVF_VPMD_RX_MAX_BURST
- *   numbers of DD bits
+ * - floor align nb_pkts to a IAVF_VPMD_DESCS_PER_LOOP power-of-two
  */
 static inline uint16_t
 _recv_raw_pkts_vec(struct iavf_rx_queue *rxq, struct rte_mbuf **rx_pkts,
@@ -260,9 +262,6 @@ _recv_raw_pkts_vec(struct iavf_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 			offsetof(struct rte_mbuf, rx_descriptor_fields1) + 8);
 	__m128i dd_check, eop_check;
 
-	/* nb_pkts shall be less equal than IAVF_VPMD_RX_MAX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, IAVF_VPMD_RX_MAX_BURST);
-
 	/* nb_pkts has to be floor-aligned to IAVF_VPMD_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, IAVF_VPMD_DESCS_PER_LOOP);
 
@@ -486,15 +485,15 @@ iavf_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
-/* vPMD receive routine that reassembles scattered packets
+/**
+ * vPMD receive routine that reassembles single burst of 32 scattered packets
+ *
  * Notice:
  * - nb_pkts < IAVF_VPMD_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > VPMD_RX_MAX_BURST, only scan IAVF_VPMD_RX_MAX_BURST
- *   numbers of DD bits
  */
-uint16_t
-iavf_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-			    uint16_t nb_pkts)
+static uint16_t
+iavf_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
 {
 	struct iavf_rx_queue *rxq = rx_queue;
 	uint8_t split_flags[IAVF_VPMD_RX_MAX_BURST] = {0};
@@ -527,6 +526,32 @@ iavf_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+iavf_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			     uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > IAVF_VPMD_RX_MAX_BURST) {
+		uint16_t burst;
+
+		burst = iavf_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      IAVF_VPMD_RX_MAX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < IAVF_VPMD_RX_MAX_BURST)
+			return retval;
+	}
+
+	return retval + iavf_recv_scattered_burst_vec(rx_queue,
+						      rx_pkts + retval,
+						      nb_pkts);
+}
+
 static inline void
 vtx1(volatile struct iavf_tx_desc *txdp, struct rte_mbuf *pkt, uint64_t flags)
 {
diff --git a/dpdk/drivers/net/iavf/iavf_vchnl.c b/dpdk/drivers/net/iavf/iavf_vchnl.c
index 14395fed31..81ad748f4d 100644
--- a/dpdk/drivers/net/iavf/iavf_vchnl.c
+++ b/dpdk/drivers/net/iavf/iavf_vchnl.c
@@ -73,6 +73,9 @@ iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args)
 	int err = 0;
 	int i = 0;
 
+	if (vf->vf_reset)
+		return -EIO;
+
 	if (_atomic_set_cmd(vf, args->ops))
 		return -1;
 
@@ -132,6 +135,38 @@ iavf_execute_vf_cmd(struct iavf_adapter *adapter, struct iavf_cmd_info *args)
 	return err;
 }
 
+static uint32_t
+iavf_convert_link_speed(enum virtchnl_link_speed virt_link_speed)
+{
+	uint32_t speed;
+
+	switch (virt_link_speed) {
+	case VIRTCHNL_LINK_SPEED_100MB:
+		speed = 100;
+		break;
+	case VIRTCHNL_LINK_SPEED_1GB:
+		speed = 1000;
+		break;
+	case VIRTCHNL_LINK_SPEED_10GB:
+		speed = 10000;
+		break;
+	case VIRTCHNL_LINK_SPEED_40GB:
+		speed = 40000;
+		break;
+	case VIRTCHNL_LINK_SPEED_20GB:
+		speed = 20000;
+		break;
+	case VIRTCHNL_LINK_SPEED_25GB:
+		speed = 25000;
+		break;
+	default:
+		speed = 0;
+		break;
+	}
+
+	return speed;
+}
+
 static void
 iavf_handle_pf_event_msg(struct rte_eth_dev *dev, uint8_t *msg,
 			uint16_t msglen)
@@ -147,13 +182,21 @@ iavf_handle_pf_event_msg(struct rte_eth_dev *dev, uint8_t *msg,
 	switch (pf_msg->event) {
 	case VIRTCHNL_EVENT_RESET_IMPENDING:
 		PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event");
+		vf->vf_reset = true;
 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET,
 					      NULL);
 		break;
 	case VIRTCHNL_EVENT_LINK_CHANGE:
 		PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event");
 		vf->link_up = pf_msg->event_data.link_event.link_status;
-		vf->link_speed = pf_msg->event_data.link_event_adv.link_speed;
+		if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
+			vf->link_speed =
+				pf_msg->event_data.link_event_adv.link_speed;
+		} else {
+			enum virtchnl_link_speed speed;
+			speed = pf_msg->event_data.link_event.link_speed;
+			vf->link_speed = iavf_convert_link_speed(speed);
+		}
 		iavf_dev_link_update(dev, 0);
 		_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
 					      NULL);
@@ -210,12 +253,9 @@ iavf_handle_virtchnl_msg(struct rte_eth_dev *dev)
 							info.msg_len);
 			} else {
 				/* read message and it's expected one */
-				if (msg_opc == vf->pend_cmd) {
-					vf->cmd_retval = msg_ret;
-					/* prevent compiler reordering */
-					rte_compiler_barrier();
-					_clear_cmd(vf);
-				} else
+				if (msg_opc == vf->pend_cmd)
+					_notify_cmd(vf, msg_ret);
+				else
 					PMD_DRV_LOG(ERR, "command mismatch,"
 						    "expect %u, get %u",
 						    vf->pend_cmd, msg_opc);
@@ -225,7 +265,7 @@ iavf_handle_virtchnl_msg(struct rte_eth_dev *dev)
 			}
 			break;
 		default:
-			PMD_DRV_LOG(ERR, "Request %u is not supported yet",
+			PMD_DRV_LOG(DEBUG, "Request %u is not supported yet",
 				    aq_opc);
 			break;
 		}
@@ -808,3 +848,59 @@ iavf_add_del_vlan(struct iavf_adapter *adapter, uint16_t vlanid, bool add)
 
 	return err;
 }
+
+int
+iavf_add_del_mc_addr_list(struct iavf_adapter *adapter,
+			struct rte_ether_addr *mc_addrs,
+			uint32_t mc_addrs_num, bool add)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
+	uint8_t cmd_buffer[sizeof(struct virtchnl_ether_addr_list) +
+		(IAVF_NUM_MACADDR_MAX * sizeof(struct virtchnl_ether_addr))];
+	struct virtchnl_ether_addr_list *list;
+	struct iavf_cmd_info args;
+	uint32_t i;
+	int err;
+
+	if (mc_addrs == NULL || mc_addrs_num == 0)
+		return 0;
+
+	if (mc_addrs_num > IAVF_NUM_MACADDR_MAX)
+		return -EINVAL;
+
+	list = (struct virtchnl_ether_addr_list *)cmd_buffer;
+	list->vsi_id = vf->vsi_res->vsi_id;
+	list->num_elements = mc_addrs_num;
+
+	for (i = 0; i < mc_addrs_num; i++) {
+		if (!IAVF_IS_MULTICAST(mc_addrs[i].addr_bytes)) {
+			PMD_DRV_LOG(ERR, "Invalid mac:%x:%x:%x:%x:%x:%x",
+				    mc_addrs[i].addr_bytes[0],
+				    mc_addrs[i].addr_bytes[1],
+				    mc_addrs[i].addr_bytes[2],
+				    mc_addrs[i].addr_bytes[3],
+				    mc_addrs[i].addr_bytes[4],
+				    mc_addrs[i].addr_bytes[5]);
+			return -EINVAL;
+		}
+
+		memcpy(list->list[i].addr, mc_addrs[i].addr_bytes,
+			sizeof(list->list[i].addr));
+	}
+
+	args.ops = add ? VIRTCHNL_OP_ADD_ETH_ADDR : VIRTCHNL_OP_DEL_ETH_ADDR;
+	args.in_args = cmd_buffer;
+	args.in_args_size = sizeof(struct virtchnl_ether_addr_list) +
+		i * sizeof(struct virtchnl_ether_addr);
+	args.out_buffer = vf->aq_resp;
+	args.out_size = IAVF_AQ_BUF_SZ;
+	err = iavf_execute_vf_cmd(adapter, &args);
+
+	if (err) {
+		PMD_DRV_LOG(ERR, "fail to execute command %s",
+			add ? "OP_ADD_ETH_ADDR" : "OP_DEL_ETH_ADDR");
+		return err;
+	}
+
+	return 0;
+}
diff --git a/dpdk/drivers/net/ice/base/ice_adminq_cmd.h b/dpdk/drivers/net/ice/base/ice_adminq_cmd.h
index e6a1350baa..a99670d51e 100644
--- a/dpdk/drivers/net/ice/base/ice_adminq_cmd.h
+++ b/dpdk/drivers/net/ice/base/ice_adminq_cmd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_ADMINQ_CMD_H_
@@ -158,13 +158,11 @@ struct ice_aqc_manage_mac_write {
 #define ICE_AQC_MAN_MAC_WR_MC_MAG_EN		BIT(0)
 #define ICE_AQC_MAN_MAC_WR_WOL_LAA_PFR_KEEP	BIT(1)
 #define ICE_AQC_MAN_MAC_WR_S		6
-#define ICE_AQC_MAN_MAC_WR_M		(3 << ICE_AQC_MAN_MAC_WR_S)
+#define ICE_AQC_MAN_MAC_WR_M		MAKEMASK(3, ICE_AQC_MAN_MAC_WR_S)
 #define ICE_AQC_MAN_MAC_UPDATE_LAA	0
-#define ICE_AQC_MAN_MAC_UPDATE_LAA_WOL	(BIT(0) << ICE_AQC_MAN_MAC_WR_S)
-	/* High 16 bits of MAC address in big endian order */
-	__be16 sah;
-	/* Low 32 bits of MAC address in big endian order */
-	__be32 sal;
+#define ICE_AQC_MAN_MAC_UPDATE_LAA_WOL	BIT(ICE_AQC_MAN_MAC_WR_S)
+	/* byte stream in network order */
+	u8 mac_addr[ETH_ALEN];
 	__le32 addr_high;
 	__le32 addr_low;
 };
@@ -1937,7 +1935,7 @@ struct ice_aqc_get_set_rss_keys {
 struct ice_aqc_get_set_rss_lut {
 #define ICE_AQC_GSET_RSS_LUT_VSI_VALID	BIT(15)
 #define ICE_AQC_GSET_RSS_LUT_VSI_ID_S	0
-#define ICE_AQC_GSET_RSS_LUT_VSI_ID_M	(0x1FF << ICE_AQC_GSET_RSS_LUT_VSI_ID_S)
+#define ICE_AQC_GSET_RSS_LUT_VSI_ID_M	(0x3FF << ICE_AQC_GSET_RSS_LUT_VSI_ID_S)
 	__le16 vsi_id;
 #define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_S	0
 #define ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_M	\
@@ -2166,8 +2164,8 @@ struct ice_aqc_event_lan_overflow {
  * @opcode: AQ command opcode
  * @datalen: length in bytes of indirect/external data buffer
  * @retval: return value from firmware
- * @cookie_h: opaque data high-half
- * @cookie_l: opaque data low-half
+ * @cookie_high: opaque data high-half
+ * @cookie_low: opaque data low-half
  * @params: command-specific parameters
  *
  * Descriptor format for commands the driver posts on the Admin Transmit Queue
diff --git a/dpdk/drivers/net/ice/base/ice_alloc.h b/dpdk/drivers/net/ice/base/ice_alloc.h
index cf823a2c2a..cfe9199403 100644
--- a/dpdk/drivers/net/ice/base/ice_alloc.h
+++ b/dpdk/drivers/net/ice/base/ice_alloc.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_ALLOC_H_
diff --git a/dpdk/drivers/net/ice/base/ice_bitops.h b/dpdk/drivers/net/ice/base/ice_bitops.h
index 32f64cac0c..0344437c9e 100644
--- a/dpdk/drivers/net/ice/base/ice_bitops.h
+++ b/dpdk/drivers/net/ice/base/ice_bitops.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_BITOPS_H_
diff --git a/dpdk/drivers/net/ice/base/ice_common.c b/dpdk/drivers/net/ice/base/ice_common.c
index 4ba3ab2028..25e30b937b 100644
--- a/dpdk/drivers/net/ice/base/ice_common.c
+++ b/dpdk/drivers/net/ice/base/ice_common.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
@@ -9,7 +9,7 @@
 #include "ice_flow.h"
 #include "ice_switch.h"
 
-#define ICE_PF_RESET_WAIT_COUNT	200
+#define ICE_PF_RESET_WAIT_COUNT	300
 
 /**
  * ice_set_mac_type - Sets MAC type
@@ -461,6 +461,7 @@ static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
 		return ICE_ERR_NO_MEMORY;
 
 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
+	sw->prof_res_bm_init = 0;
 
 	return ice_init_def_sw_recp(hw);
 }
@@ -674,6 +675,7 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
 			  "Failed to get scheduler allocated resources\n");
 		goto err_unroll_alloc;
 	}
+	ice_sched_get_psm_clk_freq(hw);
 
 	/* Initialize port_info struct with scheduler data */
 	status = ice_sched_init_port(hw->port_info);
@@ -2120,10 +2122,7 @@ ice_aq_manage_mac_write(struct ice_hw *hw, const u8 *mac_addr, u8 flags,
 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_manage_mac_write);
 
 	cmd->flags = flags;
-
-	/* Prep values for flags, sah, sal */
-	cmd->sah = HTONS(*((const u16 *)mac_addr));
-	cmd->sal = HTONL(*((const u32 *)(mac_addr + 2)));
+	ice_memcpy(cmd->mac_addr, mac_addr, ETH_ALEN, ICE_NONDMA_TO_DMA);
 
 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 }
diff --git a/dpdk/drivers/net/ice/base/ice_common.h b/dpdk/drivers/net/ice/base/ice_common.h
index c73184499f..63b733d74f 100644
--- a/dpdk/drivers/net/ice/base/ice_common.h
+++ b/dpdk/drivers/net/ice/base/ice_common.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_COMMON_H_
diff --git a/dpdk/drivers/net/ice/base/ice_controlq.c b/dpdk/drivers/net/ice/base/ice_controlq.c
index 8a65fae40e..0b651e7db3 100644
--- a/dpdk/drivers/net/ice/base/ice_controlq.c
+++ b/dpdk/drivers/net/ice/base/ice_controlq.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
@@ -180,7 +180,9 @@ ice_alloc_rq_bufs(struct ice_hw *hw, struct ice_ctl_q_info *cq)
 	i--;
 	for (; i >= 0; i--)
 		ice_free_dma_mem(hw, &cq->rq.r.rq_bi[i]);
+	cq->rq.r.rq_bi = NULL;
 	ice_free(hw, cq->rq.dma_head);
+	cq->rq.dma_head = NULL;
 
 	return ICE_ERR_NO_MEMORY;
 }
@@ -218,7 +220,9 @@ ice_alloc_sq_bufs(struct ice_hw *hw, struct ice_ctl_q_info *cq)
 	i--;
 	for (; i >= 0; i--)
 		ice_free_dma_mem(hw, &cq->sq.r.sq_bi[i]);
+	cq->sq.r.sq_bi = NULL;
 	ice_free(hw, cq->sq.dma_head);
+	cq->sq.dma_head = NULL;
 
 	return ICE_ERR_NO_MEMORY;
 }
@@ -277,6 +281,24 @@ ice_cfg_rq_regs(struct ice_hw *hw, struct ice_ctl_q_info *cq)
 	return ICE_SUCCESS;
 }
 
+#define ICE_FREE_CQ_BUFS(hw, qi, ring)					\
+do {									\
+	/* free descriptors */						\
+	if ((qi)->ring.r.ring##_bi) {					\
+		int i;							\
+									\
+		for (i = 0; i < (qi)->num_##ring##_entries; i++)	\
+			if ((qi)->ring.r.ring##_bi[i].pa)		\
+				ice_free_dma_mem((hw),			\
+					&(qi)->ring.r.ring##_bi[i]);	\
+	}								\
+	/* free the buffer info list */					\
+	if ((qi)->ring.cmd_buf)						\
+		ice_free(hw, (qi)->ring.cmd_buf);			\
+	/* free DMA head */						\
+	ice_free(hw, (qi)->ring.dma_head);				\
+} while (0)
+
 /**
  * ice_init_sq - main initialization routine for Control ATQ
  * @hw: pointer to the hardware structure
@@ -332,6 +354,7 @@ static enum ice_status ice_init_sq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
 	goto init_ctrlq_exit;
 
 init_ctrlq_free_rings:
+	ICE_FREE_CQ_BUFS(hw, cq, sq);
 	ice_free_cq_ring(hw, &cq->sq);
 
 init_ctrlq_exit:
@@ -393,27 +416,13 @@ static enum ice_status ice_init_rq(struct ice_hw *hw, struct ice_ctl_q_info *cq)
 	goto init_ctrlq_exit;
 
 init_ctrlq_free_rings:
+	ICE_FREE_CQ_BUFS(hw, cq, rq);
 	ice_free_cq_ring(hw, &cq->rq);
 
 init_ctrlq_exit:
 	return ret_code;
 }
 
-#define ICE_FREE_CQ_BUFS(hw, qi, ring)					\
-do {									\
-	int i;								\
-	/* free descriptors */						\
-	for (i = 0; i < (qi)->num_##ring##_entries; i++)		\
-		if ((qi)->ring.r.ring##_bi[i].pa)			\
-			ice_free_dma_mem((hw),				\
-					 &(qi)->ring.r.ring##_bi[i]);	\
-	/* free the buffer info list */					\
-	if ((qi)->ring.cmd_buf)						\
-		ice_free(hw, (qi)->ring.cmd_buf);			\
-	/* free DMA head */						\
-	ice_free(hw, (qi)->ring.dma_head);				\
-} while (0)
-
 /**
  * ice_shutdown_sq - shutdown the Control ATQ
  * @hw: pointer to the hardware structure
diff --git a/dpdk/drivers/net/ice/base/ice_controlq.h b/dpdk/drivers/net/ice/base/ice_controlq.h
index 8b60465474..423d171141 100644
--- a/dpdk/drivers/net/ice/base/ice_controlq.h
+++ b/dpdk/drivers/net/ice/base/ice_controlq.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_CONTROLQ_H_
diff --git a/dpdk/drivers/net/ice/base/ice_dcb.c b/dpdk/drivers/net/ice/base/ice_dcb.c
index 7048dbd02f..8918188193 100644
--- a/dpdk/drivers/net/ice/base/ice_dcb.c
+++ b/dpdk/drivers/net/ice/base/ice_dcb.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
diff --git a/dpdk/drivers/net/ice/base/ice_dcb.h b/dpdk/drivers/net/ice/base/ice_dcb.h
index 9a0968f5b8..3ffeb864cc 100644
--- a/dpdk/drivers/net/ice/base/ice_dcb.h
+++ b/dpdk/drivers/net/ice/base/ice_dcb.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_DCB_H_
diff --git a/dpdk/drivers/net/ice/base/ice_devids.h b/dpdk/drivers/net/ice/base/ice_devids.h
index 348d1907a4..8f778d918c 100644
--- a/dpdk/drivers/net/ice/base/ice_devids.h
+++ b/dpdk/drivers/net/ice/base/ice_devids.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_DEVIDS_H_
diff --git a/dpdk/drivers/net/ice/base/ice_fdir.c b/dpdk/drivers/net/ice/base/ice_fdir.c
index 37b3881696..033f6ccb4e 100644
--- a/dpdk/drivers/net/ice/base/ice_fdir.c
+++ b/dpdk/drivers/net/ice/base/ice_fdir.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
@@ -430,6 +430,10 @@ ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
 	if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) {
 		fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES;
 		fdir_fltr_ctx.qindex = 0;
+	} else if (input->dest_ctl ==
+			ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER) {
+		fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
+		fdir_fltr_ctx.qindex = 0;
 	} else {
 		if (input->dest_ctl ==
 		    ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP)
@@ -441,13 +445,16 @@ ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
 	fdir_fltr_ctx.cnt_index = input->cnt_index;
 	fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
 	fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
-	fdir_fltr_ctx.toq_prio = 3;
+	if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER)
+		fdir_fltr_ctx.toq_prio = 0;
+	else
+		fdir_fltr_ctx.toq_prio = 3;
 	fdir_fltr_ctx.pcmd = (add) ? ICE_FXD_FLTR_QW1_PCMD_ADD :
 		ICE_FXD_FLTR_QW1_PCMD_REMOVE;
 	fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
 	fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
 	fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;
-	fdir_fltr_ctx.fdid_prio = 3;
+	fdir_fltr_ctx.fdid_prio = input->fdid_prio;
 	fdir_fltr_ctx.desc_prof = 1;
 	fdir_fltr_ctx.desc_prof_prio = 3;
 	ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);
@@ -786,6 +793,10 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
 	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP:
 	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP:
 	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER:
+		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
+					input->ip.v4.src_ip);
+		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
+					input->ip.v4.dst_ip);
 		ice_pkt_insert_u32(loc, ICE_IPV4_GTPU_TEID_OFFSET,
 				   input->gtpu_data.teid);
 		ice_pkt_insert_u6_qfi(loc, ICE_IPV4_GTPU_QFI_OFFSET,
diff --git a/dpdk/drivers/net/ice/base/ice_fdir.h b/dpdk/drivers/net/ice/base/ice_fdir.h
index db1f8351f9..2cb7291eb1 100644
--- a/dpdk/drivers/net/ice/base/ice_fdir.h
+++ b/dpdk/drivers/net/ice/base/ice_fdir.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_FDIR_H_
@@ -151,9 +151,9 @@ struct ice_fdir_v6 {
 struct ice_fdir_udp_gtp {
 	u8 flags;
 	u8 msg_type;
-	u16 rsrvd_len;
-	u32 teid;
-	u16 rsrvd_seq_nbr;
+	__be16 rsrvd_len;
+	__be32 teid;
+	__be16 rsrvd_seq_nbr;
 	u8 rsrvd_n_pdu_nbr;
 	u8 rsrvd_next_ext_type;
 	u8 rsvrd_ext_len;
@@ -202,6 +202,7 @@ struct ice_fdir_fltr {
 	u8 cnt_ena;
 	u8 fltr_status;
 	u16 cnt_index;
+	u8 fdid_prio;
 	u32 fltr_id;
 };
 
diff --git a/dpdk/drivers/net/ice/base/ice_flex_pipe.c b/dpdk/drivers/net/ice/base/ice_flex_pipe.c
index e8d4bbee40..cc95a2e0d0 100644
--- a/dpdk/drivers/net/ice/base/ice_flex_pipe.c
+++ b/dpdk/drivers/net/ice/base/ice_flex_pipe.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
@@ -610,7 +610,7 @@ ice_gen_key_word(u8 val, u8 valid, u8 dont_care, u8 nvr_mtch, u8 *key,
 static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max)
 {
 	u16 count = 0;
-	u16 i, j;
+	u16 i;
 
 	/* check each byte */
 	for (i = 0; i < size; i++) {
@@ -626,11 +626,9 @@ static bool ice_bits_max_set(const u8 *mask, u16 size, u16 max)
 			return false;
 
 		/* count the bits in this byte, checking threshold */
-		for (j = 0; j < BITS_PER_BYTE; j++) {
-			count += (mask[i] & (0x1 << j)) ? 1 : 0;
-			if (count > max)
-				return false;
-		}
+		count += ice_hweight8(mask[i]);
+		if (count > max)
+			return false;
 	}
 
 	return true;
@@ -914,9 +912,8 @@ ice_update_pkg(struct ice_hw *hw, struct ice_buf *bufs, u32 count)
 		return status;
 
 	for (i = 0; i < count; i++) {
-		bool last = ((i + 1) == count);
-
 		struct ice_buf_hdr *bh = (struct ice_buf_hdr *)(bufs + i);
+		bool last = ((i + 1) == count);
 
 		status = ice_aq_update_pkg(hw, bh, LE16_TO_CPU(bh->data_end),
 					   last, &offset, &info, NULL);
@@ -1566,7 +1563,7 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type type,
  * allocated for every list entry.
  */
 enum ice_status
-ice_get_sw_fv_list(struct ice_hw *hw, u16 *prot_ids, u8 ids_cnt,
+ice_get_sw_fv_list(struct ice_hw *hw, u16 *prot_ids, u16 ids_cnt,
 		   ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list)
 {
 	struct ice_sw_fv_list_entry *fvl;
@@ -1583,7 +1580,7 @@ ice_get_sw_fv_list(struct ice_hw *hw, u16 *prot_ids, u8 ids_cnt,
 
 	ice_seg = hw->seg;
 	do {
-		u8 i;
+		u16 i;
 
 		fv = (struct ice_fv *)
 			ice_pkg_enum_entry(ice_seg, &state, ICE_SID_FLD_VEC_SW,
@@ -1807,7 +1804,7 @@ static u16 ice_pkg_buf_get_active_sections(struct ice_buf_build *bld)
 }
 
 /**
- * ice_pkg_buf_header
+ * ice_pkg_buf
  * @bld: pointer to pkg build (allocated by ice_pkg_buf_alloc())
  *
  * Return a pointer to the buffer's header
@@ -1916,9 +1913,11 @@ ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type,
  * ice_create_tunnel
  * @hw: pointer to the HW structure
  * @type: type of tunnel
- * @port: port to use for vxlan tunnel
+ * @port: port of tunnel to create
  *
- * Creates a tunnel
+ * Create a tunnel by updating the parse graph in the parser. We do that by
+ * creating a package buffer with the tunnel info and issuing an update package
+ * command.
  */
 enum ice_status
 ice_create_tunnel(struct ice_hw *hw, enum ice_tunnel_type type, u16 port)
@@ -2001,7 +2000,7 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all)
 	struct ice_buf_build *bld;
 	u16 count = 0;
 	u16 size;
-	u16 i;
+	u16 i, j;
 
 	/* determine count */
 	for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
@@ -2028,30 +2027,31 @@ enum ice_status ice_destroy_tunnel(struct ice_hw *hw, u16 port, bool all)
 					  size);
 	if (!sect_rx)
 		goto ice_destroy_tunnel_err;
-	sect_rx->count = CPU_TO_LE16(1);
+	sect_rx->count = CPU_TO_LE16(count);
 
 	sect_tx = (struct ice_boost_tcam_section *)
 		ice_pkg_buf_alloc_section(bld, ICE_SID_TXPARSER_BOOST_TCAM,
 					  size);
 	if (!sect_tx)
 		goto ice_destroy_tunnel_err;
-	sect_tx->count = CPU_TO_LE16(1);
+	sect_tx->count = CPU_TO_LE16(count);
 
 	/* copy original boost entry to update package buffer, one copy to Rx
 	 * section, another copy to the Tx section
 	 */
-	for (i = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
+	for (i = 0, j = 0; i < hw->tnl.count && i < ICE_TUNNEL_MAX_ENTRIES; i++)
 		if (hw->tnl.tbl[i].valid && hw->tnl.tbl[i].in_use &&
 		    (all || hw->tnl.tbl[i].port == port)) {
-			ice_memcpy(sect_rx->tcam + i,
+			ice_memcpy(sect_rx->tcam + j,
 				   hw->tnl.tbl[i].boost_entry,
 				   sizeof(*sect_rx->tcam),
 				   ICE_NONDMA_TO_NONDMA);
-			ice_memcpy(sect_tx->tcam + i,
+			ice_memcpy(sect_tx->tcam + j,
 				   hw->tnl.tbl[i].boost_entry,
 				   sizeof(*sect_tx->tcam),
 				   ICE_NONDMA_TO_NONDMA);
 			hw->tnl.tbl[i].marked = true;
+			j++;
 		}
 
 	status = ice_update_pkg(hw, ice_pkg_buf(bld), 1);
@@ -2684,6 +2684,12 @@ ice_find_prof_id_with_mask(struct ice_hw *hw, enum ice_block blk,
 	struct ice_es *es = &hw->blk[blk].es;
 	u16 i;
 
+	/* For FD and RSS, we don't want to re-use an existed profile with the
+	 * same field vector and mask. This will cause rule interference.
+	 */
+	if (blk == ICE_BLK_FD || blk == ICE_BLK_RSS)
+		return ICE_ERR_DOES_NOT_EXIST;
+
 	for (i = 0; i < es->count; i++) {
 		u16 off = i * es->fvw;
 
@@ -3832,6 +3838,7 @@ ice_vsig_get_ref(struct ice_hw *hw, enum ice_block blk, u16 vsig, u16 *refs)
 {
 	u16 idx = vsig & ICE_VSIG_IDX_M;
 	struct ice_vsig_vsi *ptr;
+
 	*refs = 0;
 
 	if (!hw->blk[blk].xlt2.vsig_tbl[idx].in_use)
@@ -4038,12 +4045,12 @@ ice_upd_prof_hw(struct ice_hw *hw, enum ice_block blk,
 	struct ice_buf_build *b;
 	struct ice_chs_chg *tmp;
 	enum ice_status status;
-	u16 pkg_sects = 0;
-	u16 sects = 0;
+	u16 pkg_sects;
 	u16 xlt1 = 0;
 	u16 xlt2 = 0;
 	u16 tcam = 0;
 	u16 es = 0;
+	u16 sects;
 
 	/* count number of sections we need */
 	LIST_FOR_EACH_ENTRY(tmp, chgs, ice_chs_chg, list_entry) {
@@ -4142,8 +4149,6 @@ static void ice_update_fd_mask(struct ice_hw *hw, u16 prof_id, u32 mask_sel)
 		  GLQF_FDMASK_SEL(prof_id), mask_sel);
 }
 
-#define ICE_SRC_DST_MAX_COUNT	8
-
 struct ice_fd_src_dst_pair {
 	u8 prot_id;
 	u8 count;
@@ -4702,9 +4707,7 @@ ice_rem_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig,
 		} while (vsi_cur);
 	}
 
-	status = ice_vsig_free(hw, blk, vsig);
-
-	return status;
+	return ice_vsig_free(hw, blk, vsig);
 }
 
 /**
@@ -4922,8 +4925,8 @@ static enum ice_status
 ice_add_prof_to_lst(struct ice_hw *hw, enum ice_block blk,
 		    struct LIST_HEAD_TYPE *lst, u64 hdl)
 {
-	struct ice_vsig_prof *p;
 	struct ice_prof_map *map;
+	struct ice_vsig_prof *p;
 	u16 i;
 
 	map = ice_search_prof_id(hw, blk, hdl);
@@ -5200,7 +5203,7 @@ ice_add_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsig, u64 hdl,
 	/* new VSIG profile structure */
 	t = (struct ice_vsig_prof *)ice_malloc(hw, sizeof(*t));
 	if (!t)
-		goto err_ice_add_prof_id_vsig;
+		return ICE_ERR_NO_MEMORY;
 
 	t->profile_cookie = map->profile_cookie;
 	t->prof_id = map->prof_id;
@@ -5319,7 +5322,7 @@ ice_create_prof_id_vsig(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl,
 }
 
 /**
- * ice_create_vsig_from_list - create a new VSIG with a list of profiles
+ * ice_create_vsig_from_lst - create a new VSIG with a list of profiles
  * @hw: pointer to the HW struct
  * @blk: hardware block
  * @vsi: the initial VSI that will be in VSIG
@@ -5445,13 +5448,11 @@ ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)
 	struct ice_vsig_prof *tmp1, *del1;
 	struct LIST_HEAD_TYPE union_lst;
 	struct ice_chs_chg *tmp, *del;
-	struct LIST_HEAD_TYPE chrs;
 	struct LIST_HEAD_TYPE chg;
 	enum ice_status status;
-	u16 vsig, or_vsig = 0;
+	u16 vsig;
 
 	INIT_LIST_HEAD(&union_lst);
-	INIT_LIST_HEAD(&chrs);
 	INIT_LIST_HEAD(&chg);
 
 	/* Get profile */
@@ -5463,6 +5464,7 @@ ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)
 	status = ice_vsig_find_vsi(hw, blk, vsi, &vsig);
 	if (!status && vsig) {
 		bool only_vsi;
+		u16 or_vsig;
 		u16 ref;
 
 		/* found in vsig */
@@ -5572,11 +5574,6 @@ ice_add_prof_id_flow(struct ice_hw *hw, enum ice_block blk, u16 vsi, u64 hdl)
 		ice_free(hw, del1);
 	}
 
-	LIST_FOR_EACH_ENTRY_SAFE(del1, tmp1, &chrs, ice_vsig_prof, list) {
-		LIST_DEL(&del1->list);
-		ice_free(hw, del1);
-	}
-
 	return status;
 }
 
diff --git a/dpdk/drivers/net/ice/base/ice_flex_pipe.h b/dpdk/drivers/net/ice/base/ice_flex_pipe.h
index ee606af15a..10f328b652 100644
--- a/dpdk/drivers/net/ice/base/ice_flex_pipe.h
+++ b/dpdk/drivers/net/ice/base/ice_flex_pipe.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_FLEX_PIPE_H_
@@ -36,7 +36,7 @@ ice_get_sw_fv_bitmap(struct ice_hw *hw, enum ice_prof_type type,
 void
 ice_init_prof_result_bm(struct ice_hw *hw);
 enum ice_status
-ice_get_sw_fv_list(struct ice_hw *hw, u16 *prot_ids, u8 ids_cnt,
+ice_get_sw_fv_list(struct ice_hw *hw, u16 *prot_ids, u16 ids_cnt,
 		   ice_bitmap_t *bm, struct LIST_HEAD_TYPE *fv_list);
 bool
 ice_get_open_tunnel_port(struct ice_hw *hw, enum ice_tunnel_type type,
diff --git a/dpdk/drivers/net/ice/base/ice_flex_type.h b/dpdk/drivers/net/ice/base/ice_flex_type.h
index 1be98ea521..7708ced40a 100644
--- a/dpdk/drivers/net/ice/base/ice_flex_type.h
+++ b/dpdk/drivers/net/ice/base/ice_flex_type.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_FLEX_TYPE_H_
diff --git a/dpdk/drivers/net/ice/base/ice_flow.c b/dpdk/drivers/net/ice/base/ice_flow.c
index 391df1b540..277bb4a276 100644
--- a/dpdk/drivers/net/ice/base/ice_flow.c
+++ b/dpdk/drivers/net/ice/base/ice_flow.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
@@ -548,11 +548,41 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
 				(const ice_bitmap_t *)ice_ptypes_ipv4_il;
 			ice_and_bitmap(params->ptypes, params->ptypes, src,
 				       ICE_FLOW_PTYPE_MAX);
+			if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
+				src = (const ice_bitmap_t *)ice_ptypes_udp_il;
+				ice_and_bitmap(params->ptypes,
+						params->ptypes, src,
+					       ICE_FLOW_PTYPE_MAX);
+			} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
+				ice_and_bitmap(params->ptypes, params->ptypes,
+					       (const ice_bitmap_t *)
+					       ice_ptypes_tcp_il,
+					       ICE_FLOW_PTYPE_MAX);
+			} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
+				src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
+				ice_and_bitmap(params->ptypes, params->ptypes,
+					       src, ICE_FLOW_PTYPE_MAX);
+			}
 		} else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) {
 			src = !i ? (const ice_bitmap_t *)ice_ptypes_ipv6_ofos :
 				(const ice_bitmap_t *)ice_ptypes_ipv6_il;
 			ice_and_bitmap(params->ptypes, params->ptypes, src,
 				       ICE_FLOW_PTYPE_MAX);
+			if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
+				src = (const ice_bitmap_t *)ice_ptypes_udp_il;
+				ice_and_bitmap(params->ptypes,
+						params->ptypes, src,
+					       ICE_FLOW_PTYPE_MAX);
+			} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
+				ice_and_bitmap(params->ptypes, params->ptypes,
+					       (const ice_bitmap_t *)
+					       ice_ptypes_tcp_il,
+					       ICE_FLOW_PTYPE_MAX);
+			} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
+				src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
+				ice_and_bitmap(params->ptypes, params->ptypes,
+					       src, ICE_FLOW_PTYPE_MAX);
+			}
 		}
 
 		if (hdrs & ICE_FLOW_SEG_HDR_ICMP) {
@@ -560,18 +590,6 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
 				(const ice_bitmap_t *)ice_ptypes_icmp_il;
 			ice_and_bitmap(params->ptypes, params->ptypes, src,
 				       ICE_FLOW_PTYPE_MAX);
-		} else if (hdrs & ICE_FLOW_SEG_HDR_UDP) {
-			src = (const ice_bitmap_t *)ice_ptypes_udp_il;
-			ice_and_bitmap(params->ptypes, params->ptypes, src,
-				       ICE_FLOW_PTYPE_MAX);
-		} else if (hdrs & ICE_FLOW_SEG_HDR_TCP) {
-			ice_and_bitmap(params->ptypes, params->ptypes,
-				       (const ice_bitmap_t *)ice_ptypes_tcp_il,
-				       ICE_FLOW_PTYPE_MAX);
-		} else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) {
-			src = (const ice_bitmap_t *)ice_ptypes_sctp_il;
-			ice_and_bitmap(params->ptypes, params->ptypes, src,
-				       ICE_FLOW_PTYPE_MAX);
 		} else if (hdrs & ICE_FLOW_SEG_HDR_GRE) {
 			if (!i) {
 				src = (const ice_bitmap_t *)ice_ptypes_gre_of;
@@ -586,10 +604,6 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
 			src = (const ice_bitmap_t *)ice_ptypes_gtpc_tid;
 			ice_and_bitmap(params->ptypes, params->ptypes,
 				       src, ICE_FLOW_PTYPE_MAX);
-		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU) {
-			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
-			ice_and_bitmap(params->ptypes, params->ptypes,
-				       src, ICE_FLOW_PTYPE_MAX);
 		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_EH) {
 			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
 			ice_and_bitmap(params->ptypes, params->ptypes,
@@ -598,6 +612,10 @@ ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params)
 			/* Attributes for GTP packet with Extension Header */
 			params->attr = ice_attr_gtpu_eh;
 			params->attr_cnt = ARRAY_SIZE(ice_attr_gtpu_eh);
+		} else if (hdrs & ICE_FLOW_SEG_HDR_GTPU_IP) {
+			src = (const ice_bitmap_t *)ice_ptypes_gtpu;
+			ice_and_bitmap(params->ptypes, params->ptypes,
+				       src, ICE_FLOW_PTYPE_MAX);
 		}
 	}
 
@@ -1162,7 +1180,7 @@ ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk,
 		       struct ice_flow_prof **prof)
 {
 	struct ice_flow_prof_params params;
-	enum ice_status status = ICE_SUCCESS;
+	enum ice_status status;
 	u8 i;
 
 	if (!prof || (acts_cnt && !acts))
@@ -1835,14 +1853,11 @@ void ice_rem_vsi_rss_list(struct ice_hw *hw, u16 vsi_handle)
 	ice_acquire_lock(&hw->rss_locks);
 	LIST_FOR_EACH_ENTRY_SAFE(r, tmp, &hw->rss_list_head,
 				 ice_rss_cfg, l_entry) {
-		if (ice_is_bit_set(r->vsis, vsi_handle)) {
-			ice_clear_bit(vsi_handle, r->vsis);
-
+		if (ice_test_and_clear_bit(vsi_handle, r->vsis))
 			if (!ice_is_any_bit_set(r->vsis, ICE_MAX_VSI)) {
 				LIST_DEL(&r->l_entry);
 				ice_free(hw, r);
 			}
-		}
 	}
 	ice_release_lock(&hw->rss_locks);
 }
@@ -2109,6 +2124,13 @@ ice_add_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
 	if (status)
 		goto exit;
 
+	/* don't do RSS for GTPU outer */
+	if (segs_cnt == ICE_RSS_OUTER_HEADERS &&
+	    segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
+		status = ICE_SUCCESS;
+		goto exit;
+	}
+
 	/* Search for a flow profile that has matching headers, hash fields
 	 * and has the input VSI associated to it. If found, no further
 	 * operations required and exit.
@@ -2225,6 +2247,7 @@ ice_add_rss_cfg(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
 	ice_acquire_lock(&hw->rss_locks);
 	status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds, addl_hdrs,
 				      ICE_RSS_OUTER_HEADERS, symm);
+
 	if (!status)
 		status = ice_add_rss_cfg_sync(hw, vsi_handle, hashed_flds,
 					      addl_hdrs, ICE_RSS_INNER_HEADERS,
@@ -2264,6 +2287,12 @@ ice_rem_rss_cfg_sync(struct ice_hw *hw, u16 vsi_handle, u64 hashed_flds,
 	if (status)
 		goto out;
 
+	if (segs_cnt == ICE_RSS_OUTER_HEADERS &&
+	    segs[segs_cnt - 1].hdrs & ICE_FLOW_SEG_HDR_GTPU) {
+		status = ICE_SUCCESS;
+		goto out;
+	}
+
 	prof = ice_flow_find_prof_conds(hw, blk, ICE_FLOW_RX, segs, segs_cnt,
 					vsi_handle,
 					ICE_FLOW_FIND_PROF_CHK_FLDS);
diff --git a/dpdk/drivers/net/ice/base/ice_flow.h b/dpdk/drivers/net/ice/base/ice_flow.h
index 4686274af8..9b314a1eaa 100644
--- a/dpdk/drivers/net/ice/base/ice_flow.h
+++ b/dpdk/drivers/net/ice/base/ice_flow.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_FLOW_H_
@@ -118,6 +118,7 @@ enum ice_flow_seg_hdr {
  * ICE_FLOW_SEG_HDR_GTPU_UP           1              1
  */
 #define ICE_FLOW_SEG_HDR_GTPU (ICE_FLOW_SEG_HDR_GTPU_IP | \
+			       ICE_FLOW_SEG_HDR_GTPU_EH | \
 			       ICE_FLOW_SEG_HDR_GTPU_DWN | \
 			       ICE_FLOW_SEG_HDR_GTPU_UP)
 
@@ -187,6 +188,7 @@ enum ice_flow_avf_hdr_field {
 	ICE_AVF_FLOW_FIELD_IPV4_SCTP,
 	ICE_AVF_FLOW_FIELD_IPV4_OTHER,
 	ICE_AVF_FLOW_FIELD_FRAG_IPV4,
+	/* Values 37-38 are reserved */
 	ICE_AVF_FLOW_FIELD_UNICAST_IPV6_UDP	= 39,
 	ICE_AVF_FLOW_FIELD_MULTICAST_IPV6_UDP,
 	ICE_AVF_FLOW_FIELD_IPV6_UDP,
diff --git a/dpdk/drivers/net/ice/base/ice_hw_autogen.h b/dpdk/drivers/net/ice/base/ice_hw_autogen.h
index 92d432044d..1c9c84dfb4 100644
--- a/dpdk/drivers/net/ice/base/ice_hw_autogen.h
+++ b/dpdk/drivers/net/ice/base/ice_hw_autogen.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 /* Machine-generated file; do not edit */
diff --git a/dpdk/drivers/net/ice/base/ice_lan_tx_rx.h b/dpdk/drivers/net/ice/base/ice_lan_tx_rx.h
index a97c63cc97..51e30848f8 100644
--- a/dpdk/drivers/net/ice/base/ice_lan_tx_rx.h
+++ b/dpdk/drivers/net/ice/base/ice_lan_tx_rx.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_LAN_TX_RX_H_
diff --git a/dpdk/drivers/net/ice/base/ice_nvm.c b/dpdk/drivers/net/ice/base/ice_nvm.c
index 1dbfc2dcc7..434258b14c 100644
--- a/dpdk/drivers/net/ice/base/ice_nvm.c
+++ b/dpdk/drivers/net/ice/base/ice_nvm.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_common.h"
diff --git a/dpdk/drivers/net/ice/base/ice_nvm.h b/dpdk/drivers/net/ice/base/ice_nvm.h
index d5b7b2d196..8624d19b19 100644
--- a/dpdk/drivers/net/ice/base/ice_nvm.h
+++ b/dpdk/drivers/net/ice/base/ice_nvm.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_NVM_H_
diff --git a/dpdk/drivers/net/ice/base/ice_osdep.h b/dpdk/drivers/net/ice/base/ice_osdep.h
index 27c1830c5e..32ac8ac397 100644
--- a/dpdk/drivers/net/ice/base/ice_osdep.h
+++ b/dpdk/drivers/net/ice/base/ice_osdep.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018-2020 Intel Corporation
  */
 
 #ifndef _ICE_OSDEP_H_
@@ -24,6 +24,8 @@
 #include <rte_random.h>
 #include <rte_io.h>
 
+#include "ice_alloc.h"
+
 #include "../ice_logs.h"
 
 #define INLINE inline
@@ -176,7 +178,6 @@ struct ice_virt_mem {
 
 #define ice_memset(a, b, c, d) memset((a), (b), (c))
 #define ice_memcpy(a, b, c, d) rte_memcpy((a), (b), (c))
-#define ice_memdup(a, b, c, d) rte_memcpy(ice_malloc(a, c), b, c)
 
 #define CPU_TO_BE16(o) rte_cpu_to_be_16(o)
 #define CPU_TO_BE32(o) rte_cpu_to_be_32(o)
@@ -223,6 +224,19 @@ ice_destroy_lock(__attribute__((unused)) struct ice_lock *sp)
 
 struct ice_hw;
 
+static __rte_always_inline void *
+ice_memdup(__rte_unused struct ice_hw *hw, const void *src, size_t size,
+	   __rte_unused enum ice_memcpy_type dir)
+{
+	void *p;
+
+	p = ice_malloc(hw, size);
+	if (p)
+		rte_memcpy(p, src, size);
+
+	return p;
+}
+
 static inline void *
 ice_alloc_dma_mem(__attribute__((unused)) struct ice_hw *hw,
 		  struct ice_dma_mem *mem, u64 size)
@@ -343,6 +357,21 @@ static inline void list_add_tail(struct ice_list_entry *entry,
 				  member) :				       \
 		     0)
 
+#define LIST_FOR_EACH_ENTRY_SAFE(pos, tmp, head, type, member)		       \
+	for ((pos) = (head)->lh_first ?					       \
+		     container_of((head)->lh_first, struct type, member) :     \
+		     0,                                                        \
+		     (tmp) = (pos) == 0 ? 0 : ((pos)->member.next.le_next ?    \
+		     container_of((pos)->member.next.le_next, struct type,     \
+				  member) :				       \
+		     0);						       \
+	     (pos);							       \
+	     (pos) = (tmp),						       \
+	     (tmp) = (pos) == 0 ? 0 : ((tmp)->member.next.le_next ?	       \
+		     container_of((pos)->member.next.le_next, struct type,     \
+				  member) :				       \
+		     0))
+
 #define LIST_REPLACE_INIT(list_head, head) do {				\
 	(head)->lh_first = (list_head)->lh_first;			\
 	INIT_LIST_HEAD(list_head);					\
@@ -356,8 +385,6 @@ static inline void list_add_tail(struct ice_list_entry *entry,
 #define HLIST_DEL(entry)                       LIST_DEL(entry)
 #define HLIST_FOR_EACH_ENTRY(pos, head, type, member) \
 	LIST_FOR_EACH_ENTRY(pos, head, type, member)
-#define LIST_FOR_EACH_ENTRY_SAFE(pos, tmp, head, type, member) \
-	LIST_FOR_EACH_ENTRY(pos, head, type, member)
 
 #ifndef ICE_DBG_TRACE
 #define ICE_DBG_TRACE		BIT_ULL(0)
diff --git a/dpdk/drivers/net/ice/base/ice_protocol_type.h b/dpdk/drivers/net/ice/base/ice_protocol_type.h
index fdcbb2cad3..cbc7c37016 100644
--- a/dpdk/drivers/net/ice/base/ice_protocol_type.h
+++ b/dpdk/drivers/net/ice/base/ice_protocol_type.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_PROTOCOL_TYPE_H_
diff --git a/dpdk/drivers/net/ice/base/ice_sbq_cmd.h b/dpdk/drivers/net/ice/base/ice_sbq_cmd.h
index 70a019292a..22bfcebc3c 100644
--- a/dpdk/drivers/net/ice/base/ice_sbq_cmd.h
+++ b/dpdk/drivers/net/ice/base/ice_sbq_cmd.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_SBQ_CMD_H_
diff --git a/dpdk/drivers/net/ice/base/ice_sched.c b/dpdk/drivers/net/ice/base/ice_sched.c
index 553fc28ff3..3669688bd8 100644
--- a/dpdk/drivers/net/ice/base/ice_sched.c
+++ b/dpdk/drivers/net/ice/base/ice_sched.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_sched.h"
@@ -1357,7 +1357,7 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
 			 ice_memdup(hw, buf->layer_props,
 				    (hw->num_tx_sched_layers *
 				     sizeof(*hw->layer_info)),
-				    ICE_DMA_TO_DMA);
+				    ICE_NONDMA_TO_NONDMA);
 	if (!hw->layer_info) {
 		status = ICE_ERR_NO_MEMORY;
 		goto sched_query_out;
@@ -1368,6 +1368,46 @@ enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw)
 	return status;
 }
 
+/**
+ * ice_sched_get_psm_clk_freq - determine the PSM clock frequency
+ * @hw: pointer to the HW struct
+ *
+ * Determine the PSM clock frequency and store in HW struct
+ */
+void ice_sched_get_psm_clk_freq(struct ice_hw *hw)
+{
+	u32 val, clk_src;
+
+	val = rd32(hw, GLGEN_CLKSTAT_SRC);
+	clk_src = (val & GLGEN_CLKSTAT_SRC_PSM_CLK_SRC_M) >>
+		GLGEN_CLKSTAT_SRC_PSM_CLK_SRC_S;
+
+#define PSM_CLK_SRC_367_MHZ 0x0
+#define PSM_CLK_SRC_416_MHZ 0x1
+#define PSM_CLK_SRC_446_MHZ 0x2
+#define PSM_CLK_SRC_390_MHZ 0x3
+
+	switch (clk_src) {
+	case PSM_CLK_SRC_367_MHZ:
+		hw->psm_clk_freq = ICE_PSM_CLK_367MHZ_IN_HZ;
+		break;
+	case PSM_CLK_SRC_416_MHZ:
+		hw->psm_clk_freq = ICE_PSM_CLK_416MHZ_IN_HZ;
+		break;
+	case PSM_CLK_SRC_446_MHZ:
+		hw->psm_clk_freq = ICE_PSM_CLK_446MHZ_IN_HZ;
+		break;
+	case PSM_CLK_SRC_390_MHZ:
+		hw->psm_clk_freq = ICE_PSM_CLK_390MHZ_IN_HZ;
+		break;
+	default:
+		ice_debug(hw, ICE_DBG_SCHED, "PSM clk_src unexpected %u\n",
+			  clk_src);
+		/* fall back to a safe default */
+		hw->psm_clk_freq = ICE_PSM_CLK_446MHZ_IN_HZ;
+	}
+}
+
 /**
  * ice_sched_find_node_in_subtree - Find node in part of base node subtree
  * @hw: pointer to the HW struct
@@ -2188,7 +2228,7 @@ ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,
 		return ICE_ERR_PARAM;
 
 	/* Does parent have enough space */
-	if (parent->num_children + num_items >=
+	if (parent->num_children + num_items >
 	    hw->max_children[parent->tx_sched_layer])
 		return ICE_ERR_AQ_FULL;
 
@@ -2256,6 +2296,10 @@ ice_sched_move_vsi_to_agg(struct ice_port_info *pi, u16 vsi_handle, u32 agg_id,
 	if (!vsi_node)
 		return ICE_ERR_DOES_NOT_EXIST;
 
+	/* Is this VSI already part of given aggregator? */
+	if (ice_sched_find_node_in_subtree(pi->hw, agg_node, vsi_node))
+		return ICE_SUCCESS;
+
 	aggl = ice_sched_get_agg_layer(pi->hw);
 	vsil = ice_sched_get_vsi_layer(pi->hw);
 
@@ -2867,7 +2911,7 @@ ice_sched_update_elem(struct ice_hw *hw, struct ice_sched_node *node,
  */
 static enum ice_status
 ice_sched_cfg_node_bw_alloc(struct ice_hw *hw, struct ice_sched_node *node,
-			    enum ice_rl_type rl_type, u8 bw_alloc)
+			    enum ice_rl_type rl_type, u16 bw_alloc)
 {
 	struct ice_aqc_txsched_elem_data buf;
 	struct ice_aqc_txsched_elem *data;
@@ -3671,11 +3715,12 @@ ice_cfg_agg_bw_alloc(struct ice_port_info *pi, u32 agg_id, u8 ena_tcmap,
 
 /**
  * ice_sched_calc_wakeup - calculate RL profile wakeup parameter
+ * @hw: pointer to the HW struct
  * @bw: bandwidth in Kbps
  *
  * This function calculates the wakeup parameter of RL profile.
  */
-static u16 ice_sched_calc_wakeup(s32 bw)
+static u16 ice_sched_calc_wakeup(struct ice_hw *hw, s32 bw)
 {
 	s64 bytes_per_sec, wakeup_int, wakeup_a, wakeup_b, wakeup_f;
 	s32 wakeup_f_int;
@@ -3683,7 +3728,7 @@ static u16 ice_sched_calc_wakeup(s32 bw)
 
 	/* Get the wakeup integer value */
 	bytes_per_sec = DIV_64BIT(((s64)bw * 1000), BITS_PER_BYTE);
-	wakeup_int = DIV_64BIT(ICE_RL_PROF_FREQUENCY, bytes_per_sec);
+	wakeup_int = DIV_64BIT(hw->psm_clk_freq, bytes_per_sec);
 	if (wakeup_int > 63) {
 		wakeup = (u16)((1 << 15) | wakeup_int);
 	} else {
@@ -3692,7 +3737,7 @@ static u16 ice_sched_calc_wakeup(s32 bw)
 		 */
 		wakeup_b = (s64)ICE_RL_PROF_MULTIPLIER * wakeup_int;
 		wakeup_a = DIV_64BIT((s64)ICE_RL_PROF_MULTIPLIER *
-				     ICE_RL_PROF_FREQUENCY, bytes_per_sec);
+				     hw->psm_clk_freq, bytes_per_sec);
 
 		/* Get Fraction value */
 		wakeup_f = wakeup_a - wakeup_b;
@@ -3712,13 +3757,15 @@ static u16 ice_sched_calc_wakeup(s32 bw)
 
 /**
  * ice_sched_bw_to_rl_profile - convert BW to profile parameters
+ * @hw: pointer to the HW struct
  * @bw: bandwidth in Kbps
  * @profile: profile parameters to return
  *
  * This function converts the BW to profile structure format.
  */
 static enum ice_status
-ice_sched_bw_to_rl_profile(u32 bw, struct ice_aqc_rl_profile_elem *profile)
+ice_sched_bw_to_rl_profile(struct ice_hw *hw, u32 bw,
+			   struct ice_aqc_rl_profile_elem *profile)
 {
 	enum ice_status status = ICE_ERR_PARAM;
 	s64 bytes_per_sec, ts_rate, mv_tmp;
@@ -3738,7 +3785,7 @@ ice_sched_bw_to_rl_profile(u32 bw, struct ice_aqc_rl_profile_elem *profile)
 	for (i = 0; i < 64; i++) {
 		u64 pow_result = BIT_ULL(i);
 
-		ts_rate = DIV_64BIT((s64)ICE_RL_PROF_FREQUENCY,
+		ts_rate = DIV_64BIT((s64)hw->psm_clk_freq,
 				    pow_result * ICE_RL_PROF_TS_MULTIPLIER);
 		if (ts_rate <= 0)
 			continue;
@@ -3762,7 +3809,7 @@ ice_sched_bw_to_rl_profile(u32 bw, struct ice_aqc_rl_profile_elem *profile)
 	if (found) {
 		u16 wm;
 
-		wm = ice_sched_calc_wakeup(bw);
+		wm = ice_sched_calc_wakeup(hw, bw);
 		profile->rl_multiply = CPU_TO_LE16(mv);
 		profile->wake_up_calc = CPU_TO_LE16(wm);
 		profile->rl_encode = CPU_TO_LE16(encode);
@@ -3831,7 +3878,7 @@ ice_sched_add_rl_profile(struct ice_port_info *pi,
 	if (!rl_prof_elem)
 		return NULL;
 
-	status = ice_sched_bw_to_rl_profile(bw, &rl_prof_elem->profile);
+	status = ice_sched_bw_to_rl_profile(hw, bw, &rl_prof_elem->profile);
 	if (status != ICE_SUCCESS)
 		goto exit_add_rl_prof;
 
diff --git a/dpdk/drivers/net/ice/base/ice_sched.h b/dpdk/drivers/net/ice/base/ice_sched.h
index d6b467477c..57bf4b59d6 100644
--- a/dpdk/drivers/net/ice/base/ice_sched.h
+++ b/dpdk/drivers/net/ice/base/ice_sched.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_SCHED_H_
@@ -25,12 +25,16 @@
 	((BIT(11) - 1) * 64) /* In Bytes */
 #define ICE_MAX_BURST_SIZE_KBYTE_GRANULARITY	ICE_MAX_BURST_SIZE_ALLOWED
 
-#define ICE_RL_PROF_FREQUENCY 446000000
 #define ICE_RL_PROF_ACCURACY_BYTES 128
 #define ICE_RL_PROF_MULTIPLIER 10000
 #define ICE_RL_PROF_TS_MULTIPLIER 32
 #define ICE_RL_PROF_FRACTION 512
 
+#define ICE_PSM_CLK_367MHZ_IN_HZ 367647059
+#define ICE_PSM_CLK_416MHZ_IN_HZ 416666667
+#define ICE_PSM_CLK_446MHZ_IN_HZ 446428571
+#define ICE_PSM_CLK_390MHZ_IN_HZ 390625000
+
 struct rl_profile_params {
 	u32 bw;			/* in Kbps */
 	u16 rl_multiplier;
@@ -83,6 +87,7 @@ ice_aq_query_sched_elems(struct ice_hw *hw, u16 elems_req,
 			 u16 *elems_ret, struct ice_sq_cd *cd);
 enum ice_status ice_sched_init_port(struct ice_port_info *pi);
 enum ice_status ice_sched_query_res_alloc(struct ice_hw *hw);
+void ice_sched_get_psm_clk_freq(struct ice_hw *hw);
 
 /* Functions to cleanup scheduler SW DB */
 void ice_sched_clear_port(struct ice_port_info *pi);
diff --git a/dpdk/drivers/net/ice/base/ice_status.h b/dpdk/drivers/net/ice/base/ice_status.h
index ac120fa300..ba28895a17 100644
--- a/dpdk/drivers/net/ice/base/ice_status.h
+++ b/dpdk/drivers/net/ice/base/ice_status.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_STATUS_H_
diff --git a/dpdk/drivers/net/ice/base/ice_switch.c b/dpdk/drivers/net/ice/base/ice_switch.c
index afa4fe30d4..71c6d9821c 100644
--- a/dpdk/drivers/net/ice/base/ice_switch.c
+++ b/dpdk/drivers/net/ice/base/ice_switch.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ice_switch.h"
@@ -611,7 +611,7 @@ ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
 	/* Complete initialization of the root recipe entry */
 	lkup_exts->n_val_words = fv_word_idx;
 	recps[rid].big_recp = (num_recps > 1);
-	recps[rid].n_grp_count = num_recps;
+	recps[rid].n_grp_count = (u8)num_recps;
 	recps[rid].root_buf = (struct ice_aqc_recipe_data_elem *)
 		ice_memdup(hw, tmp, recps[rid].n_grp_count *
 			   sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA);
@@ -2507,6 +2507,9 @@ ice_add_update_vsi_list(struct ice_hw *hw,
 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
 						vsi_list_id);
 
+		if (!m_entry->vsi_list_info)
+			return ICE_ERR_NO_MEMORY;
+
 		/* If this entry was large action then the large action needs
 		 * to be updated to point to FWD to VSI list
 		 */
@@ -3721,6 +3724,7 @@ ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
+		 fm_entry->vsi_list_info &&
 		 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
 				 vsi_handle))));
 }
@@ -3795,14 +3799,12 @@ ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
 
 	LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
 			    ice_fltr_mgmt_list_entry, list_entry) {
-		struct ice_fltr_info *fi;
-
-		fi = &fm_entry->fltr_info;
-		if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
+		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
 			continue;
 
 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
-							vsi_list_head, fi);
+							vsi_list_head,
+							&fm_entry->fltr_info);
 		if (status)
 			return status;
 	}
@@ -4748,7 +4750,7 @@ static bool ice_prot_type_to_id(enum ice_protocol_type type, u16 *id)
 {
 	u16 i;
 
-	for (i = 0; ice_prot_id_tbl[i].type != ICE_PROTOCOL_LAST; i++)
+	for (i = 0; i < ARRAY_SIZE(ice_prot_id_tbl); i++)
 		if (ice_prot_id_tbl[i].type == type) {
 			*id = ice_prot_id_tbl[i].protocol_id;
 			return true;
@@ -5995,9 +5997,12 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw,
 		if (status)
 			return status;
 
+		ice_memset(&tmp_fltr, 0, sizeof(tmp_fltr), ICE_NONDMA_MEM);
 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
+		tmp_fltr.lkup_type = ICE_SW_LKUP_LAST;
+
 		/* Update the previous switch rule of "forward to VSI" to
 		 * "fwd to VSI list"
 		 */
@@ -6238,23 +6243,8 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 	sw->recp_list[rid].adv_rule = true;
 	rule_head = &sw->recp_list[rid].filt_rules;
 
-	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) {
-		struct ice_fltr_info tmp_fltr;
-
-		tmp_fltr.fltr_rule_id =
-			LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
-		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
-		tmp_fltr.fwd_id.hw_vsi_id =
-			ice_get_hw_vsi_num(hw, vsi_handle);
-		tmp_fltr.vsi_handle = vsi_handle;
-		/* Update the previous switch rule of "forward to VSI" to
-		 * "fwd to VSI list"
-		 */
-		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
-		if (status)
-			goto err_ice_add_adv_rule;
+	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
 		adv_fltr->vsi_count = 1;
-	}
 
 	/* Add rule entry to book keeping list */
 	LIST_ADD(&adv_fltr->list_entry, rule_head);
@@ -6325,6 +6315,8 @@ ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
 						  lkup_type);
 		if (status)
 			return status;
+
+		ice_memset(&tmp_fltr, 0, sizeof(tmp_fltr), ICE_NONDMA_MEM);
 		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
 		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
@@ -6343,6 +6335,7 @@ ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
 				  tmp_fltr.fwd_id.hw_vsi_id, status);
 			return status;
 		}
+		fm_list->vsi_list_info->ref_cnt--;
 
 		/* Remove the VSI list since it is no longer used */
 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
@@ -6421,7 +6414,6 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
 	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
 		remove_rule = true;
 	} else if (list_elem->vsi_count > 1) {
-		list_elem->vsi_list_info->ref_cnt--;
 		remove_rule = false;
 		vsi_handle = rinfo->sw_act.vsi_handle;
 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
@@ -6497,7 +6489,8 @@ ice_rem_adv_rule_by_id(struct ice_hw *hw,
 						list_itr->lkups_cnt, &rinfo);
 		}
 	}
-	return ICE_ERR_PARAM;
+	/* either list is empty or unable to find rule */
+	return ICE_ERR_DOES_NOT_EXIST;
 }
 
 /**
diff --git a/dpdk/drivers/net/ice/base/ice_switch.h b/dpdk/drivers/net/ice/base/ice_switch.h
index 61083738ab..5dc795148e 100644
--- a/dpdk/drivers/net/ice/base/ice_switch.h
+++ b/dpdk/drivers/net/ice/base/ice_switch.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_SWITCH_H_
diff --git a/dpdk/drivers/net/ice/base/ice_type.h b/dpdk/drivers/net/ice/base/ice_type.h
index a8e4229a19..bf3c5ffd0a 100644
--- a/dpdk/drivers/net/ice/base/ice_type.h
+++ b/dpdk/drivers/net/ice/base/ice_type.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2019
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _ICE_TYPE_H_
@@ -528,7 +528,7 @@ struct ice_sched_node {
 #define ICE_TXSCHED_GET_EIR_BWALLOC(x)	\
 	LE16_TO_CPU((x)->info.eir_bw.bw_alloc)
 
-struct ice_sched_rl_profle {
+struct ice_sched_rl_profile {
 	u32 rate; /* In Kbps */
 	struct ice_aqc_rl_profile_elem info;
 };
@@ -745,6 +745,8 @@ struct ice_hw {
 	struct ice_sched_rl_profile **cir_profiles;
 	struct ice_sched_rl_profile **eir_profiles;
 	struct ice_sched_rl_profile **srl_profiles;
+	/* PSM clock frequency for calculating RL profile params */
+	u32 psm_clk_freq;
 	u64 debug_mask;		/* BITMAP for debug mask */
 	enum ice_mac_type mac_type;
 
diff --git a/dpdk/drivers/net/ice/base/meson.build b/dpdk/drivers/net/ice/base/meson.build
index eff155574d..46c4ffb500 100644
--- a/dpdk/drivers/net/ice/base/meson.build
+++ b/dpdk/drivers/net/ice/base/meson.build
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2018 Intel Corporation
+# Copyright(c) 2018-2020 Intel Corporation
 
 sources = [
 	'ice_controlq.c',
diff --git a/dpdk/drivers/net/ice/ice_ethdev.c b/dpdk/drivers/net/ice/ice_ethdev.c
index de189daba9..c2e659303c 100644
--- a/dpdk/drivers/net/ice/ice_ethdev.c
+++ b/dpdk/drivers/net/ice/ice_ethdev.c
@@ -870,7 +870,7 @@ ice_add_mac_filter(struct ice_vsi *vsi, struct rte_ether_addr *mac_addr)
 		ret = -ENOMEM;
 		goto DONE;
 	}
-	rte_memcpy(&f->mac_info.mac_addr, mac_addr, ETH_ADDR_LEN);
+	rte_ether_addr_copy(mac_addr, &f->mac_info.mac_addr);
 	TAILQ_INSERT_TAIL(&vsi->mac_list, f, next);
 	vsi->mac_num++;
 
@@ -1573,7 +1573,7 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 		cfg = ICE_AQ_VSI_PROP_SECURITY_VALID |
 			ICE_AQ_VSI_PROP_FLOW_DIR_VALID;
 		vsi_ctx.info.valid_sections |= rte_cpu_to_le_16(cfg);
-		cfg = ICE_AQ_VSI_FD_ENABLE | ICE_AQ_VSI_FD_PROG_ENABLE;
+		cfg = ICE_AQ_VSI_FD_ENABLE;
 		vsi_ctx.info.fd_options = rte_cpu_to_le_16(cfg);
 		vsi_ctx.info.max_fd_fltr_dedicated =
 			rte_cpu_to_le_16(hw->func_caps.fd_fltr_guar);
@@ -1601,9 +1601,10 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 
 		cfg = ICE_AQ_VSI_PROP_FLOW_DIR_VALID;
 		vsi_ctx.info.valid_sections |= rte_cpu_to_le_16(cfg);
-		cfg = ICE_AQ_VSI_FD_ENABLE | ICE_AQ_VSI_FD_PROG_ENABLE;
+		cfg = ICE_AQ_VSI_FD_PROG_ENABLE;
 		vsi_ctx.info.fd_options = rte_cpu_to_le_16(cfg);
 		vsi_ctx.info.sw_id = hw->port_info->sw_id;
+		vsi_ctx.info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
 		ret = ice_vsi_config_tc_queue_mapping(vsi,
 						      &vsi_ctx.info,
 						      ICE_DEFAULT_TCMAP);
@@ -1657,16 +1658,16 @@ ice_setup_vsi(struct ice_pf *pf, enum ice_vsi_type type)
 
 	if (type == ICE_VSI_PF) {
 		/* MAC configuration */
-		rte_memcpy(pf->dev_addr.addr_bytes,
-			   hw->port_info->mac.perm_addr,
-			   ETH_ADDR_LEN);
+		rte_ether_addr_copy((struct rte_ether_addr *)
+					hw->port_info->mac.perm_addr,
+				    &pf->dev_addr);
 
-		rte_memcpy(&mac_addr, &pf->dev_addr, RTE_ETHER_ADDR_LEN);
+		rte_ether_addr_copy(&pf->dev_addr, &mac_addr);
 		ret = ice_add_mac_filter(vsi, &mac_addr);
 		if (ret != ICE_SUCCESS)
 			PMD_INIT_LOG(ERR, "Failed to add dflt MAC filter");
 
-		rte_memcpy(&mac_addr, &broadcast, RTE_ETHER_ADDR_LEN);
+		rte_ether_addr_copy(&broadcast, &mac_addr);
 		ret = ice_add_mac_filter(vsi, &mac_addr);
 		if (ret != ICE_SUCCESS)
 			PMD_INIT_LOG(ERR, "Failed to add MAC filter");
@@ -2287,9 +2288,10 @@ ice_release_vsi(struct ice_vsi *vsi)
 	struct ice_hw *hw;
 	struct ice_vsi_ctx vsi_ctx;
 	enum ice_status ret;
+	int error = 0;
 
 	if (!vsi)
-		return 0;
+		return error;
 
 	hw = ICE_VSI_TO_HW(vsi);
 
@@ -2302,12 +2304,13 @@ ice_release_vsi(struct ice_vsi *vsi)
 	ret = ice_free_vsi(hw, vsi->idx, &vsi_ctx, false, NULL);
 	if (ret != ICE_SUCCESS) {
 		PMD_INIT_LOG(ERR, "Failed to free vsi by aq, %u", vsi->vsi_id);
-		rte_free(vsi);
-		return -1;
+		error = -1;
 	}
 
+	rte_free(vsi->rss_lut);
+	rte_free(vsi->rss_key);
 	rte_free(vsi);
-	return 0;
+	return error;
 }
 
 void
@@ -2439,24 +2442,6 @@ ice_dev_uninit(struct rte_eth_dev *dev)
 	return 0;
 }
 
-static int
-ice_dev_configure(struct rte_eth_dev *dev)
-{
-	struct ice_adapter *ad =
-		ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
-
-	/* Initialize to TRUE. If any of Rx queues doesn't meet the
-	 * bulk allocation or vector Rx preconditions we will reset it.
-	 */
-	ad->rx_bulk_alloc_allowed = true;
-	ad->tx_simple_allowed = true;
-
-	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
-		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
-
-	return 0;
-}
-
 static int ice_init_rss(struct ice_pf *pf)
 {
 	struct ice_hw *hw = ICE_PF_TO_HW(pf);
@@ -2474,18 +2459,35 @@ static int ice_init_rss(struct ice_pf *pf)
 	vsi->rss_key_size = ICE_AQC_GET_SET_RSS_KEY_DATA_RSS_KEY_SIZE;
 	vsi->rss_lut_size = pf->hash_lut_size;
 
+	if (nb_q == 0) {
+		PMD_DRV_LOG(WARNING,
+			"RSS is not supported as rx queues number is zero\n");
+		return 0;
+	}
+
 	if (is_safe_mode) {
 		PMD_DRV_LOG(WARNING, "RSS is not supported in safe mode\n");
 		return 0;
 	}
 
-	if (!vsi->rss_key)
+	if (!vsi->rss_key) {
 		vsi->rss_key = rte_zmalloc(NULL,
 					   vsi->rss_key_size, 0);
-	if (!vsi->rss_lut)
+		if (vsi->rss_key == NULL) {
+			PMD_DRV_LOG(ERR, "Failed to allocate memory for rss_key");
+			return -ENOMEM;
+		}
+	}
+	if (!vsi->rss_lut) {
 		vsi->rss_lut = rte_zmalloc(NULL,
 					   vsi->rss_lut_size, 0);
-
+		if (vsi->rss_lut == NULL) {
+			PMD_DRV_LOG(ERR, "Failed to allocate memory for rss_key");
+			rte_free(vsi->rss_key);
+			vsi->rss_key = NULL;
+			return -ENOMEM;
+		}
+	}
 	/* configure RSS key */
 	if (!rss_conf->rss_key) {
 		/* Calculate the default hash key */
@@ -2499,7 +2501,7 @@ static int ice_init_rss(struct ice_pf *pf)
 	rte_memcpy(key.standard_rss_key, vsi->rss_key, vsi->rss_key_size);
 	ret = ice_aq_set_rss_key(hw, vsi->idx, &key);
 	if (ret)
-		return -EINVAL;
+		goto out;
 
 	/* init RSS LUT table */
 	for (i = 0; i < vsi->rss_lut_size; i++)
@@ -2509,7 +2511,7 @@ static int ice_init_rss(struct ice_pf *pf)
 				 ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF,
 				 vsi->rss_lut, vsi->rss_lut_size);
 	if (ret)
-		return -EINVAL;
+		goto out;
 
 	/* Enable registers for symmetric_toeplitz function. */
 	reg = ICE_READ_REG(hw, VSIQF_HASH_CTL(vsi->vsi_id));
@@ -2584,6 +2586,40 @@ static int ice_init_rss(struct ice_pf *pf)
 		PMD_DRV_LOG(ERR, "%s PPPoE/PPPoD_SessionID rss flow fail %d",
 				__func__, ret);
 
+	return 0;
+out:
+	rte_free(vsi->rss_key);
+	vsi->rss_key = NULL;
+	rte_free(vsi->rss_lut);
+	vsi->rss_lut = NULL;
+	return -EINVAL;
+}
+
+static int
+ice_dev_configure(struct rte_eth_dev *dev)
+{
+	struct ice_adapter *ad =
+		ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+	struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	int ret;
+
+	/* Initialize to TRUE. If any of Rx queues doesn't meet the
+	 * bulk allocation or vector Rx preconditions we will reset it.
+	 */
+	ad->rx_bulk_alloc_allowed = true;
+	ad->tx_simple_allowed = true;
+
+	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
+	if (dev->data->nb_rx_queues) {
+		ret = ice_init_rss(pf);
+		if (ret) {
+			PMD_DRV_LOG(ERR, "Failed to enable rss for PF");
+			return ret;
+		}
+	}
+
 	return 0;
 }
 
@@ -2598,14 +2634,14 @@ __vsi_queues_bind_intr(struct ice_vsi *vsi, uint16_t msix_vect,
 	for (i = 0; i < nb_queue; i++) {
 		/*do actual bind*/
 		val = (msix_vect & QINT_RQCTL_MSIX_INDX_M) |
-		      (0 < QINT_RQCTL_ITR_INDX_S) | QINT_RQCTL_CAUSE_ENA_M;
+		      (0 << QINT_RQCTL_ITR_INDX_S) | QINT_RQCTL_CAUSE_ENA_M;
 		val_tx = (msix_vect & QINT_TQCTL_MSIX_INDX_M) |
-			 (0 < QINT_TQCTL_ITR_INDX_S) | QINT_TQCTL_CAUSE_ENA_M;
+			 (0 << QINT_TQCTL_ITR_INDX_S) | QINT_TQCTL_CAUSE_ENA_M;
 
 		PMD_DRV_LOG(INFO, "queue %d is binding to vect %d",
 			    base_queue + i, msix_vect);
 		/* set ITR0 value */
-		ICE_WRITE_REG(hw, GLINT_ITR(0, msix_vect), 0x10);
+		ICE_WRITE_REG(hw, GLINT_ITR(0, msix_vect), 0x2);
 		ICE_WRITE_REG(hw, QINT_RQCTL(base_queue + i), val);
 		ICE_WRITE_REG(hw, QINT_TQCTL(base_queue + i), val_tx);
 	}
@@ -2790,12 +2826,6 @@ ice_dev_start(struct rte_eth_dev *dev)
 		}
 	}
 
-	ret = ice_init_rss(pf);
-	if (ret) {
-		PMD_DRV_LOG(ERR, "Failed to enable rss for PF");
-		goto rx_err;
-	}
-
 	ice_set_rx_function(dev);
 	ice_set_tx_function(dev);
 
@@ -3217,7 +3247,7 @@ ice_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 		return -EBUSY;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > ICE_ETH_MAX_LEN)
 		dev_data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
@@ -3264,7 +3294,7 @@ static int ice_macaddr_set(struct rte_eth_dev *dev,
 		PMD_DRV_LOG(ERR, "Failed to add mac filter");
 		return -EIO;
 	}
-	memcpy(&pf->dev_addr, mac_addr, ETH_ADDR_LEN);
+	rte_ether_addr_copy(mac_addr, &pf->dev_addr);
 
 	flags = ICE_AQC_MAN_MAC_UPDATE_LAA_WOL;
 	ret = ice_aq_manage_mac_write(hw, mac_addr->addr_bytes, flags, NULL);
@@ -4058,6 +4088,13 @@ ice_update_vsi_stats(struct ice_vsi *vsi)
 	ice_stat_update_40(hw, GLV_BPRCH(idx), GLV_BPRCL(idx),
 			   vsi->offset_loaded, &oes->rx_broadcast,
 			   &nes->rx_broadcast);
+	/* enlarge the limitation when rx_bytes overflowed */
+	if (vsi->offset_loaded) {
+		if (ICE_RXTX_BYTES_LOW(vsi->old_rx_bytes) > nes->rx_bytes)
+			nes->rx_bytes += (uint64_t)1 << ICE_40_BIT_WIDTH;
+		nes->rx_bytes += ICE_RXTX_BYTES_HIGH(vsi->old_rx_bytes);
+	}
+	vsi->old_rx_bytes = nes->rx_bytes;
 	/* exclude CRC bytes */
 	nes->rx_bytes -= (nes->rx_unicast + nes->rx_multicast +
 			  nes->rx_broadcast) * RTE_ETHER_CRC_LEN;
@@ -4084,6 +4121,13 @@ ice_update_vsi_stats(struct ice_vsi *vsi)
 	/* GLV_TDPC not supported */
 	ice_stat_update_32(hw, GLV_TEPC(idx), vsi->offset_loaded,
 			   &oes->tx_errors, &nes->tx_errors);
+	/* enlarge the limitation when tx_bytes overflowed */
+	if (vsi->offset_loaded) {
+		if (ICE_RXTX_BYTES_LOW(vsi->old_tx_bytes) > nes->tx_bytes)
+			nes->tx_bytes += (uint64_t)1 << ICE_40_BIT_WIDTH;
+		nes->tx_bytes += ICE_RXTX_BYTES_HIGH(vsi->old_tx_bytes);
+	}
+	vsi->old_tx_bytes = nes->tx_bytes;
 	vsi->offset_loaded = true;
 
 	PMD_DRV_LOG(DEBUG, "************** VSI[%u] stats start **************",
@@ -4131,6 +4175,13 @@ ice_read_stats_registers(struct ice_pf *pf, struct ice_hw *hw)
 	ice_stat_update_32(hw, PRTRPB_RDPC,
 			   pf->offset_loaded, &os->eth.rx_discards,
 			   &ns->eth.rx_discards);
+	/* enlarge the limitation when rx_bytes overflowed */
+	if (pf->offset_loaded) {
+		if (ICE_RXTX_BYTES_LOW(pf->old_rx_bytes) > ns->eth.rx_bytes)
+			ns->eth.rx_bytes += (uint64_t)1 << ICE_40_BIT_WIDTH;
+		ns->eth.rx_bytes += ICE_RXTX_BYTES_HIGH(pf->old_rx_bytes);
+	}
+	pf->old_rx_bytes = ns->eth.rx_bytes;
 
 	/* Workaround: CRC size should not be included in byte statistics,
 	 * so subtract RTE_ETHER_CRC_LEN from the byte counter for each rx
@@ -4161,6 +4212,13 @@ ice_read_stats_registers(struct ice_pf *pf, struct ice_hw *hw)
 			   GLPRT_BPTCL(hw->port_info->lport),
 			   pf->offset_loaded, &os->eth.tx_broadcast,
 			   &ns->eth.tx_broadcast);
+	/* enlarge the limitation when tx_bytes overflowed */
+	if (pf->offset_loaded) {
+		if (ICE_RXTX_BYTES_LOW(pf->old_tx_bytes) > ns->eth.tx_bytes)
+			ns->eth.tx_bytes += (uint64_t)1 << ICE_40_BIT_WIDTH;
+		ns->eth.tx_bytes += ICE_RXTX_BYTES_HIGH(pf->old_tx_bytes);
+	}
+	pf->old_tx_bytes = ns->eth.tx_bytes;
 	ns->eth.tx_bytes -= (ns->eth.tx_unicast + ns->eth.tx_multicast +
 			     ns->eth.tx_broadcast) * RTE_ETHER_CRC_LEN;
 
diff --git a/dpdk/drivers/net/ice/ice_ethdev.h b/dpdk/drivers/net/ice/ice_ethdev.h
index f2186e1ff9..cce0b5f2d6 100644
--- a/dpdk/drivers/net/ice/ice_ethdev.h
+++ b/dpdk/drivers/net/ice/ice_ethdev.h
@@ -123,6 +123,10 @@
  */
 #define ICE_ETH_OVERHEAD \
 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + ICE_VLAN_TAG_SIZE * 2)
+#define ICE_ETH_MAX_LEN (RTE_ETHER_MTU + ICE_ETH_OVERHEAD)
+
+#define ICE_RXTX_BYTES_HIGH(bytes) ((bytes) & ~ICE_40_BIT_MASK)
+#define ICE_RXTX_BYTES_LOW(bytes) ((bytes) & ICE_40_BIT_MASK)
 
 /* DDP package type */
 enum ice_pkg_type {
@@ -239,6 +243,8 @@ struct ice_vsi {
 	struct ice_eth_stats eth_stats_offset;
 	struct ice_eth_stats eth_stats;
 	bool offset_loaded;
+	uint64_t old_rx_bytes;
+	uint64_t old_tx_bytes;
 };
 
 enum proto_xtr_type {
@@ -254,6 +260,7 @@ enum ice_fdir_tunnel_type {
 	ICE_FDIR_TUNNEL_TYPE_NONE = 0,
 	ICE_FDIR_TUNNEL_TYPE_VXLAN,
 	ICE_FDIR_TUNNEL_TYPE_GTPU,
+	ICE_FDIR_TUNNEL_TYPE_GTPU_EH,
 };
 
 struct rte_flow;
@@ -380,6 +387,8 @@ struct ice_pf {
 	struct ice_parser_list perm_parser_list;
 	struct ice_parser_list dist_parser_list;
 	bool init_link_up;
+	uint64_t old_rx_bytes;
+	uint64_t old_tx_bytes;
 };
 
 #define ICE_MAX_QUEUE_NUM  2048
diff --git a/dpdk/drivers/net/ice/ice_fdir_filter.c b/dpdk/drivers/net/ice/ice_fdir_filter.c
index fa87074556..91fef712c1 100644
--- a/dpdk/drivers/net/ice/ice_fdir_filter.c
+++ b/dpdk/drivers/net/ice/ice_fdir_filter.c
@@ -67,10 +67,11 @@
 	ICE_FDIR_INSET_VXLAN_IPV4 | \
 	ICE_INSET_TUN_SCTP_SRC_PORT | ICE_INSET_TUN_SCTP_DST_PORT)
 
-#define ICE_FDIR_INSET_GTPU_IPV4 (\
-	ICE_INSET_GTPU_TEID)
+#define ICE_FDIR_INSET_GTPU (\
+	ICE_INSET_IPV4_SRC | ICE_INSET_IPV4_DST | ICE_INSET_GTPU_TEID)
 
-#define ICE_FDIR_INSET_GTPU_EH_IPV4 (\
+#define ICE_FDIR_INSET_GTPU_EH (\
+	ICE_INSET_IPV4_SRC | ICE_INSET_IPV4_DST | \
 	ICE_INSET_GTPU_TEID | ICE_INSET_GTPU_QFI)
 
 static struct ice_pattern_match_item ice_fdir_pattern_os[] = {
@@ -125,14 +126,16 @@ static struct ice_pattern_match_item ice_fdir_pattern_comms[] = {
 				       ICE_FDIR_INSET_VXLAN_IPV4_TCP,        ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_sctp,
 				       ICE_FDIR_INSET_VXLAN_IPV4_SCTP,       ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_ipv4,   ICE_FDIR_INSET_GTPU_IPV4,             ICE_INSET_NONE},
-	{pattern_eth_ipv4_gtpu_eh_ipv4,
-				       ICE_FDIR_INSET_GTPU_EH_IPV4,          ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu,	       ICE_FDIR_INSET_GTPU,                  ICE_INSET_NONE},
+	{pattern_eth_ipv4_gtpu_eh,     ICE_FDIR_INSET_GTPU_EH,               ICE_INSET_NONE},
 };
 
 static struct ice_flow_parser ice_fdir_parser_os;
 static struct ice_flow_parser ice_fdir_parser_comms;
 
+static int
+ice_fdir_is_tunnel_profile(enum ice_fdir_tunnel_type tunnel_type);
+
 static const struct rte_memzone *
 ice_memzone_reserve(const char *name, uint32_t len, int socket_id)
 {
@@ -915,7 +918,7 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 		{ICE_INSET_TUN_UDP_DST_PORT, ICE_FLOW_FIELD_IDX_UDP_DST_PORT},
 		{ICE_INSET_TUN_SCTP_SRC_PORT, ICE_FLOW_FIELD_IDX_SCTP_SRC_PORT},
 		{ICE_INSET_TUN_SCTP_DST_PORT, ICE_FLOW_FIELD_IDX_SCTP_DST_PORT},
-		{ICE_INSET_GTPU_TEID, ICE_FLOW_FIELD_IDX_GTPU_EH_TEID},
+		{ICE_INSET_GTPU_TEID, ICE_FLOW_FIELD_IDX_GTPU_IP_TEID},
 		{ICE_INSET_GTPU_QFI, ICE_FLOW_FIELD_IDX_GTPU_EH_QFI},
 	};
 
@@ -928,11 +931,12 @@ ice_fdir_input_set_parse(uint64_t inset, enum ice_flow_field *field)
 
 static int
 ice_fdir_input_set_conf(struct ice_pf *pf, enum ice_fltr_ptype flow,
-			uint64_t input_set, bool is_tunnel)
+			uint64_t input_set, enum ice_fdir_tunnel_type ttype)
 {
 	struct ice_flow_seg_info *seg;
 	struct ice_flow_seg_info *seg_tun = NULL;
 	enum ice_flow_field field[ICE_FLOW_FIELD_IDX_MAX];
+	bool is_tunnel;
 	int i, ret;
 
 	if (!input_set)
@@ -984,9 +988,15 @@ ice_fdir_input_set_conf(struct ice_pf *pf, enum ice_fltr_ptype flow,
 	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP:
 	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP:
 	case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER:
-		ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_EH |
-				       ICE_FLOW_SEG_HDR_GTPU_IP |
-				  ICE_FLOW_SEG_HDR_IPV4);
+		if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU)
+			ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_IP |
+					  ICE_FLOW_SEG_HDR_IPV4);
+		else if (ttype == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
+			ICE_FLOW_SET_HDRS(seg, ICE_FLOW_SEG_HDR_GTPU_EH |
+					  ICE_FLOW_SEG_HDR_GTPU_IP |
+					  ICE_FLOW_SEG_HDR_IPV4);
+		else
+			PMD_DRV_LOG(ERR, "not supported tunnel type.");
 		break;
 	default:
 		PMD_DRV_LOG(ERR, "not supported filter type.");
@@ -1000,6 +1010,7 @@ ice_fdir_input_set_conf(struct ice_pf *pf, enum ice_fltr_ptype flow,
 				 ICE_FLOW_FLD_OFF_INVAL, false);
 	}
 
+	is_tunnel = ice_fdir_is_tunnel_profile(ttype);
 	if (!is_tunnel) {
 		ret = ice_fdir_hw_tbl_conf(pf, pf->main_vsi, pf->fdir.fdir_vsi,
 					   seg, flow, false);
@@ -1224,7 +1235,7 @@ ice_fdir_create_filter(struct ice_adapter *ad,
 	is_tun = ice_fdir_is_tunnel_profile(filter->tunnel_type);
 
 	ret = ice_fdir_input_set_conf(pf, filter->input.flow_type,
-			filter->input_set, is_tun);
+			filter->input_set, filter->tunnel_type);
 	if (ret) {
 		rte_flow_error_set(error, -ret,
 				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
@@ -1488,8 +1499,7 @@ ice_fdir_parse_action(struct ice_adapter *ad,
 			dest_num++;
 
 			filter->input.dest_ctl =
-				ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX;
-			filter->input.q_index = 0;
+				ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			dest_num++;
@@ -1504,6 +1514,7 @@ ice_fdir_parse_action(struct ice_adapter *ad,
 
 			mark_spec = actions->conf;
 			filter->input.fltr_id = mark_spec->id;
+			filter->input.fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ONE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			counter_num++;
@@ -1522,7 +1533,7 @@ ice_fdir_parse_action(struct ice_adapter *ad,
 		}
 	}
 
-	if (dest_num == 0 || dest_num >= 2) {
+	if (dest_num >= 2) {
 		rte_flow_error_set(error, EINVAL,
 			   RTE_FLOW_ERROR_TYPE_ACTION, actions,
 			   "Unsupported action combination");
@@ -1543,6 +1554,18 @@ ice_fdir_parse_action(struct ice_adapter *ad,
 		return -rte_errno;
 	}
 
+	if (dest_num + mark_num + counter_num == 0) {
+		rte_flow_error_set(error, EINVAL,
+			   RTE_FLOW_ERROR_TYPE_ACTION, actions,
+			   "Empty action");
+		return -rte_errno;
+	}
+
+	/* set default action to PASSTHRU mode, in "mark/count only" case. */
+	if (dest_num == 0)
+		filter->input.dest_ctl =
+			ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER;
+
 	return 0;
 }
 
@@ -1896,6 +1919,7 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				filter->input.gtpu_data.qfi =
 					gtp_psc_spec->qfi;
 			}
+			tunnel_type = ICE_FDIR_TUNNEL_TYPE_GTPU_EH;
 			break;
 		default:
 			rte_flow_error_set(error, EINVAL,
@@ -1906,7 +1930,8 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 		}
 	}
 
-	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU)
+	if (tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU ||
+	    tunnel_type == ICE_FDIR_TUNNEL_TYPE_GTPU_EH)
 		flow_type = ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER;
 
 	filter->tunnel_type = tunnel_type;
@@ -1938,23 +1963,26 @@ ice_fdir_parse(struct ice_adapter *ad,
 
 	ret = ice_fdir_parse_pattern(ad, pattern, error, filter);
 	if (ret)
-		return ret;
+		goto error;
 	input_set = filter->input_set;
 	if (!input_set || input_set & ~item->input_set_mask) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 				   pattern,
 				   "Invalid input set");
-		return -rte_errno;
+		ret = -rte_errno;
+		goto error;
 	}
 
 	ret = ice_fdir_parse_action(ad, actions, error, filter);
 	if (ret)
-		return ret;
-
-	*meta = filter;
+		goto error;
 
-	return 0;
+	if (meta)
+		*meta = filter;
+error:
+	rte_free(item);
+	return ret;
 }
 
 static struct ice_flow_parser ice_fdir_parser_os = {
diff --git a/dpdk/drivers/net/ice/ice_generic_flow.c b/dpdk/drivers/net/ice/ice_generic_flow.c
index c9efa8356f..1d2d60fda6 100644
--- a/dpdk/drivers/net/ice/ice_generic_flow.c
+++ b/dpdk/drivers/net/ice/ice_generic_flow.c
@@ -1034,6 +1034,13 @@ enum rte_flow_item_type pattern_eth_ipv6_nvgre_eth_ipv6_icmp6[] = {
 };
 
 /* GTPU */
+enum rte_flow_item_type pattern_eth_ipv4_gtpu[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_END,
+};
 enum rte_flow_item_type pattern_eth_ipv4_gtpu_ipv4[] = {
 	RTE_FLOW_ITEM_TYPE_ETH,
 	RTE_FLOW_ITEM_TYPE_IPV4,
@@ -1042,6 +1049,14 @@ enum rte_flow_item_type pattern_eth_ipv4_gtpu_ipv4[] = {
 	RTE_FLOW_ITEM_TYPE_IPV4,
 	RTE_FLOW_ITEM_TYPE_END,
 };
+enum rte_flow_item_type pattern_eth_ipv4_gtpu_eh[] = {
+	RTE_FLOW_ITEM_TYPE_ETH,
+	RTE_FLOW_ITEM_TYPE_IPV4,
+	RTE_FLOW_ITEM_TYPE_UDP,
+	RTE_FLOW_ITEM_TYPE_GTPU,
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+	RTE_FLOW_ITEM_TYPE_END,
+};
 enum rte_flow_item_type pattern_eth_ipv4_gtpu_eh_ipv4[] = {
 	RTE_FLOW_ITEM_TYPE_ETH,
 	RTE_FLOW_ITEM_TYPE_IPV4,
@@ -1360,7 +1375,6 @@ typedef struct ice_flow_engine * (*parse_engine_t)(struct ice_adapter *ad,
 		struct ice_parser_list *parser_list,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
-		void **meta,
 		struct rte_flow_error *error);
 
 void
@@ -1698,11 +1712,11 @@ ice_parse_engine_create(struct ice_adapter *ad,
 		struct ice_parser_list *parser_list,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
-		void **meta,
 		struct rte_flow_error *error)
 {
 	struct ice_flow_engine *engine = NULL;
 	struct ice_flow_parser_node *parser_node;
+	void *meta = NULL;
 	void *temp;
 
 	TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
@@ -1711,18 +1725,12 @@ ice_parse_engine_create(struct ice_adapter *ad,
 		if (parser_node->parser->parse_pattern_action(ad,
 				parser_node->parser->array,
 				parser_node->parser->array_len,
-				pattern, actions, meta, error) < 0)
+				pattern, actions, &meta, error) < 0)
 			continue;
 
 		engine = parser_node->parser->engine;
-		if (engine->create == NULL) {
-			rte_flow_error_set(error, EINVAL,
-					RTE_FLOW_ERROR_TYPE_HANDLE,
-					NULL, "Invalid engine");
-			continue;
-		}
-
-		ret = engine->create(ad, flow, *meta, error);
+		RTE_ASSERT(engine->create != NULL);
+		ret = engine->create(ad, flow, meta, error);
 		if (ret == 0)
 			return engine;
 		else if (ret == -EEXIST)
@@ -1737,7 +1745,6 @@ ice_parse_engine_validate(struct ice_adapter *ad,
 		struct ice_parser_list *parser_list,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
-		void **meta,
 		struct rte_flow_error *error)
 {
 	struct ice_flow_engine *engine = NULL;
@@ -1748,7 +1755,7 @@ ice_parse_engine_validate(struct ice_adapter *ad,
 		if (parser_node->parser->parse_pattern_action(ad,
 				parser_node->parser->array,
 				parser_node->parser->array_len,
-				pattern, actions, meta, error) < 0)
+				pattern, actions, NULL, error) < 0)
 			continue;
 
 		engine = parser_node->parser->engine;
@@ -1764,7 +1771,6 @@ ice_flow_process_filter(struct rte_eth_dev *dev,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
 		struct ice_flow_engine **engine,
-		void **meta,
 		parse_engine_t ice_parse_engine,
 		struct rte_flow_error *error)
 {
@@ -1780,7 +1786,7 @@ ice_flow_process_filter(struct rte_eth_dev *dev,
 		return -rte_errno;
 	}
 
-	if (!actions) {
+	if (!actions || actions->type == RTE_FLOW_ACTION_TYPE_END) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_ACTION_NUM,
 				   NULL, "NULL action.");
@@ -1799,7 +1805,7 @@ ice_flow_process_filter(struct rte_eth_dev *dev,
 		return ret;
 
 	*engine = ice_parse_engine(ad, flow, &pf->rss_parser_list,
-			pattern, actions, meta, error);
+			pattern, actions, error);
 	if (*engine != NULL)
 		return 0;
 
@@ -1807,11 +1813,11 @@ ice_flow_process_filter(struct rte_eth_dev *dev,
 	case ICE_FLOW_CLASSIFY_STAGE_DISTRIBUTOR_ONLY:
 	case ICE_FLOW_CLASSIFY_STAGE_DISTRIBUTOR:
 		*engine = ice_parse_engine(ad, flow, &pf->dist_parser_list,
-				pattern, actions, meta, error);
+				pattern, actions, error);
 		break;
 	case ICE_FLOW_CLASSIFY_STAGE_PERMISSION:
 		*engine = ice_parse_engine(ad, flow, &pf->perm_parser_list,
-				pattern, actions, meta, error);
+				pattern, actions, error);
 		break;
 	default:
 		return -EINVAL;
@@ -1830,11 +1836,10 @@ ice_flow_validate(struct rte_eth_dev *dev,
 		const struct rte_flow_action actions[],
 		struct rte_flow_error *error)
 {
-	void *meta;
 	struct ice_flow_engine *engine;
 
 	return ice_flow_process_filter(dev, NULL, attr, pattern, actions,
-			&engine, &meta, ice_parse_engine_validate, error);
+			&engine, ice_parse_engine_validate, error);
 }
 
 static struct rte_flow *
@@ -1848,7 +1853,6 @@ ice_flow_create(struct rte_eth_dev *dev,
 	struct rte_flow *flow = NULL;
 	int ret;
 	struct ice_flow_engine *engine = NULL;
-	void *meta;
 
 	flow = rte_zmalloc("ice_flow", sizeof(struct rte_flow), 0);
 	if (!flow) {
@@ -1859,7 +1863,7 @@ ice_flow_create(struct rte_eth_dev *dev,
 	}
 
 	ret = ice_flow_process_filter(dev, flow, attr, pattern, actions,
-			&engine, &meta, ice_parse_engine_create, error);
+			&engine, ice_parse_engine_create, error);
 	if (ret < 0)
 		goto free_flow;
 	flow->engine = engine;
diff --git a/dpdk/drivers/net/ice/ice_generic_flow.h b/dpdk/drivers/net/ice/ice_generic_flow.h
index ac085b47fa..adc30ee2aa 100644
--- a/dpdk/drivers/net/ice/ice_generic_flow.h
+++ b/dpdk/drivers/net/ice/ice_generic_flow.h
@@ -336,7 +336,9 @@ extern enum rte_flow_item_type pattern_eth_ipv6_nvgre_eth_ipv6_sctp[];
 extern enum rte_flow_item_type pattern_eth_ipv6_nvgre_eth_ipv6_icmp6[];
 
 /* GTPU */
+extern enum rte_flow_item_type pattern_eth_ipv4_gtpu[];
 extern enum rte_flow_item_type pattern_eth_ipv4_gtpu_ipv4[];
+extern enum rte_flow_item_type pattern_eth_ipv4_gtpu_eh[];
 extern enum rte_flow_item_type pattern_eth_ipv4_gtpu_eh_ipv4[];
 extern enum rte_flow_item_type pattern_eth_ipv4_gtpu_eh_ipv4_udp[];
 extern enum rte_flow_item_type pattern_eth_ipv4_gtpu_eh_ipv4_tcp[];
diff --git a/dpdk/drivers/net/ice/ice_hash.c b/dpdk/drivers/net/ice/ice_hash.c
index b145a3f0d5..23c455762b 100644
--- a/dpdk/drivers/net/ice/ice_hash.c
+++ b/dpdk/drivers/net/ice/ice_hash.c
@@ -95,7 +95,7 @@ struct rss_type_match_hdr hint_7 = {
 struct rss_type_match_hdr hint_8 = {
 	ICE_FLOW_SEG_HDR_IPV6 | ICE_FLOW_SEG_HDR_SCTP, ETH_RSS_NONFRAG_IPV6_SCTP};
 struct rss_type_match_hdr hint_9 = {
-	ICE_FLOW_SEG_HDR_GTPU_IP,	ETH_RSS_IPV4};
+	ICE_FLOW_SEG_HDR_GTPU_EH, ETH_RSS_IPV4};
 struct rss_type_match_hdr hint_10 = {
 	ICE_FLOW_SEG_HDR_PPPOE,	ETH_RSS_IPV4};
 struct rss_type_match_hdr hint_11 = {
@@ -104,6 +104,10 @@ struct rss_type_match_hdr hint_12 = {
 	ICE_FLOW_SEG_HDR_PPPOE,	ETH_RSS_NONFRAG_IPV4_TCP};
 struct rss_type_match_hdr hint_13 = {
 	ICE_FLOW_SEG_HDR_PPPOE,	ETH_RSS_NONFRAG_IPV4_SCTP};
+struct rss_type_match_hdr hint_14 = {
+	ICE_FLOW_SEG_HDR_GTPU_EH, ETH_RSS_NONFRAG_IPV4_UDP};
+struct rss_type_match_hdr hint_15 = {
+	ICE_FLOW_SEG_HDR_GTPU_EH, ETH_RSS_NONFRAG_IPV4_TCP};
 
 /* Supported pattern for os default package. */
 static struct ice_pattern_match_item ice_hash_pattern_list_os[] = {
@@ -130,8 +134,8 @@ static struct ice_pattern_match_item ice_hash_pattern_list_comms[] = {
 	{pattern_eth_ipv6_sctp,		    ICE_INSET_NONE,  &hint_8},
 	{pattern_empty,			    ICE_INSET_NONE,  &hint_0},
 	{pattern_eth_ipv4_gtpu_eh_ipv4,	    ICE_INSET_NONE,  &hint_9},
-	{pattern_eth_ipv4_gtpu_eh_ipv4_udp, ICE_INSET_NONE,  &hint_9},
-	{pattern_eth_ipv4_gtpu_eh_ipv4_tcp, ICE_INSET_NONE,  &hint_9},
+	{pattern_eth_ipv4_gtpu_eh_ipv4_udp, ICE_INSET_NONE,  &hint_14},
+	{pattern_eth_ipv4_gtpu_eh_ipv4_tcp, ICE_INSET_NONE,  &hint_15},
 	{pattern_eth_pppoes_ipv4,	    ICE_INSET_NONE,  &hint_10},
 	{pattern_eth_pppoes_ipv4_udp,	    ICE_INSET_NONE,  &hint_11},
 	{pattern_eth_pppoes_ipv4_tcp,	    ICE_INSET_NONE,  &hint_12},
@@ -424,26 +428,31 @@ ice_hash_parse_pattern_action(__rte_unused struct ice_adapter *ad,
 	/* Check rss supported pattern and find matched pattern. */
 	pattern_match_item = ice_search_pattern_match_item(pattern,
 					array, array_len, error);
-	if (!pattern_match_item)
-		return -rte_errno;
+	if (!pattern_match_item) {
+		ret = -rte_errno;
+		goto error;
+	}
 
 	ret = ice_hash_check_inset(pattern, error);
 	if (ret)
-		return -rte_errno;
+		goto error;
 
 	/* Save protocol header to rss_meta. */
-	*meta = rss_meta_ptr;
-	((struct rss_meta *)*meta)->pkt_hdr = ((struct rss_type_match_hdr *)
+	rss_meta_ptr->pkt_hdr = ((struct rss_type_match_hdr *)
 		(pattern_match_item->meta))->hdr_mask;
 
 	/* Check rss action. */
-	ret = ice_hash_parse_action(pattern_match_item, actions, meta, error);
-	if (ret)
-		return -rte_errno;
+	ret = ice_hash_parse_action(pattern_match_item, actions,
+				    (void **)&rss_meta_ptr, error);
 
+error:
+	if (!ret && meta)
+		*meta = rss_meta_ptr;
+	else
+		rte_free(rss_meta_ptr);
 	rte_free(pattern_match_item);
 
-	return 0;
+	return ret;
 }
 
 static int
diff --git a/dpdk/drivers/net/ice/ice_rxtx.c b/dpdk/drivers/net/ice/ice_rxtx.c
index 2db1744562..ccb391c04b 100644
--- a/dpdk/drivers/net/ice/ice_rxtx.c
+++ b/dpdk/drivers/net/ice/ice_rxtx.c
@@ -85,23 +85,23 @@ ice_program_hw_rx_queue(struct ice_rx_queue *rxq)
 				   dev->data->dev_conf.rxmode.max_rx_pkt_len);
 
 	if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME) {
-		if (rxq->max_pkt_len <= RTE_ETHER_MAX_LEN ||
+		if (rxq->max_pkt_len <= ICE_ETH_MAX_LEN ||
 		    rxq->max_pkt_len > ICE_FRAME_SIZE_MAX) {
 			PMD_DRV_LOG(ERR, "maximum packet length must "
 				    "be larger than %u and smaller than %u,"
 				    "as jumbo frame is enabled",
-				    (uint32_t)RTE_ETHER_MAX_LEN,
+				    (uint32_t)ICE_ETH_MAX_LEN,
 				    (uint32_t)ICE_FRAME_SIZE_MAX);
 			return -EINVAL;
 		}
 	} else {
 		if (rxq->max_pkt_len < RTE_ETHER_MIN_LEN ||
-		    rxq->max_pkt_len > RTE_ETHER_MAX_LEN) {
+		    rxq->max_pkt_len > ICE_ETH_MAX_LEN) {
 			PMD_DRV_LOG(ERR, "maximum packet length must be "
 				    "larger than %u and smaller than %u, "
 				    "as jumbo frame is disabled",
 				    (uint32_t)RTE_ETHER_MIN_LEN,
-				    (uint32_t)RTE_ETHER_MAX_LEN);
+				    (uint32_t)ICE_ETH_MAX_LEN);
 			return -EINVAL;
 		}
 	}
@@ -236,17 +236,12 @@ _ice_rx_queue_release_mbufs(struct ice_rx_queue *rxq)
 			rxq->sw_ring[i].mbuf = NULL;
 		}
 	}
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
-		if (rxq->rx_nb_avail == 0)
-			return;
-		for (i = 0; i < rxq->rx_nb_avail; i++) {
-			struct rte_mbuf *mbuf;
+	if (rxq->rx_nb_avail == 0)
+		return;
+	for (i = 0; i < rxq->rx_nb_avail; i++)
+		rte_pktmbuf_free_seg(rxq->rx_stage[rxq->rx_next_avail + i]);
 
-			mbuf = rxq->rx_stage[rxq->rx_next_avail + i];
-			rte_pktmbuf_free_seg(mbuf);
-		}
-		rxq->rx_nb_avail = 0;
-#endif /* RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC */
+	rxq->rx_nb_avail = 0;
 }
 
 static void
@@ -309,16 +304,10 @@ ice_switch_rx_queue(struct ice_hw *hw, uint16_t q_idx, bool on)
 }
 
 static inline int
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 ice_check_rx_burst_bulk_alloc_preconditions(struct ice_rx_queue *rxq)
-#else
-ice_check_rx_burst_bulk_alloc_preconditions
-	(__rte_unused struct ice_rx_queue *rxq)
-#endif
 {
 	int ret = 0;
 
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 	if (!(rxq->rx_free_thresh >= ICE_RX_MAX_BURST)) {
 		PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions: "
 			     "rxq->rx_free_thresh=%d, "
@@ -338,9 +327,6 @@ ice_check_rx_burst_bulk_alloc_preconditions
 			     rxq->nb_rx_desc, rxq->rx_free_thresh);
 		ret = -EINVAL;
 	}
-#else
-	ret = -EINVAL;
-#endif
 
 	return ret;
 }
@@ -357,17 +343,11 @@ ice_reset_rx_queue(struct ice_rx_queue *rxq)
 		return;
 	}
 
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
-	if (ice_check_rx_burst_bulk_alloc_preconditions(rxq) == 0)
-		len = (uint16_t)(rxq->nb_rx_desc + ICE_RX_MAX_BURST);
-	else
-#endif /* RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC */
-		len = rxq->nb_rx_desc;
+	len = (uint16_t)(rxq->nb_rx_desc + ICE_RX_MAX_BURST);
 
 	for (i = 0; i < len * sizeof(union ice_rx_flex_desc); i++)
 		((volatile char *)rxq->rx_ring)[i] = 0;
 
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 	memset(&rxq->fake_mbuf, 0x0, sizeof(rxq->fake_mbuf));
 	for (i = 0; i < ICE_RX_MAX_BURST; ++i)
 		rxq->sw_ring[rxq->nb_rx_desc + i].mbuf = &rxq->fake_mbuf;
@@ -375,7 +355,6 @@ ice_reset_rx_queue(struct ice_rx_queue *rxq)
 	rxq->rx_nb_avail = 0;
 	rxq->rx_next_avail = 0;
 	rxq->rx_free_trigger = (uint16_t)(rxq->rx_free_thresh - 1);
-#endif /* RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC */
 
 	rxq->rx_tail = 0;
 	rxq->nb_rx_hold = 0;
@@ -551,7 +530,7 @@ ice_fdir_program_hw_rx_queue(struct ice_rx_queue *rxq)
 	rx_ctx.hbuf = rxq->rx_hdr_len >> ICE_RLAN_CTX_HBUF_S;
 	rx_ctx.dtype = 0; /* No Header Split mode */
 	rx_ctx.dsize = 1; /* 32B descriptors */
-	rx_ctx.rxmax = RTE_ETHER_MAX_LEN;
+	rx_ctx.rxmax = ICE_ETH_MAX_LEN;
 	/* TPH: Transaction Layer Packet (TLP) processing hints */
 	rx_ctx.tphrdesc_ena = 1;
 	rx_ctx.tphwdesc_ena = 1;
@@ -926,13 +905,11 @@ ice_rx_queue_setup(struct rte_eth_dev *dev,
 	/* Allocate the maximun number of RX ring hardware descriptor. */
 	len = ICE_MAX_RING_DESC;
 
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 	/**
 	 * Allocating a little more memory because vectorized/bulk_alloc Rx
 	 * functions doesn't check boundaries each time.
 	 */
 	len += ICE_RX_MAX_BURST;
-#endif
 
 	/* Allocate the maximum number of RX ring hardware descriptor. */
 	ring_size = sizeof(union ice_rx_flex_desc) * len;
@@ -952,11 +929,8 @@ ice_rx_queue_setup(struct rte_eth_dev *dev,
 	rxq->rx_ring_dma = rz->iova;
 	rxq->rx_ring = rz->addr;
 
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
+	/* always reserve more for bulk alloc */
 	len = (uint16_t)(nb_desc + ICE_RX_MAX_BURST);
-#else
-	len = nb_desc;
-#endif
 
 	/* Allocate the software ring. */
 	rxq->sw_ring = rte_zmalloc_socket(NULL,
@@ -977,17 +951,14 @@ ice_rx_queue_setup(struct rte_eth_dev *dev,
 	use_def_burst_func = ice_check_rx_burst_bulk_alloc_preconditions(rxq);
 
 	if (!use_def_burst_func) {
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 		PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are "
 			     "satisfied. Rx Burst Bulk Alloc function will be "
 			     "used on port=%d, queue=%d.",
 			     rxq->port_id, rxq->queue_id);
-#endif /* RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC */
 	} else {
 		PMD_INIT_LOG(DEBUG, "Rx Burst Bulk Alloc Preconditions are "
-			     "not satisfied, Scattered Rx is requested, "
-			     "or RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC is "
-			     "not enabled on port=%d, queue=%d.",
+			     "not satisfied, Scattered Rx is requested. "
+			     "on port=%d, queue=%d.",
 			     rxq->port_id, rxq->queue_id);
 		ad->rx_bulk_alloc_allowed = false;
 	}
@@ -1307,6 +1278,11 @@ ice_rxd_error_to_pkt_flags(uint16_t stat_err0)
 	if (unlikely(stat_err0 & (1 << ICE_RX_FLEX_DESC_STATUS0_XSUM_EIPE_S)))
 		flags |= PKT_RX_EIP_CKSUM_BAD;
 
+	if (unlikely(stat_err0 & (1 << ICE_RX_FLEX_DESC_STATUS0_XSUM_EUDPE_S)))
+		flags |= PKT_RX_OUTER_L4_CKSUM_BAD;
+	else
+		flags |= PKT_RX_OUTER_L4_CKSUM_GOOD;
+
 	return flags;
 }
 
@@ -1399,7 +1375,6 @@ ice_rxd_to_pkt_fields(struct rte_mbuf *mb,
 #endif
 }
 
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 #define ICE_LOOK_AHEAD 8
 #if (ICE_LOOK_AHEAD != 8)
 #error "PMD ICE: ICE_LOOK_AHEAD must be 8\n"
@@ -1620,15 +1595,6 @@ ice_recv_pkts_bulk_alloc(void *rx_queue,
 
 	return nb_rx;
 }
-#else
-static uint16_t
-ice_recv_pkts_bulk_alloc(void __rte_unused *rx_queue,
-			 struct rte_mbuf __rte_unused **rx_pkts,
-			 uint16_t __rte_unused nb_pkts)
-{
-	return 0;
-}
-#endif /* RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC */
 
 static uint16_t
 ice_recv_scattered_pkts(void *rx_queue,
@@ -1872,9 +1838,7 @@ ice_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 		ptypes = ptypes_os;
 
 	if (dev->rx_pkt_burst == ice_recv_pkts ||
-#ifdef RTE_LIBRTE_ICE_RX_ALLOW_BULK_ALLOC
 	    dev->rx_pkt_burst == ice_recv_pkts_bulk_alloc ||
-#endif
 	    dev->rx_pkt_burst == ice_recv_scattered_pkts)
 		return ptypes;
 
@@ -2256,8 +2220,11 @@ ice_parse_tunneling_params(uint64_t ol_flags,
 	*cd_tunneling |= (tx_offload.l2_len >> 1) <<
 		ICE_TXD_CTX_QW0_NATLEN_S;
 
-	if ((ol_flags & PKT_TX_OUTER_UDP_CKSUM) &&
-	    (ol_flags & PKT_TX_OUTER_IP_CKSUM) &&
+	/**
+	 * Calculate the tunneling UDP checksum.
+	 * Shall be set only if L4TUNT = 01b and EIPT is not zero
+	 */
+	if (!(*cd_tunneling & ICE_TX_CTX_EIPT_NONE) &&
 	    (*cd_tunneling & ICE_TXD_CTX_UDP_TUNNELING))
 		*cd_tunneling |= ICE_TXD_CTX_QW0_L4T_CS_M;
 }
@@ -2421,6 +2388,24 @@ ice_set_tso_ctx(struct rte_mbuf *mbuf, union ice_tx_offload tx_offload)
 	return ctx_desc;
 }
 
+/* HW requires that TX buffer size ranges from 1B up to (16K-1)B. */
+#define ICE_MAX_DATA_PER_TXD \
+	(ICE_TXD_QW1_TX_BUF_SZ_M >> ICE_TXD_QW1_TX_BUF_SZ_S)
+/* Calculate the number of TX descriptors needed for each pkt */
+static inline uint16_t
+ice_calc_pkt_desc(struct rte_mbuf *tx_pkt)
+{
+	struct rte_mbuf *txd = tx_pkt;
+	uint16_t count = 0;
+
+	while (txd != NULL) {
+		count += DIV_ROUND_UP(txd->data_len, ICE_MAX_DATA_PER_TXD);
+		txd = txd->next;
+	}
+
+	return count;
+}
+
 uint16_t
 ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 {
@@ -2440,6 +2425,7 @@ ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	uint32_t td_offset = 0;
 	uint32_t td_tag = 0;
 	uint16_t tx_last;
+	uint16_t slen;
 	uint64_t buf_dma_addr;
 	uint64_t ol_flags;
 	union ice_tx_offload tx_offload = {0};
@@ -2452,12 +2438,14 @@ ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 
 	/* Check if the descriptor ring needs to be cleaned. */
 	if (txq->nb_tx_free < txq->tx_free_thresh)
-		ice_xmit_cleanup(txq);
+		(void)ice_xmit_cleanup(txq);
 
 	for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
 		tx_pkt = *tx_pkts++;
 
 		td_cmd = 0;
+		td_tag = 0;
+		td_offset = 0;
 		ol_flags = tx_pkt->ol_flags;
 		tx_offload.l2_len = tx_pkt->l2_len;
 		tx_offload.l3_len = tx_pkt->l3_len;
@@ -2471,8 +2459,15 @@ ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		/* The number of descriptors that must be allocated for
 		 * a packet equals to the number of the segments of that
 		 * packet plus the number of context descriptor if needed.
+		 * Recalculate the needed tx descs when TSO enabled in case
+		 * the mbuf data size exceeds max data size that hw allows
+		 * per tx desc.
 		 */
-		nb_used = (uint16_t)(tx_pkt->nb_segs + nb_ctx);
+		if (ol_flags & PKT_TX_TCP_SEG)
+			nb_used = (uint16_t)(ice_calc_pkt_desc(tx_pkt) +
+					     nb_ctx);
+		else
+			nb_used = (uint16_t)(tx_pkt->nb_segs + nb_ctx);
 		tx_last = (uint16_t)(tx_id + nb_used - 1);
 
 		/* Circular ring */
@@ -2509,10 +2504,9 @@ ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 						   &cd_tunneling_params);
 
 		/* Enable checksum offloading */
-		if (ol_flags & ICE_TX_CKSUM_OFFLOAD_MASK) {
+		if (ol_flags & ICE_TX_CKSUM_OFFLOAD_MASK)
 			ice_txd_enable_checksum(ol_flags, &td_cmd,
 						&td_offset, tx_offload);
-		}
 
 		if (nb_ctx) {
 			/* Setup TX context descriptor if required */
@@ -2562,15 +2556,37 @@ ice_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			txe->mbuf = m_seg;
 
 			/* Setup TX Descriptor */
+			slen = m_seg->data_len;
 			buf_dma_addr = rte_mbuf_data_iova(m_seg);
+
+			while ((ol_flags & PKT_TX_TCP_SEG) &&
+				unlikely(slen > ICE_MAX_DATA_PER_TXD)) {
+				txd->buf_addr = rte_cpu_to_le_64(buf_dma_addr);
+				txd->cmd_type_offset_bsz =
+				rte_cpu_to_le_64(ICE_TX_DESC_DTYPE_DATA |
+				((uint64_t)td_cmd << ICE_TXD_QW1_CMD_S) |
+				((uint64_t)td_offset << ICE_TXD_QW1_OFFSET_S) |
+				((uint64_t)ICE_MAX_DATA_PER_TXD <<
+				 ICE_TXD_QW1_TX_BUF_SZ_S) |
+				((uint64_t)td_tag << ICE_TXD_QW1_L2TAG1_S));
+
+				buf_dma_addr += ICE_MAX_DATA_PER_TXD;
+				slen -= ICE_MAX_DATA_PER_TXD;
+
+				txe->last_id = tx_last;
+				tx_id = txe->next_id;
+				txe = txn;
+				txd = &tx_ring[tx_id];
+				txn = &sw_ring[txe->next_id];
+			}
+
 			txd->buf_addr = rte_cpu_to_le_64(buf_dma_addr);
 			txd->cmd_type_offset_bsz =
 				rte_cpu_to_le_64(ICE_TX_DESC_DTYPE_DATA |
-				((uint64_t)td_cmd  << ICE_TXD_QW1_CMD_S) |
+				((uint64_t)td_cmd << ICE_TXD_QW1_CMD_S) |
 				((uint64_t)td_offset << ICE_TXD_QW1_OFFSET_S) |
-				((uint64_t)m_seg->data_len  <<
-				 ICE_TXD_QW1_TX_BUF_SZ_S) |
-				((uint64_t)td_tag  << ICE_TXD_QW1_L2TAG1_S));
+				((uint64_t)slen << ICE_TXD_QW1_TX_BUF_SZ_S) |
+				((uint64_t)td_tag << ICE_TXD_QW1_L2TAG1_S));
 
 			txe->last_id = tx_last;
 			tx_id = txe->next_id;
@@ -3268,7 +3284,7 @@ ice_get_default_pkt_type(uint16_t ptype)
 		       RTE_PTYPE_L4_TCP,
 		[93] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
 		       RTE_PTYPE_L4_SCTP,
-		[94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV4_EXT_UNKNOWN |
+		[94] = RTE_PTYPE_L2_ETHER | RTE_PTYPE_L3_IPV6_EXT_UNKNOWN |
 		       RTE_PTYPE_L4_ICMP,
 
 		/* IPv6 --> IPv4 */
diff --git a/dpdk/drivers/net/ice/ice_rxtx.h b/dpdk/drivers/net/ice/ice_rxtx.h
index 9e3d2cd076..f80fdc1d6b 100644
--- a/dpdk/drivers/net/ice/ice_rxtx.h
+++ b/dpdk/drivers/net/ice/ice_rxtx.h
@@ -31,7 +31,7 @@
 
 #define ICE_VPMD_RX_BURST           32
 #define ICE_VPMD_TX_BURST           32
-#define ICE_RXQ_REARM_THRESH        32
+#define ICE_RXQ_REARM_THRESH        64
 #define ICE_MAX_RX_BURST            ICE_RXQ_REARM_THRESH
 #define ICE_TX_MAX_FREE_BUF_SZ      64
 #define ICE_DESCS_PER_LOOP          4
@@ -66,7 +66,7 @@ struct ice_rx_queue {
 	uint16_t rxrearm_start;	/**< the idx we start the re-arming from */
 	uint64_t mbuf_initializer; /**< value to init mbufs */
 
-	uint8_t port_id; /* device port ID */
+	uint16_t port_id; /* device port ID */
 	uint8_t crc_len; /* 0 if CRC stripped, 4 otherwise */
 	uint16_t queue_id; /* RX queue index */
 	uint16_t reg_idx; /* RX queue register index */
@@ -109,7 +109,7 @@ struct ice_tx_queue {
 	uint8_t pthresh; /**< Prefetch threshold register. */
 	uint8_t hthresh; /**< Host threshold register. */
 	uint8_t wthresh; /**< Write-back threshold reg. */
-	uint8_t port_id; /* Device port identifier. */
+	uint16_t port_id; /* Device port identifier. */
 	uint16_t queue_id; /* TX queue index. */
 	uint32_t q_teid; /* TX schedule node id. */
 	uint16_t reg_idx;
diff --git a/dpdk/drivers/net/ice/ice_rxtx_vec_avx2.c b/dpdk/drivers/net/ice/ice_rxtx_vec_avx2.c
index be50677c2f..1acda1a383 100644
--- a/dpdk/drivers/net/ice/ice_rxtx_vec_avx2.c
+++ b/dpdk/drivers/net/ice/ice_rxtx_vec_avx2.c
@@ -232,43 +232,88 @@ _ice_recv_raw_pkts_vec_avx2(struct ice_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	 * bit13 is for VLAN indication.
 	 */
 	const __m256i flags_mask =
-		 _mm256_set1_epi32((7 << 4) | (1 << 12) | (1 << 13));
+		 _mm256_set1_epi32((0xF << 4) | (1 << 12) | (1 << 13));
 	/**
 	 * data to be shuffled by the result of the flags mask shifted by 4
 	 * bits.  This gives use the l3_l4 flags.
 	 */
-	const __m256i l3_l4_flags_shuf = _mm256_set_epi8(0, 0, 0, 0, 0, 0, 0, 0,
-			/* shift right 1 bit to make sure it not exceed 255 */
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
-			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
-			 PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
-			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
-			 PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
-			/* second 128-bits */
-			0, 0, 0, 0, 0, 0, 0, 0,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
-			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
-			 PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
-			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
-			 PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1);
+	const __m256i l3_l4_flags_shuf =
+		_mm256_set_epi8((PKT_RX_OUTER_L4_CKSUM_BAD >> 20 |
+		 PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
+		  PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_BAD  |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_BAD  |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		/**
+		 * second 128-bits
+		 * shift right 20 bits to use the low two bits to indicate
+		 * outer checksum status
+		 * shift right 1 bit to make sure it not exceed 255
+		 */
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_BAD  |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_BAD  |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1);
 	const __m256i cksum_mask =
-		 _mm256_set1_epi32(PKT_RX_IP_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD |
-				   PKT_RX_L4_CKSUM_GOOD | PKT_RX_L4_CKSUM_BAD |
-				   PKT_RX_EIP_CKSUM_BAD);
+		 _mm256_set1_epi32(PKT_RX_IP_CKSUM_MASK |
+				   PKT_RX_L4_CKSUM_MASK |
+				   PKT_RX_EIP_CKSUM_BAD |
+				   PKT_RX_OUTER_L4_CKSUM_MASK);
 	/**
 	 * data to be shuffled by result of flag mask, shifted down 12.
 	 * If RSS(bit12)/VLAN(bit13) are set,
@@ -450,6 +495,15 @@ _ice_recv_raw_pkts_vec_avx2(struct ice_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		__m256i l3_l4_flags = _mm256_shuffle_epi8(l3_l4_flags_shuf,
 				_mm256_srli_epi32(flag_bits, 4));
 		l3_l4_flags = _mm256_slli_epi32(l3_l4_flags, 1);
+
+		__m256i l4_outer_mask = _mm256_set1_epi32(0x6);
+		__m256i l4_outer_flags =
+				_mm256_and_si256(l3_l4_flags, l4_outer_mask);
+		l4_outer_flags = _mm256_slli_epi32(l4_outer_flags, 20);
+
+		__m256i l3_l4_mask = _mm256_set1_epi32(~0x6);
+		l3_l4_flags = _mm256_and_si256(l3_l4_flags, l3_l4_mask);
+		l3_l4_flags = _mm256_or_si256(l3_l4_flags, l4_outer_flags);
 		l3_l4_flags = _mm256_and_si256(l3_l4_flags, cksum_mask);
 		/* set rss and vlan flags */
 		const __m256i rss_vlan_flag_bits =
diff --git a/dpdk/drivers/net/ice/ice_rxtx_vec_common.h b/dpdk/drivers/net/ice/ice_rxtx_vec_common.h
index 5e6f89642a..97e26d2968 100644
--- a/dpdk/drivers/net/ice/ice_rxtx_vec_common.h
+++ b/dpdk/drivers/net/ice/ice_rxtx_vec_common.h
@@ -29,6 +29,7 @@ ice_rx_reassemble_packets(struct ice_rx_queue *rxq, struct rte_mbuf **rx_bufs,
 			if (!split_flags[buf_idx]) {
 				/* it's the last packet of the set */
 				start->hash = end->hash;
+				start->vlan_tci = end->vlan_tci;
 				start->ol_flags = end->ol_flags;
 				/* we need to strip crc for the whole packet */
 				start->pkt_len -= rxq->crc_len;
@@ -243,8 +244,10 @@ ice_rx_vec_queue_default(struct ice_rx_queue *rxq)
 #define ICE_NO_VECTOR_FLAGS (				 \
 		DEV_TX_OFFLOAD_MULTI_SEGS |		 \
 		DEV_TX_OFFLOAD_VLAN_INSERT |		 \
+		DEV_TX_OFFLOAD_IPV4_CKSUM |		 \
 		DEV_TX_OFFLOAD_SCTP_CKSUM |		 \
 		DEV_TX_OFFLOAD_UDP_CKSUM |		 \
+		DEV_TX_OFFLOAD_TCP_TSO |		 \
 		DEV_TX_OFFLOAD_TCP_CKSUM)
 
 static inline int
diff --git a/dpdk/drivers/net/ice/ice_rxtx_vec_sse.c b/dpdk/drivers/net/ice/ice_rxtx_vec_sse.c
index 9d5f1f194f..4e6b0a0aa8 100644
--- a/dpdk/drivers/net/ice/ice_rxtx_vec_sse.c
+++ b/dpdk/drivers/net/ice/ice_rxtx_vec_sse.c
@@ -95,39 +95,67 @@ ice_rx_desc_to_olflags_v(struct ice_rx_queue *rxq, __m128i descs[4],
 	 * bit12 for RSS indication.
 	 * bit13 for VLAN indication.
 	 */
-	const __m128i desc_mask = _mm_set_epi32(0x3070, 0x3070,
-						0x3070, 0x3070);
-
+	const __m128i desc_mask = _mm_set_epi32(0x30f0, 0x30f0,
+						0x30f0, 0x30f0);
 	const __m128i cksum_mask = _mm_set_epi32(PKT_RX_IP_CKSUM_MASK |
 						 PKT_RX_L4_CKSUM_MASK |
+						 PKT_RX_OUTER_L4_CKSUM_MASK |
 						 PKT_RX_EIP_CKSUM_BAD,
 						 PKT_RX_IP_CKSUM_MASK |
 						 PKT_RX_L4_CKSUM_MASK |
+						 PKT_RX_OUTER_L4_CKSUM_MASK |
 						 PKT_RX_EIP_CKSUM_BAD,
 						 PKT_RX_IP_CKSUM_MASK |
 						 PKT_RX_L4_CKSUM_MASK |
+						 PKT_RX_OUTER_L4_CKSUM_MASK |
 						 PKT_RX_EIP_CKSUM_BAD,
 						 PKT_RX_IP_CKSUM_MASK |
 						 PKT_RX_L4_CKSUM_MASK |
+						 PKT_RX_OUTER_L4_CKSUM_MASK |
 						 PKT_RX_EIP_CKSUM_BAD);
 
 	/* map the checksum, rss and vlan fields to the checksum, rss
 	 * and vlan flag
 	 */
-	const __m128i cksum_flags = _mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0,
-			/* shift right 1 bit to make sure it not exceed 255 */
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
-			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
-			 PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
-			 PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_GOOD |
-			 PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
-			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
-			(PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1);
+	const __m128i cksum_flags =
+		_mm_set_epi8((PKT_RX_OUTER_L4_CKSUM_BAD >> 20 |
+		 PKT_RX_EIP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD |
+		  PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_BAD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		/**
+		 * shift right 20 bits to use the low two bits to indicate
+		 * outer checksum status
+		 * shift right 1 bit to make sure it not exceed 255
+		 */
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_BAD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_EIP_CKSUM_BAD |
+		 PKT_RX_L4_CKSUM_GOOD | PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_BAD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_BAD) >> 1,
+		(PKT_RX_OUTER_L4_CKSUM_GOOD >> 20 | PKT_RX_L4_CKSUM_GOOD |
+		 PKT_RX_IP_CKSUM_GOOD) >> 1);
 
 	const __m128i rss_vlan_flags = _mm_set_epi8(0, 0, 0, 0,
 			0, 0, 0, 0,
@@ -140,13 +168,21 @@ ice_rx_desc_to_olflags_v(struct ice_rx_queue *rxq, __m128i descs[4],
 	flags = _mm_unpackhi_epi32(descs[0], descs[1]);
 	tmp_desc = _mm_unpackhi_epi32(descs[2], descs[3]);
 	tmp_desc = _mm_unpacklo_epi64(flags, tmp_desc);
-	tmp_desc = _mm_and_si128(flags, desc_mask);
+	tmp_desc = _mm_and_si128(tmp_desc, desc_mask);
 
 	/* checksum flags */
 	tmp_desc = _mm_srli_epi32(tmp_desc, 4);
 	flags = _mm_shuffle_epi8(cksum_flags, tmp_desc);
 	/* then we shift left 1 bit */
 	flags = _mm_slli_epi32(flags, 1);
+
+	__m128i l4_outer_mask = _mm_set_epi32(0x6, 0x6, 0x6, 0x6);
+	__m128i l4_outer_flags = _mm_and_si128(flags, l4_outer_mask);
+	l4_outer_flags = _mm_slli_epi32(l4_outer_flags, 20);
+
+	__m128i l3_l4_mask = _mm_set_epi32(~0x6, ~0x6, ~0x6, ~0x6);
+	__m128i l3_l4_flags = _mm_and_si128(flags, l3_l4_mask);
+	flags = _mm_or_si128(l3_l4_flags, l4_outer_flags);
 	/* we need to mask out the reduntant bits introduced by RSS or
 	 * VLAN fields.
 	 */
@@ -168,10 +204,10 @@ ice_rx_desc_to_olflags_v(struct ice_rx_queue *rxq, __m128i descs[4],
 	 * appropriate flags means that we have to do a shift and blend for
 	 * each mbuf before we do the write.
 	 */
-	rearm0 = _mm_blend_epi16(mbuf_init, _mm_slli_si128(flags, 8), 0x10);
-	rearm1 = _mm_blend_epi16(mbuf_init, _mm_slli_si128(flags, 4), 0x10);
-	rearm2 = _mm_blend_epi16(mbuf_init, flags, 0x10);
-	rearm3 = _mm_blend_epi16(mbuf_init, _mm_srli_si128(flags, 4), 0x10);
+	rearm0 = _mm_blend_epi16(mbuf_init, _mm_slli_si128(flags, 8), 0x30);
+	rearm1 = _mm_blend_epi16(mbuf_init, _mm_slli_si128(flags, 4), 0x30);
+	rearm2 = _mm_blend_epi16(mbuf_init, flags, 0x30);
+	rearm3 = _mm_blend_epi16(mbuf_init, _mm_srli_si128(flags, 4), 0x30);
 
 	/* write the rearm data and the olflags in one write */
 	RTE_BUILD_BUG_ON(offsetof(struct rte_mbuf, ol_flags) !=
@@ -188,10 +224,10 @@ static inline void
 ice_rx_desc_to_ptype_v(__m128i descs[4], struct rte_mbuf **rx_pkts,
 		       uint32_t *ptype_tbl)
 {
-	const __m128i ptype_mask = _mm_set_epi16(0, ICE_RX_FLEX_DESC_PTYPE_M,
-						 0, ICE_RX_FLEX_DESC_PTYPE_M,
-						 0, ICE_RX_FLEX_DESC_PTYPE_M,
-						 0, ICE_RX_FLEX_DESC_PTYPE_M);
+	const __m128i ptype_mask = _mm_set_epi16(ICE_RX_FLEX_DESC_PTYPE_M, 0,
+						 ICE_RX_FLEX_DESC_PTYPE_M, 0,
+						 ICE_RX_FLEX_DESC_PTYPE_M, 0,
+						 ICE_RX_FLEX_DESC_PTYPE_M, 0);
 	__m128i ptype_01 = _mm_unpacklo_epi32(descs[0], descs[1]);
 	__m128i ptype_23 = _mm_unpacklo_epi32(descs[2], descs[3]);
 	__m128i ptype_all = _mm_unpacklo_epi64(ptype_01, ptype_23);
@@ -205,10 +241,11 @@ ice_rx_desc_to_ptype_v(__m128i descs[4], struct rte_mbuf **rx_pkts,
 }
 
 /**
+ * vPMD raw receive routine, only accept(nb_pkts >= ICE_DESCS_PER_LOOP)
+ *
  * Notice:
  * - nb_pkts < ICE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > ICE_VPMD_RX_BURST, only scan ICE_VPMD_RX_BURST
- *   numbers of DD bits
+ * - floor align nb_pkts to a ICE_DESCS_PER_LOOP power-of-two
  */
 static inline uint16_t
 _ice_recv_raw_pkts_vec(struct ice_rx_queue *rxq, struct rte_mbuf **rx_pkts,
@@ -264,9 +301,6 @@ _ice_recv_raw_pkts_vec(struct ice_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	const __m128i eop_check = _mm_set_epi64x(0x0000000200000002LL,
 						 0x0000000200000002LL);
 
-	/* nb_pkts shall be less equal than ICE_MAX_RX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, ICE_MAX_RX_BURST);
-
 	/* nb_pkts has to be floor-aligned to ICE_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, ICE_DESCS_PER_LOOP);
 
@@ -454,15 +488,15 @@ ice_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _ice_recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
-/* vPMD receive routine that reassembles scattered packets
+/**
+ * vPMD receive routine that reassembles single burst of 32 scattered packets
+ *
  * Notice:
  * - nb_pkts < ICE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > ICE_VPMD_RX_BURST, only scan ICE_VPMD_RX_BURST
- *   numbers of DD bits
  */
-uint16_t
-ice_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-			    uint16_t nb_pkts)
+static uint16_t
+ice_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			     uint16_t nb_pkts)
 {
 	struct ice_rx_queue *rxq = rx_queue;
 	uint8_t split_flags[ICE_VPMD_RX_BURST] = {0};
@@ -496,6 +530,32 @@ ice_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 					     &split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+ice_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			    uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > ICE_VPMD_RX_BURST) {
+		uint16_t burst;
+
+		burst = ice_recv_scattered_burst_vec(rx_queue,
+						     rx_pkts + retval,
+						     ICE_VPMD_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < ICE_VPMD_RX_BURST)
+			return retval;
+	}
+
+	return retval + ice_recv_scattered_burst_vec(rx_queue,
+						     rx_pkts + retval,
+						     nb_pkts);
+}
+
 static inline void
 ice_vtx1(volatile struct ice_tx_desc *txdp, struct rte_mbuf *pkt,
 	 uint64_t flags)
diff --git a/dpdk/drivers/net/ice/ice_switch_filter.c b/dpdk/drivers/net/ice/ice_switch_filter.c
index 4a9356b317..03493ee464 100644
--- a/dpdk/drivers/net/ice/ice_switch_filter.c
+++ b/dpdk/drivers/net/ice/ice_switch_filter.c
@@ -25,7 +25,8 @@
 #include "ice_generic_flow.h"
 
 
-#define MAX_QGRP_NUM_TYPE 7
+#define MAX_QGRP_NUM_TYPE	7
+#define MAX_INPUT_SET_BYTE	32
 
 #define ICE_SW_INSET_ETHER ( \
 	ICE_INSET_DMAC | ICE_INSET_SMAC | ICE_INSET_ETHERTYPE)
@@ -97,12 +98,47 @@ struct sw_meta {
 
 static struct ice_flow_parser ice_switch_dist_parser_os;
 static struct ice_flow_parser ice_switch_dist_parser_comms;
-static struct ice_flow_parser ice_switch_perm_parser;
+static struct ice_flow_parser ice_switch_perm_parser_os;
+static struct ice_flow_parser ice_switch_perm_parser_comms;
+
+static struct
+ice_pattern_match_item ice_switch_pattern_dist_os[] = {
+	{pattern_ethertype,
+			ICE_SW_INSET_ETHER, ICE_INSET_NONE},
+	{pattern_eth_arp,
+			ICE_INSET_NONE, ICE_INSET_NONE},
+	{pattern_eth_ipv4,
+			ICE_SW_INSET_MAC_IPV4, ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp,
+			ICE_SW_INSET_MAC_IPV4_UDP, ICE_INSET_NONE},
+	{pattern_eth_ipv4_tcp,
+			ICE_SW_INSET_MAC_IPV4_TCP, ICE_INSET_NONE},
+	{pattern_eth_ipv6,
+			ICE_SW_INSET_MAC_IPV6, ICE_INSET_NONE},
+	{pattern_eth_ipv6_udp,
+			ICE_SW_INSET_MAC_IPV6_UDP, ICE_INSET_NONE},
+	{pattern_eth_ipv6_tcp,
+			ICE_SW_INSET_MAC_IPV6_TCP, ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_vxlan_eth_ipv4,
+			ICE_SW_INSET_DIST_VXLAN_IPV4, ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_udp,
+			ICE_SW_INSET_DIST_VXLAN_IPV4_UDP, ICE_INSET_NONE},
+	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,
+			ICE_SW_INSET_DIST_VXLAN_IPV4_TCP, ICE_INSET_NONE},
+	{pattern_eth_ipv4_nvgre_eth_ipv4,
+			ICE_SW_INSET_DIST_NVGRE_IPV4, ICE_INSET_NONE},
+	{pattern_eth_ipv4_nvgre_eth_ipv4_udp,
+			ICE_SW_INSET_DIST_NVGRE_IPV4_UDP, ICE_INSET_NONE},
+	{pattern_eth_ipv4_nvgre_eth_ipv4_tcp,
+			ICE_SW_INSET_DIST_NVGRE_IPV4_TCP, ICE_INSET_NONE},
+};
 
 static struct
 ice_pattern_match_item ice_switch_pattern_dist_comms[] = {
 	{pattern_ethertype,
 			ICE_SW_INSET_ETHER, ICE_INSET_NONE},
+	{pattern_eth_arp,
+			ICE_INSET_NONE, ICE_INSET_NONE},
 	{pattern_eth_ipv4,
 			ICE_SW_INSET_MAC_IPV4, ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp,
@@ -138,7 +174,7 @@ ice_pattern_match_item ice_switch_pattern_dist_comms[] = {
 };
 
 static struct
-ice_pattern_match_item ice_switch_pattern_dist_os[] = {
+ice_pattern_match_item ice_switch_pattern_perm_os[] = {
 	{pattern_ethertype,
 			ICE_SW_INSET_ETHER, ICE_INSET_NONE},
 	{pattern_eth_arp,
@@ -156,21 +192,25 @@ ice_pattern_match_item ice_switch_pattern_dist_os[] = {
 	{pattern_eth_ipv6_tcp,
 			ICE_SW_INSET_MAC_IPV6_TCP, ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4,
-			ICE_SW_INSET_DIST_VXLAN_IPV4, ICE_INSET_NONE},
+			ICE_SW_INSET_PERM_TUNNEL_IPV4, ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_udp,
-			ICE_SW_INSET_DIST_VXLAN_IPV4_UDP, ICE_INSET_NONE},
+			ICE_SW_INSET_PERM_TUNNEL_IPV4_UDP, ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp_vxlan_eth_ipv4_tcp,
-			ICE_SW_INSET_DIST_VXLAN_IPV4_TCP, ICE_INSET_NONE},
+			ICE_SW_INSET_PERM_TUNNEL_IPV4_TCP, ICE_INSET_NONE},
 	{pattern_eth_ipv4_nvgre_eth_ipv4,
-			ICE_SW_INSET_DIST_NVGRE_IPV4, ICE_INSET_NONE},
+			ICE_SW_INSET_PERM_TUNNEL_IPV4, ICE_INSET_NONE},
 	{pattern_eth_ipv4_nvgre_eth_ipv4_udp,
-			ICE_SW_INSET_DIST_NVGRE_IPV4_UDP, ICE_INSET_NONE},
+			ICE_SW_INSET_PERM_TUNNEL_IPV4_UDP, ICE_INSET_NONE},
 	{pattern_eth_ipv4_nvgre_eth_ipv4_tcp,
-			ICE_SW_INSET_DIST_NVGRE_IPV4_TCP, ICE_INSET_NONE},
+			ICE_SW_INSET_PERM_TUNNEL_IPV4_TCP, ICE_INSET_NONE},
 };
 
 static struct
-ice_pattern_match_item ice_switch_pattern_perm[] = {
+ice_pattern_match_item ice_switch_pattern_perm_comms[] = {
+	{pattern_ethertype,
+			ICE_SW_INSET_ETHER, ICE_INSET_NONE},
+	{pattern_eth_arp,
+		ICE_INSET_NONE, ICE_INSET_NONE},
 	{pattern_eth_ipv4,
 			ICE_SW_INSET_MAC_IPV4, ICE_INSET_NONE},
 	{pattern_eth_ipv4_udp,
@@ -320,6 +360,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 	uint64_t input_set = ICE_INSET_NONE;
+	uint16_t input_set_byte = 0;
 	uint16_t j, t = 0;
 	uint16_t tunnel_valid = 0;
 
@@ -369,6 +410,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						m->src_addr[j] =
 						eth_mask->src.addr_bytes[j];
 						i = 1;
+						input_set_byte++;
 					}
 					if (eth_mask->dst.addr_bytes[j] ==
 								UINT8_MAX) {
@@ -377,6 +419,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						m->dst_addr[j] =
 						eth_mask->dst.addr_bytes[j];
 						i = 1;
+						input_set_byte++;
 					}
 				}
 				if (i)
@@ -387,6 +430,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						eth_spec->type;
 					list[t].m_u.ethertype.ethtype_id =
 						UINT16_MAX;
+					input_set_byte += 2;
 					t++;
 				}
 			} else if (!eth_spec && !eth_mask) {
@@ -458,30 +502,35 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						ipv4_spec->hdr.src_addr;
 					list[t].m_u.ipv4_hdr.src_addr =
 						UINT32_MAX;
+					input_set_byte += 2;
 				}
 				if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
 					list[t].h_u.ipv4_hdr.dst_addr =
 						ipv4_spec->hdr.dst_addr;
 					list[t].m_u.ipv4_hdr.dst_addr =
 						UINT32_MAX;
+					input_set_byte += 2;
 				}
 				if (ipv4_mask->hdr.time_to_live == UINT8_MAX) {
 					list[t].h_u.ipv4_hdr.time_to_live =
 						ipv4_spec->hdr.time_to_live;
 					list[t].m_u.ipv4_hdr.time_to_live =
 						UINT8_MAX;
+					input_set_byte++;
 				}
 				if (ipv4_mask->hdr.next_proto_id == UINT8_MAX) {
 					list[t].h_u.ipv4_hdr.protocol =
 						ipv4_spec->hdr.next_proto_id;
 					list[t].m_u.ipv4_hdr.protocol =
 						UINT8_MAX;
+					input_set_byte++;
 				}
 				if (ipv4_mask->hdr.type_of_service ==
 						UINT8_MAX) {
 					list[t].h_u.ipv4_hdr.tos =
 						ipv4_spec->hdr.type_of_service;
 					list[t].m_u.ipv4_hdr.tos = UINT8_MAX;
+					input_set_byte++;
 				}
 				t++;
 			} else if (!ipv4_spec && !ipv4_mask) {
@@ -563,6 +612,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						ipv6_spec->hdr.src_addr[j];
 						s->src_addr[j] =
 						ipv6_mask->hdr.src_addr[j];
+						input_set_byte++;
 					}
 					if (ipv6_mask->hdr.dst_addr[j] ==
 								UINT8_MAX) {
@@ -570,17 +620,20 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						ipv6_spec->hdr.dst_addr[j];
 						s->dst_addr[j] =
 						ipv6_mask->hdr.dst_addr[j];
+						input_set_byte++;
 					}
 				}
 				if (ipv6_mask->hdr.proto == UINT8_MAX) {
 					f->next_hdr =
 						ipv6_spec->hdr.proto;
 					s->next_hdr = UINT8_MAX;
+					input_set_byte++;
 				}
 				if (ipv6_mask->hdr.hop_limits == UINT8_MAX) {
 					f->hop_limit =
 						ipv6_spec->hdr.hop_limits;
 					s->hop_limit = UINT8_MAX;
+					input_set_byte++;
 				}
 				if ((ipv6_mask->hdr.vtc_flow &
 						rte_cpu_to_be_32
@@ -597,6 +650,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 					f->be_ver_tc_flow = CPU_TO_BE32(vtf.u.val);
 					vtf.u.fld.tc = UINT8_MAX;
 					s->be_ver_tc_flow = CPU_TO_BE32(vtf.u.val);
+					input_set_byte += 4;
 				}
 				t++;
 			} else if (!ipv6_spec && !ipv6_mask) {
@@ -648,14 +702,16 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						udp_spec->hdr.src_port;
 					list[t].m_u.l4_hdr.src_port =
 						udp_mask->hdr.src_port;
+					input_set_byte += 2;
 				}
 				if (udp_mask->hdr.dst_port == UINT16_MAX) {
 					list[t].h_u.l4_hdr.dst_port =
 						udp_spec->hdr.dst_port;
 					list[t].m_u.l4_hdr.dst_port =
 						udp_mask->hdr.dst_port;
+					input_set_byte += 2;
 				}
-						t++;
+				t++;
 			} else if (!udp_spec && !udp_mask) {
 				list[t].type = ICE_UDP_ILOS;
 			}
@@ -705,12 +761,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						tcp_spec->hdr.src_port;
 					list[t].m_u.l4_hdr.src_port =
 						tcp_mask->hdr.src_port;
+					input_set_byte += 2;
 				}
 				if (tcp_mask->hdr.dst_port == UINT16_MAX) {
 					list[t].h_u.l4_hdr.dst_port =
 						tcp_spec->hdr.dst_port;
 					list[t].m_u.l4_hdr.dst_port =
 						tcp_mask->hdr.dst_port;
+					input_set_byte += 2;
 				}
 				t++;
 			} else if (!tcp_spec && !tcp_mask) {
@@ -756,12 +814,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						sctp_spec->hdr.src_port;
 					list[t].m_u.sctp_hdr.src_port =
 						sctp_mask->hdr.src_port;
+					input_set_byte += 2;
 				}
 				if (sctp_mask->hdr.dst_port == UINT16_MAX) {
 					list[t].h_u.sctp_hdr.dst_port =
 						sctp_spec->hdr.dst_port;
 					list[t].m_u.sctp_hdr.dst_port =
 						sctp_mask->hdr.dst_port;
+					input_set_byte += 2;
 				}
 				t++;
 			} else if (!sctp_spec && !sctp_mask) {
@@ -799,6 +859,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						UINT32_MAX;
 					input_set |=
 						ICE_INSET_TUN_VXLAN_VNI;
+					input_set_byte += 2;
 				}
 				t++;
 			} else if (!vxlan_spec && !vxlan_mask) {
@@ -835,6 +896,7 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 						UINT32_MAX;
 					input_set |=
 						ICE_INSET_TUN_NVGRE_TNI;
+					input_set_byte += 2;
 				}
 				t++;
 			} else if (!nvgre_spec && !nvgre_mask) {
@@ -865,13 +927,15 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 					list[t].m_u.vlan_hdr.vlan =
 						UINT16_MAX;
 					input_set |= ICE_INSET_VLAN_OUTER;
+					input_set_byte += 2;
 				}
 				if (vlan_mask->inner_type == UINT16_MAX) {
 					list[t].h_u.vlan_hdr.type =
 						vlan_spec->inner_type;
 					list[t].m_u.vlan_hdr.type =
 						UINT16_MAX;
-					input_set |= ICE_INSET_VLAN_OUTER;
+					input_set |= ICE_INSET_ETHERTYPE;
+					input_set_byte += 2;
 				}
 				t++;
 			} else if (!vlan_spec && !vlan_mask) {
@@ -906,6 +970,14 @@ ice_switch_inset_get(const struct rte_flow_item pattern[],
 		}
 	}
 
+	if (input_set_byte > MAX_INPUT_SET_BYTE) {
+		rte_flow_error_set(error, EINVAL,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			item,
+			"too much input set");
+		return -ENOTSUP;
+	}
+
 	*lkups_num = t;
 
 	return input_set;
@@ -937,6 +1009,8 @@ ice_switch_parse_action(struct ice_pf *pf,
 		switch (action_type) {
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			act_qgrop = action->conf;
+			if (act_qgrop->queue_num <= 1)
+				goto error;
 			rule_info->sw_act.fltr_act =
 				ICE_FWD_TO_QGRP;
 			rule_info->sw_act.fwd_id.q_id =
@@ -997,6 +1071,46 @@ ice_switch_parse_action(struct ice_pf *pf,
 	return -rte_errno;
 }
 
+static int
+ice_switch_check_action(const struct rte_flow_action *actions,
+			    struct rte_flow_error *error)
+{
+	const struct rte_flow_action *action;
+	enum rte_flow_action_type action_type;
+	uint16_t actions_num = 0;
+
+	for (action = actions; action->type !=
+				RTE_FLOW_ACTION_TYPE_END; action++) {
+		action_type = action->type;
+		switch (action_type) {
+		case RTE_FLOW_ACTION_TYPE_VF:
+		case RTE_FLOW_ACTION_TYPE_RSS:
+		case RTE_FLOW_ACTION_TYPE_QUEUE:
+		case RTE_FLOW_ACTION_TYPE_DROP:
+			actions_num++;
+			break;
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			continue;
+		default:
+			rte_flow_error_set(error,
+					   EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+					   actions,
+					   "Invalid action type");
+			return -rte_errno;
+		}
+	}
+
+	if (actions_num != 1) {
+		rte_flow_error_set(error,
+				   EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
+				   actions,
+				   "Invalid action number");
+		return -rte_errno;
+	}
+
+	return 0;
+}
+
 static int
 ice_switch_parse_pattern_action(struct ice_adapter *ad,
 		struct ice_pattern_match_item *array,
@@ -1015,7 +1129,8 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad,
 	uint16_t lkups_num = 0;
 	const struct rte_flow_item *item = pattern;
 	uint16_t item_num = 0;
-	enum ice_sw_tunnel_type tun_type = ICE_NON_TUN;
+	enum ice_sw_tunnel_type tun_type =
+		ICE_SW_TUN_AND_NON_TUN;
 	struct ice_pattern_match_item *pattern_match_item = NULL;
 
 	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
@@ -1051,6 +1166,7 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad,
 		return -rte_errno;
 	}
 
+	memset(&rule_info, 0, sizeof(rule_info));
 	rule_info.tun_type = tun_type;
 
 	sw_meta_ptr =
@@ -1081,6 +1197,14 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad,
 		goto error;
 	}
 
+	ret = ice_switch_check_action(actions, error);
+	if (ret) {
+		rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
+				   "Invalid input action number");
+		goto error;
+	}
+
 	ret = ice_switch_parse_action(pf, actions, error, &rule_info);
 	if (ret) {
 		rte_flow_error_set(error, EINVAL,
@@ -1088,10 +1212,17 @@ ice_switch_parse_pattern_action(struct ice_adapter *ad,
 				   "Invalid input action");
 		goto error;
 	}
-	*meta = sw_meta_ptr;
-	((struct sw_meta *)*meta)->list = list;
-	((struct sw_meta *)*meta)->lkups_num = lkups_num;
-	((struct sw_meta *)*meta)->rule_info = rule_info;
+
+	if (meta) {
+		*meta = sw_meta_ptr;
+		((struct sw_meta *)*meta)->list = list;
+		((struct sw_meta *)*meta)->lkups_num = lkups_num;
+		((struct sw_meta *)*meta)->rule_info = rule_info;
+	} else {
+		rte_free(list);
+		rte_free(sw_meta_ptr);
+	}
+
 	rte_free(pattern_match_item);
 
 	return 0;
@@ -1123,7 +1254,7 @@ ice_switch_init(struct ice_adapter *ad)
 {
 	int ret = 0;
 	struct ice_flow_parser *dist_parser;
-	struct ice_flow_parser *perm_parser = &ice_switch_perm_parser;
+	struct ice_flow_parser *perm_parser;
 
 	if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS)
 		dist_parser = &ice_switch_dist_parser_comms;
@@ -1132,10 +1263,16 @@ ice_switch_init(struct ice_adapter *ad)
 	else
 		return -EINVAL;
 
-	if (ad->devargs.pipe_mode_support)
+	if (ad->devargs.pipe_mode_support) {
+		if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS)
+			perm_parser = &ice_switch_perm_parser_comms;
+		else
+			perm_parser = &ice_switch_perm_parser_os;
+
 		ret = ice_register_parser(perm_parser, ad);
-	else
+	} else {
 		ret = ice_register_parser(dist_parser, ad);
+	}
 	return ret;
 }
 
@@ -1143,17 +1280,25 @@ static void
 ice_switch_uninit(struct ice_adapter *ad)
 {
 	struct ice_flow_parser *dist_parser;
-	struct ice_flow_parser *perm_parser = &ice_switch_perm_parser;
+	struct ice_flow_parser *perm_parser;
 
 	if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS)
 		dist_parser = &ice_switch_dist_parser_comms;
-	else
+	else if (ad->active_pkg_type == ICE_PKG_TYPE_OS_DEFAULT)
 		dist_parser = &ice_switch_dist_parser_os;
+	else
+		return;
+
+	if (ad->devargs.pipe_mode_support) {
+		if (ad->active_pkg_type == ICE_PKG_TYPE_COMMS)
+			perm_parser = &ice_switch_perm_parser_comms;
+		else
+			perm_parser = &ice_switch_perm_parser_os;
 
-	if (ad->devargs.pipe_mode_support)
 		ice_unregister_parser(perm_parser, ad);
-	else
+	} else {
 		ice_unregister_parser(dist_parser, ad);
+	}
 }
 
 static struct
@@ -1186,10 +1331,19 @@ ice_flow_parser ice_switch_dist_parser_comms = {
 };
 
 static struct
-ice_flow_parser ice_switch_perm_parser = {
+ice_flow_parser ice_switch_perm_parser_os = {
+	.engine = &ice_switch_engine,
+	.array = ice_switch_pattern_perm_os,
+	.array_len = RTE_DIM(ice_switch_pattern_perm_os),
+	.parse_pattern_action = ice_switch_parse_pattern_action,
+	.stage = ICE_FLOW_STAGE_PERMISSION,
+};
+
+static struct
+ice_flow_parser ice_switch_perm_parser_comms = {
 	.engine = &ice_switch_engine,
-	.array = ice_switch_pattern_perm,
-	.array_len = RTE_DIM(ice_switch_pattern_perm),
+	.array = ice_switch_pattern_perm_comms,
+	.array_len = RTE_DIM(ice_switch_pattern_perm_comms),
 	.parse_pattern_action = ice_switch_parse_pattern_action,
 	.stage = ICE_FLOW_STAGE_PERMISSION,
 };
diff --git a/dpdk/drivers/net/ifc/base/ifcvf.h b/dpdk/drivers/net/ifc/base/ifcvf.h
index 9be2770fea..3f7497bd02 100644
--- a/dpdk/drivers/net/ifc/base/ifcvf.h
+++ b/dpdk/drivers/net/ifc/base/ifcvf.h
@@ -13,7 +13,10 @@
 #define IFCVF_SUBSYS_DEVICE_ID	0x001A
 
 #define IFCVF_MAX_QUEUES		1
+
+#ifndef VIRTIO_F_IOMMU_PLATFORM
 #define VIRTIO_F_IOMMU_PLATFORM		33
+#endif
 
 /* Common configuration */
 #define IFCVF_PCI_CAP_COMMON_CFG	1
diff --git a/dpdk/drivers/net/ipn3ke/ipn3ke_ethdev.h b/dpdk/drivers/net/ipn3ke/ipn3ke_ethdev.h
index 9b0cf309c8..a6815a9cca 100644
--- a/dpdk/drivers/net/ipn3ke/ipn3ke_ethdev.h
+++ b/dpdk/drivers/net/ipn3ke/ipn3ke_ethdev.h
@@ -640,6 +640,7 @@ ipn3ke_tm_ops_get(struct rte_eth_dev *ethdev,
  */
 #define IPN3KE_ETH_OVERHEAD \
 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + IPN3KE_VLAN_TAG_SIZE * 2)
+#define IPN3KE_ETH_MAX_LEN (RTE_ETHER_MTU + IPN3KE_ETH_OVERHEAD)
 
 #define IPN3KE_MAC_FRAME_SIZE_MAX    9728
 #define IPN3KE_MAC_RX_FRAME_MAXLENGTH    0x00AE
diff --git a/dpdk/drivers/net/ipn3ke/ipn3ke_representor.c b/dpdk/drivers/net/ipn3ke/ipn3ke_representor.c
index 8d9ebef915..d7dada7bde 100644
--- a/dpdk/drivers/net/ipn3ke/ipn3ke_representor.c
+++ b/dpdk/drivers/net/ipn3ke/ipn3ke_representor.c
@@ -701,7 +701,7 @@ struct ipn3ke_rpst_hw_port_stats *hw_stats)
 		&tmp,
 		IPN3KE_25G_TX_STATISTICS_STATUS,
 		port_id,
-		1);
+		0);
 	if (tmp & IPN3KE_25G_TX_STATISTICS_STATUS_SHADOW_REQUEST_MASK) {
 		tmp = 0x00000000;
 		(*hw->f_mac_read)(hw,
@@ -2598,7 +2598,8 @@ ipn3ke_rpst_scan_check(void)
 	int ret;
 
 	if (ipn3ke_rpst_scan_num == 1) {
-		ret = pthread_create(&ipn3ke_rpst_scan_thread,
+		ret = rte_ctrl_thread_create(&ipn3ke_rpst_scan_thread,
+			"ipn3ke scanner",
 			NULL,
 			ipn3ke_rpst_scan_handle_request, NULL);
 		if (ret) {
@@ -2793,7 +2794,7 @@ ipn3ke_rpst_mtu_set(struct rte_eth_dev *ethdev, uint16_t mtu)
 		return -EBUSY;
 	}
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > IPN3KE_ETH_MAX_LEN)
 		dev_data->dev_conf.rxmode.offloads |=
 			(uint64_t)(DEV_RX_OFFLOAD_JUMBO_FRAME);
 	else
diff --git a/dpdk/drivers/net/ipn3ke/meson.build b/dpdk/drivers/net/ipn3ke/meson.build
index e3c8a6768c..0d1dc9866b 100644
--- a/dpdk/drivers/net/ipn3ke/meson.build
+++ b/dpdk/drivers/net/ipn3ke/meson.build
@@ -9,11 +9,7 @@
 #  rte_eth_switch_domain_free()
 #
 
-dep = dependency('libfdt', required: false)
-if not dep.found()
-	dep = cc.find_library('libfdt', required: false)
-endif
-if not dep.found()
+if has_libfdt == 0
 	build = false
 	reason = 'missing dependency, "libfdt"'
 endif
@@ -21,9 +17,11 @@ endif
 if build
 	allow_experimental_apis = true
 
+	includes += include_directories('../../raw/ifpga')
+
 	sources += files('ipn3ke_ethdev.c',
 		'ipn3ke_representor.c',
 		'ipn3ke_tm.c',
 		'ipn3ke_flow.c')
-	deps += ['bus_ifpga', 'sched', 'pmd_i40e', 'rawdev', 'rawdev_ifpga']
+	deps += ['bus_ifpga', 'ethdev', 'sched']
 endif
diff --git a/dpdk/drivers/net/ixgbe/Makefile b/dpdk/drivers/net/ixgbe/Makefile
index 85762e2f2a..31523025b3 100644
--- a/dpdk/drivers/net/ixgbe/Makefile
+++ b/dpdk/drivers/net/ixgbe/Makefile
@@ -57,6 +57,7 @@ endif
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_ethdev -lrte_net -lrte_kvargs -lrte_hash
 LDLIBS += -lrte_bus_pci
+LDLIBS += -lpthread
 
 #
 # Add extra flags for base driver files (also known as shared code)
diff --git a/dpdk/drivers/net/ixgbe/base/README b/dpdk/drivers/net/ixgbe/base/README
index b6b420e2f3..a48b14ed27 100644
--- a/dpdk/drivers/net/ixgbe/base/README
+++ b/dpdk/drivers/net/ixgbe/base/README
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
+ * Copyright(c) 2010-2020 Intel Corporation
  */
 
 Intel® IXGBE driver
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_82598.c b/dpdk/drivers/net/ixgbe/base/ixgbe_82598.c
index 245ff75d55..c83e1c6b30 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_82598.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_82598.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_type.h"
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_82598.h b/dpdk/drivers/net/ixgbe/base/ixgbe_82598.h
index 8013f495ec..7bad5e12d3 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_82598.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_82598.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_82598_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_82599.c b/dpdk/drivers/net/ixgbe/base/ixgbe_82599.c
index 96bdde62c8..9cd0b1428c 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_82599.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_82599.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_type.h"
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_82599.h b/dpdk/drivers/net/ixgbe/base/ixgbe_82599.h
index a32eb1f517..238481983f 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_82599.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_82599.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_82599_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_api.c b/dpdk/drivers/net/ixgbe/base/ixgbe_api.c
index 873c07999c..0a22df3d06 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_api.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_api.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_api.h"
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_api.h b/dpdk/drivers/net/ixgbe/base/ixgbe_api.h
index ff8f7b2611..33e7c3c215 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_api.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_api.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_API_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_common.c b/dpdk/drivers/net/ixgbe/base/ixgbe_common.c
index 62ff767230..9e7182eb33 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_common.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_common.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_common.h"
@@ -3777,11 +3777,11 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
 	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
 		if (mpsar_lo) {
 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
-			mpsar_lo = 0;
+			mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
 		}
 		if (mpsar_hi) {
 			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
-			mpsar_hi = 0;
+			mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
 		}
 	} else if (vmdq < 32) {
 		mpsar_lo &= ~(1 << vmdq);
@@ -4600,7 +4600,8 @@ s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u32 *buffer,
 	 * Read Flash command requires reading buffer length from
 	 * two byes instead of one byte
 	 */
-	if (resp->cmd == 0x30) {
+	if (resp->cmd == IXGBE_HOST_INTERFACE_FLASH_READ_CMD ||
+	    resp->cmd == IXGBE_HOST_INTERFACE_SHADOW_RAM_READ_CMD) {
 		for (; bi < dword_len + 2; bi++) {
 			buffer[bi] = IXGBE_READ_REG_ARRAY(hw, IXGBE_FLEX_MNG,
 							  bi);
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_common.h b/dpdk/drivers/net/ixgbe/base/ixgbe_common.h
index 3bb2475119..7a31f088c4 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_common.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_common.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_COMMON_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.c b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.c
index a590e0e07c..53def2146e 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.h b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.h
index 503d06018f..c2a1013ac0 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_DCB_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.c b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.c
index d87cb58857..dc7b905c5d 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 
@@ -36,14 +36,6 @@ s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
 		stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
 		/* Received Bytes */
 		stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
-
-#if 0
-		/* Can we get rid of these??  Consequently, getting rid
-		 * of the tc_stats structure.
-		 */
-		tc_stats_array[up]->in_overflow_discards = 0;
-		tc_stats_array[up]->out_overflow_discards = 0;
-#endif
 	}
 
 	return IXGBE_SUCCESS;
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.h b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.h
index 1a14744482..8f36881378 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82598.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_DCB_82598_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.c b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.c
index f4f0ff0190..04e0d1fb7d 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.h b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.h
index 085ada27f7..7bd1d6a325 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_dcb_82599.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_DCB_82599_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.c b/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.c
index 67a124d8d1..6005c4ac93 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_vf.h"
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.h b/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.h
index 9664f3bdbf..dd2e1eee4e 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_hv_vf.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_HV_VF_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.c b/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.c
index cb82942dfa..13bdb5f68f 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_type.h"
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.h b/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.h
index 5d32cbc074..1a45e49c2f 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_mbx.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_MBX_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_osdep.h b/dpdk/drivers/net/ixgbe/base/ixgbe_osdep.h
index ea8dc1cbe5..a4eb71777c 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_osdep.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_osdep.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_OS_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_phy.c b/dpdk/drivers/net/ixgbe/base/ixgbe_phy.c
index dd118f9170..a8243fa974 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_phy.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_phy.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_api.h"
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_phy.h b/dpdk/drivers/net/ixgbe/base/ixgbe_phy.h
index f1605f2cc9..a06c3be170 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_phy.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_phy.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_PHY_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_type.h b/dpdk/drivers/net/ixgbe/base/ixgbe_type.h
index 077b8f01c7..bc927a34ee 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_type.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_type.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_TYPE_H_
@@ -4364,4 +4364,16 @@ struct ixgbe_hw {
 #define IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD	\
 				(0x1F << IXGBE_NW_MNG_IF_SEL_MDIO_PHY_ADD_SHIFT)
 
+/* Code Command (Flash I/F Interface) */
+#define IXGBE_HOST_INTERFACE_FLASH_READ_CMD			0x30
+#define IXGBE_HOST_INTERFACE_SHADOW_RAM_READ_CMD		0x31
+#define IXGBE_HOST_INTERFACE_FLASH_WRITE_CMD			0x32
+#define IXGBE_HOST_INTERFACE_SHADOW_RAM_WRITE_CMD		0x33
+#define IXGBE_HOST_INTERFACE_FLASH_MODULE_UPDATE_CMD		0x34
+#define IXGBE_HOST_INTERFACE_FLASH_BLOCK_EREASE_CMD		0x35
+#define IXGBE_HOST_INTERFACE_SHADOW_RAM_DUMP_CMD		0x36
+#define IXGBE_HOST_INTERFACE_FLASH_INFO_CMD			0x37
+#define IXGBE_HOST_INTERFACE_APPLY_UPDATE_CMD			0x38
+#define IXGBE_HOST_INTERFACE_MASK_CMD				0x000000FF
+
 #endif /* _IXGBE_TYPE_H_ */
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_vf.c b/dpdk/drivers/net/ixgbe/base/ixgbe_vf.c
index aac37822e4..7f69ece107 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_vf.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_vf.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_vf.h b/dpdk/drivers/net/ixgbe/base/ixgbe_vf.h
index dba643fced..be58b4f76e 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_vf.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_vf.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_VF_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_x540.c b/dpdk/drivers/net/ixgbe/base/ixgbe_x540.c
index f00f0eae7e..d91633a2da 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_x540.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_x540.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_x540.h"
@@ -784,7 +784,7 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask)
 	 * bits in the SW_FW_SYNC register.
 	 */
 	if (ixgbe_get_swfw_sync_semaphore(hw)) {
-		DEBUGOUT("Failed to get NVM sempahore and register semaphore while forcefully ignoring FW sempahore bit(s) and setting SW semaphore bit(s), returning IXGBE_ERR_SWFW_SYNC\n");
+		DEBUGOUT("Failed to get NVM semaphore and register semaphore while forcefully ignoring FW semaphore bit(s) and setting SW semaphore bit(s), returning IXGBE_ERR_SWFW_SYNC\n");
 		return IXGBE_ERR_SWFW_SYNC;
 	}
 	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw));
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_x540.h b/dpdk/drivers/net/ixgbe/base/ixgbe_x540.h
index 231dfe56e5..ba79847d11 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_x540.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_x540.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_X540_H_
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_x550.c b/dpdk/drivers/net/ixgbe/base/ixgbe_x550.c
index 930a61a20b..9fa999e01d 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_x550.c
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_x550.c
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #include "ixgbe_x550.h"
@@ -1891,7 +1891,14 @@ s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
 		else
 			*speed = IXGBE_LINK_SPEED_10GB_FULL;
 	} else {
+		*autoneg = true;
+
 		switch (hw->phy.type) {
+		case ixgbe_phy_x550em_xfi:
+			*speed = IXGBE_LINK_SPEED_1GB_FULL |
+				 IXGBE_LINK_SPEED_10GB_FULL;
+			*autoneg = false;
+			break;
 		case ixgbe_phy_ext_1g_t:
 #ifdef PREBOOT_SUPPORT
 			*speed = IXGBE_LINK_SPEED_1GB_FULL;
@@ -1925,7 +1932,6 @@ s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
 				 IXGBE_LINK_SPEED_1GB_FULL;
 			break;
 		}
-		*autoneg = true;
 	}
 
 	return IXGBE_SUCCESS;
diff --git a/dpdk/drivers/net/ixgbe/base/ixgbe_x550.h b/dpdk/drivers/net/ixgbe/base/ixgbe_x550.h
index 3bd98f243d..10086ab423 100644
--- a/dpdk/drivers/net/ixgbe/base/ixgbe_x550.h
+++ b/dpdk/drivers/net/ixgbe/base/ixgbe_x550.h
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2001-2018
+ * Copyright(c) 2001-2020 Intel Corporation
  */
 
 #ifndef _IXGBE_X550_H_
diff --git a/dpdk/drivers/net/ixgbe/base/meson.build b/dpdk/drivers/net/ixgbe/base/meson.build
index bbd0f51ea5..20677ab034 100644
--- a/dpdk/drivers/net/ixgbe/base/meson.build
+++ b/dpdk/drivers/net/ixgbe/base/meson.build
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2017 Intel Corporation
+# Copyright(c) 2017-2020 Intel Corporation
 
 sources = [
 	'ixgbe_82598.c',
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_ethdev.c b/dpdk/drivers/net/ixgbe/ixgbe_ethdev.c
index 2c6fd0f131..dcd7291b97 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -229,7 +229,9 @@ static int ixgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
 static int ixgbe_dev_interrupt_action(struct rte_eth_dev *dev);
 static void ixgbe_dev_interrupt_handler(void *param);
 static void ixgbe_dev_interrupt_delayed_handler(void *param);
-static void ixgbe_dev_setup_link_alarm_handler(void *param);
+static void *ixgbe_dev_setup_link_thread_handler(void *param);
+static int ixgbe_dev_wait_setup_link_complete(struct rte_eth_dev *dev,
+					      uint32_t timeout_ms);
 
 static int ixgbe_add_rar(struct rte_eth_dev *dev,
 			struct rte_ether_addr *mac_addr,
@@ -378,6 +380,7 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 					 struct rte_eth_udp_tunnel *udp_tunnel);
 static int ixgbe_filter_restore(struct rte_eth_dev *dev);
 static void ixgbe_l2_tunnel_conf(struct rte_eth_dev *dev);
+static int ixgbe_wait_for_link_up(struct ixgbe_hw *hw);
 
 /*
  * Define VF Stats MACRO for Non "cleared on read" register
@@ -1075,6 +1078,7 @@ ixgbe_swfw_lock_reset(struct ixgbe_hw *hw)
 static int
 eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 {
+	struct ixgbe_adapter *ad = eth_dev->data->dev_private;
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw =
@@ -1091,7 +1095,7 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 		IXGBE_DEV_PRIVATE_TO_BW_CONF(eth_dev->data->dev_private);
 	uint32_t ctrl_ext;
 	uint16_t csum;
-	int diag, i;
+	int diag, i, ret;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -1126,6 +1130,7 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 		return 0;
 	}
 
+	rte_atomic32_clear(&ad->link_thread_running);
 	rte_eth_copy_pci_info(eth_dev, pci_dev);
 
 	/* Vendor and Device ID need to be set before init of shared code */
@@ -1170,8 +1175,8 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	memset(dcb_config, 0, sizeof(struct ixgbe_dcb_config));
 	ixgbe_dcb_init(hw, dcb_config);
 	/* Get Hardware Flow Control setting */
-	hw->fc.requested_mode = ixgbe_fc_full;
-	hw->fc.current_mode = ixgbe_fc_full;
+	hw->fc.requested_mode = ixgbe_fc_none;
+	hw->fc.current_mode = ixgbe_fc_none;
 	hw->fc.pause_time = IXGBE_FC_PAUSE;
 	for (i = 0; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
 		hw->fc.low_water[i] = IXGBE_FC_LO;
@@ -1190,7 +1195,6 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	diag = ixgbe_bypass_init_hw(hw);
 #else
 	diag = ixgbe_init_hw(hw);
-	hw->mac.autotry_restart = false;
 #endif /* RTE_LIBRTE_IXGBE_BYPASS */
 
 	/*
@@ -1270,7 +1274,14 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	memset(hwstrip, 0, sizeof(*hwstrip));
 
 	/* initialize PF if max_vfs not zero */
-	ixgbe_pf_host_init(eth_dev);
+	ret = ixgbe_pf_host_init(eth_dev);
+	if (ret) {
+		rte_free(eth_dev->data->mac_addrs);
+		eth_dev->data->mac_addrs = NULL;
+		rte_free(eth_dev->data->hash_mac_addrs);
+		eth_dev->data->hash_mac_addrs = NULL;
+		return ret;
+	}
 
 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
 	/* let hardware know driver is loaded */
@@ -1301,8 +1312,6 @@ eth_ixgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	/* enable support intr */
 	ixgbe_enable_intr(eth_dev);
 
-	ixgbe_dev_set_link_down(eth_dev);
-
 	/* initialize filter info */
 	memset(filter_info, 0,
 	       sizeof(struct ixgbe_filter_info));
@@ -1564,6 +1573,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
 {
 	int diag;
 	uint32_t tc, tcs;
+	struct ixgbe_adapter *ad = eth_dev->data->dev_private;
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
 	struct ixgbe_hw *hw =
@@ -1604,6 +1614,7 @@ eth_ixgbevf_dev_init(struct rte_eth_dev *eth_dev)
 		return 0;
 	}
 
+	rte_atomic32_clear(&ad->link_thread_running);
 	ixgbevf_parse_devargs(eth_dev->data->dev_private,
 			      pci_dev->device.devargs);
 
@@ -2530,6 +2541,41 @@ ixgbe_set_vf_rate_limit(struct rte_eth_dev *dev, uint16_t vf,
 	return 0;
 }
 
+static int
+ixgbe_flow_ctrl_enable(struct rte_eth_dev *dev, struct ixgbe_hw *hw)
+{
+	struct ixgbe_adapter *adapter = dev->data->dev_private;
+	int err;
+	uint32_t mflcn;
+
+	ixgbe_setup_fc(hw);
+
+	err = ixgbe_fc_enable(hw);
+
+	/* Not negotiated is not an error case */
+	if (err == IXGBE_SUCCESS || err == IXGBE_ERR_FC_NOT_NEGOTIATED) {
+		/*
+		 *check if we want to forward MAC frames - driver doesn't
+		 *have native capability to do that,
+		 *so we'll write the registers ourselves
+		 */
+
+		mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+
+		/* set or clear MFLCN.PMCF bit depending on configuration */
+		if (adapter->mac_ctrl_frame_fwd != 0)
+			mflcn |= IXGBE_MFLCN_PMCF;
+		else
+			mflcn &= ~IXGBE_MFLCN_PMCF;
+
+		IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn);
+		IXGBE_WRITE_FLUSH(hw);
+
+		return 0;
+	}
+	return err;
+}
+
 /*
  * Configure device link speed and setup link.
  * It returns 0 on success.
@@ -2558,19 +2604,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
 	PMD_INIT_FUNC_TRACE();
 
-	/* IXGBE devices don't support:
-	*    - half duplex (checked afterwards for valid speeds)
-	*    - fixed speed: TODO implement
-	*/
-	if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
-		PMD_INIT_LOG(ERR,
-		"Invalid link_speeds for port %u, fix speed not supported",
-				dev->data->port_id);
-		return -EINVAL;
-	}
-
 	/* Stop the link setup handler before resetting the HW. */
-	rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
+	ixgbe_dev_wait_setup_link_complete(dev, 0);
 
 	/* disable uio/vfio intr/eventfd mapping */
 	rte_intr_disable(intr_handle);
@@ -2666,6 +2701,12 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 
 	ixgbe_restore_statistics_mapping(dev);
 
+	err = ixgbe_flow_ctrl_enable(dev, hw);
+	if (err < 0) {
+		PMD_INIT_LOG(ERR, "enable flow ctrl err");
+		goto error;
+	}
+
 	err = ixgbe_dev_rxtx_start(dev);
 	if (err < 0) {
 		PMD_INIT_LOG(ERR, "Unable to start rxtx queues");
@@ -2724,7 +2765,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 	}
 
 	link_speeds = &dev->data->dev_conf.link_speeds;
-	if (*link_speeds & ~allowed_speeds) {
+
+	/* Ignore autoneg flag bit and check the validity of 
+	 * link_speed 
+	 */
+	if (((*link_speeds) >> 1) & ~(allowed_speeds >> 1)) {
 		PMD_INIT_LOG(ERR, "Invalid link setting");
 		goto error;
 	}
@@ -2801,6 +2846,11 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
 			    "please call hierarchy_commit() "
 			    "before starting the port");
 
+	/* wait for the controller to acquire link */
+	err = ixgbe_wait_for_link_up(hw);
+	if (err)
+		goto error;
+
 	/*
 	 * Update link status right before return, because it may
 	 * start link configuration process in a separate thread.
@@ -2842,7 +2892,7 @@ ixgbe_dev_stop(struct rte_eth_dev *dev)
 
 	PMD_INIT_FUNC_TRACE();
 
-	rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
+	ixgbe_dev_wait_setup_link_complete(dev, 0);
 
 	/* disable interrupts */
 	ixgbe_disable_intr(hw);
@@ -4095,16 +4145,46 @@ ixgbevf_check_link(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 	return ret_val;
 }
 
-static void
-ixgbe_dev_setup_link_alarm_handler(void *param)
+/*
+ * If @timeout_ms was 0, it means that it will not return until link complete.
+ * It returns 1 on complete, return 0 on timeout.
+ */
+static int
+ixgbe_dev_wait_setup_link_complete(struct rte_eth_dev *dev, uint32_t timeout_ms)
+{
+#define WARNING_TIMEOUT    9000 /* 9s  in total */
+	struct ixgbe_adapter *ad = dev->data->dev_private;
+	uint32_t timeout = timeout_ms ? timeout_ms : WARNING_TIMEOUT;
+
+	while (rte_atomic32_read(&ad->link_thread_running)) {
+		msec_delay(1);
+		timeout--;
+
+		if (timeout_ms) {
+			if (!timeout)
+				return 0;
+		} else if (!timeout) {
+			/* It will not return until link complete */
+			timeout = WARNING_TIMEOUT;
+			PMD_DRV_LOG(ERR, "IXGBE link thread not complete too long time!");
+		}
+	}
+
+	return 1;
+}
+
+static void *
+ixgbe_dev_setup_link_thread_handler(void *param)
 {
 	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+	struct ixgbe_adapter *ad = dev->data->dev_private;
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	struct ixgbe_interrupt *intr =
 		IXGBE_DEV_PRIVATE_TO_INTR(dev->data->dev_private);
 	u32 speed;
 	bool autoneg = false;
 
+	pthread_detach(pthread_self());
 	speed = hw->phy.autoneg_advertised;
 	if (!speed)
 		ixgbe_get_link_capabilities(hw, &speed, &autoneg);
@@ -4112,6 +4192,40 @@ ixgbe_dev_setup_link_alarm_handler(void *param)
 	ixgbe_setup_link(hw, speed, true);
 
 	intr->flags &= ~IXGBE_FLAG_NEED_LINK_CONFIG;
+	rte_atomic32_clear(&ad->link_thread_running);
+	return NULL;
+}
+
+/*
+ * In freebsd environment, nic_uio drivers do not support interrupts,
+ * rte_intr_callback_register() will fail to register interrupts.
+ * We can not make link status to change from down to up by interrupt
+ * callback. So we need to wait for the controller to acquire link
+ * when ports start.
+ * It returns 0 on link up.
+ */
+static int
+ixgbe_wait_for_link_up(struct ixgbe_hw *hw)
+{
+#ifdef RTE_EXEC_ENV_FREEBSD
+	int err, i, link_up = 0;
+	uint32_t speed = 0;
+	const int nb_iter = 25;
+
+	for (i = 0; i < nb_iter; i++) {
+		err = ixgbe_check_link(hw, &speed, &link_up, 0);
+		if (err)
+			return err;
+		if (link_up)
+			return 0;
+		msec_delay(200);
+	}
+
+	return 0;
+#else
+	RTE_SET_USED(hw);
+	return 0;
+#endif
 }
 
 /* return 0 means link status changed, -1 means not changed */
@@ -4120,6 +4234,7 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			    int wait_to_complete, int vf)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_adapter *ad = dev->data->dev_private;
 	struct rte_eth_link link;
 	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	struct ixgbe_interrupt *intr =
@@ -4133,7 +4248,8 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 	link.link_status = ETH_LINK_DOWN;
 	link.link_speed = ETH_SPEED_NUM_NONE;
 	link.link_duplex = ETH_LINK_HALF_DUPLEX;
-	link.link_autoneg = ETH_LINK_AUTONEG;
+	link.link_autoneg = !(dev->data->dev_conf.link_speeds &
+			ETH_LINK_SPEED_FIXED);
 
 	hw->mac.get_link_status = true;
 
@@ -4144,6 +4260,11 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 	if (wait_to_complete == 0 || dev->data->dev_conf.intr_conf.lsc != 0)
 		wait = 0;
 
+/* BSD has no interrupt mechanism, so force NIC status synchronization. */
+#ifdef RTE_EXEC_ENV_FREEBSD
+	wait = 1;
+#endif
+
 	if (vf)
 		diag = ixgbevf_check_link(hw, &link_speed, &link_up, wait);
 	else
@@ -4155,15 +4276,34 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 		return rte_eth_linkstatus_set(dev, &link);
 	}
 
-	esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
-	if ((esdp_reg & IXGBE_ESDP_SDP3))
-		link_up = 0;
+	if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {
+		esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+		if ((esdp_reg & IXGBE_ESDP_SDP3))
+			link_up = 0;
+	}
 
 	if (link_up == 0) {
 		if (ixgbe_get_media_type(hw) == ixgbe_media_type_fiber) {
-			intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
-			rte_eal_alarm_set(10,
-				ixgbe_dev_setup_link_alarm_handler, dev);
+			ixgbe_dev_wait_setup_link_complete(dev, 0);
+			if (rte_atomic32_test_and_set(&ad->link_thread_running)) {
+				/* To avoid race condition between threads, set
+				 * the IXGBE_FLAG_NEED_LINK_CONFIG flag only
+				 * when there is no link thread running.
+				 */
+				intr->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
+				if (rte_ctrl_thread_create(&ad->link_thread_tid,
+					"ixgbe-link-handler",
+					NULL,
+					ixgbe_dev_setup_link_thread_handler,
+					dev) < 0) {
+					PMD_DRV_LOG(ERR,
+						"Create link thread failed!");
+					rte_atomic32_clear(&ad->link_thread_running);
+				}
+			} else {
+				PMD_DRV_LOG(ERR,
+					"Other link thread is running now!");
+			}
 		}
 		return rte_eth_linkstatus_set(dev, &link);
 	}
@@ -4181,6 +4321,10 @@ ixgbe_dev_link_update_share(struct rte_eth_dev *dev,
 			link.link_speed = ETH_SPEED_NUM_100M;
 		break;
 
+	case IXGBE_LINK_SPEED_10_FULL:
+		link.link_speed = ETH_SPEED_NUM_10M;
+		break;
+
 	case IXGBE_LINK_SPEED_100_FULL:
 		link.link_speed = ETH_SPEED_NUM_100M;
 		break;
@@ -4615,6 +4759,11 @@ ixgbe_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 	 * MFLCN register.
 	 */
 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+	if (mflcn_reg & IXGBE_MFLCN_PMCF)
+		fc_conf->mac_ctrl_frame_fwd = 1;
+	else
+		fc_conf->mac_ctrl_frame_fwd = 0;
+
 	if (mflcn_reg & (IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_RFCE))
 		rx_pause = 1;
 	else
@@ -4646,10 +4795,10 @@ static int
 ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 {
 	struct ixgbe_hw *hw;
+	struct ixgbe_adapter *adapter = dev->data->dev_private;
 	int err;
 	uint32_t rx_buf_size;
 	uint32_t max_high_water;
-	uint32_t mflcn;
 	enum ixgbe_fc_mode rte_fcmode_2_ixgbe_fcmode[] = {
 		ixgbe_fc_none,
 		ixgbe_fc_rx_pause,
@@ -4682,31 +4831,14 @@ ixgbe_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 	hw->fc.low_water[0]   = fc_conf->low_water;
 	hw->fc.send_xon       = fc_conf->send_xon;
 	hw->fc.disable_fc_autoneg = !fc_conf->autoneg;
+	adapter->mac_ctrl_frame_fwd = fc_conf->mac_ctrl_frame_fwd;
 
-	err = ixgbe_fc_enable(hw);
-
-	/* Not negotiated is not an error case */
-	if ((err == IXGBE_SUCCESS) || (err == IXGBE_ERR_FC_NOT_NEGOTIATED)) {
-
-		/* check if we want to forward MAC frames - driver doesn't have native
-		 * capability to do that, so we'll write the registers ourselves */
-
-		mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-
-		/* set or clear MFLCN.PMCF bit depending on configuration */
-		if (fc_conf->mac_ctrl_frame_fwd != 0)
-			mflcn |= IXGBE_MFLCN_PMCF;
-		else
-			mflcn &= ~IXGBE_MFLCN_PMCF;
-
-		IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn);
-		IXGBE_WRITE_FLUSH(hw);
-
-		return 0;
+	err = ixgbe_flow_ctrl_enable(dev, hw);
+	if (err < 0) {
+		PMD_INIT_LOG(ERR, "ixgbe_flow_ctrl_enable = 0x%x", err);
+		return -EIO;
 	}
-
-	PMD_INIT_LOG(ERR, "ixgbe_fc_enable = 0x%x", err);
-	return -EIO;
+	return err;
 }
 
 /**
@@ -5090,7 +5222,7 @@ ixgbe_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
 
 	/* switch to jumbo mode if needed */
-	if (frame_size > RTE_ETHER_MAX_LEN) {
+	if (frame_size > IXGBE_ETH_MAX_LEN) {
 		dev->data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 		hlreg0 |= IXGBE_HLREG0_JUMBOEN;
@@ -5207,13 +5339,19 @@ ixgbevf_dev_start(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	/* Stop the link setup handler before resetting the HW. */
-	rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
+	ixgbe_dev_wait_setup_link_complete(dev, 0);
 
 	err = hw->mac.ops.reset_hw(hw);
-	if (err) {
+
+	/**
+	 * In this case, reuses the MAC address assigned by VF
+	 * initialization.
+	 */
+	if (err != IXGBE_SUCCESS && err != IXGBE_ERR_INVALID_MAC_ADDR) {
 		PMD_INIT_LOG(ERR, "Unable to reset vf hardware (%d)", err);
 		return err;
 	}
+
 	hw->mac.get_link_status = true;
 
 	/* negotiate mailbox API version to use with the PF. */
@@ -5305,7 +5443,7 @@ ixgbevf_dev_stop(struct rte_eth_dev *dev)
 
 	PMD_INIT_FUNC_TRACE();
 
-	rte_eal_alarm_cancel(ixgbe_dev_setup_link_alarm_handler, dev);
+	ixgbe_dev_wait_setup_link_complete(dev, 0);
 
 	ixgbevf_intr_disable(dev);
 
@@ -6520,7 +6658,8 @@ ixgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 	 * prior to 3.11.33 which contains the following change:
 	 * "ixgbe: Enable jumbo frames support w/ SR-IOV"
 	 */
-	ixgbevf_rlpml_set_vf(hw, max_frame);
+	if (ixgbevf_rlpml_set_vf(hw, max_frame))
+		return -EINVAL;
 
 	/* update max frame size */
 	dev->data->dev_conf.rxmode.max_rx_pkt_len = max_frame;
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_ethdev.h b/dpdk/drivers/net/ixgbe/ixgbe_ethdev.h
index 76a1b9d184..e406b754e8 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/dpdk/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -104,6 +104,9 @@
 /* The overhead from MTU to max frame size. */
 #define IXGBE_ETH_OVERHEAD (RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
 
+/* The max frame size with default MTU */
+#define IXGBE_ETH_MAX_LEN  (RTE_ETHER_MTU + IXGBE_ETH_OVERHEAD)
+
 /* bit of VXLAN tunnel type | 7 bits of zeros  | 8 bits of zeros*/
 #define IXGBE_FDIR_VXLAN_TUNNEL_TYPE    0x8000
 /* bit of NVGRE tunnel type | 7 bits of zeros  | 8 bits of zeros*/
@@ -510,6 +513,9 @@ struct ixgbe_adapter {
 	 * mailbox status) link status.
 	 */
 	uint8_t pflink_fullchk;
+	uint8_t mac_ctrl_frame_fwd;
+	rte_atomic32_t link_thread_running;
+	pthread_t link_thread_tid;
 };
 
 struct ixgbe_vf_representor {
@@ -709,7 +715,7 @@ void ixgbe_vlan_hw_filter_disable(struct rte_eth_dev *dev);
 
 void ixgbe_vlan_hw_strip_config(struct rte_eth_dev *dev);
 
-void ixgbe_pf_host_init(struct rte_eth_dev *eth_dev);
+int ixgbe_pf_host_init(struct rte_eth_dev *eth_dev);
 
 void ixgbe_pf_host_uninit(struct rte_eth_dev *eth_dev);
 
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_fdir.c b/dpdk/drivers/net/ixgbe/ixgbe_fdir.c
index 166dae1e03..9ff5aa8c72 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_fdir.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_fdir.c
@@ -515,9 +515,30 @@ ixgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
 				uint16_t offset)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_hw_fdir_info *fdir_info =
+		IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private);
 	uint32_t fdirctrl;
 	int i;
 
+	if (fdir_info->flex_bytes_offset == offset)
+		return 0;
+
+	/**
+	 * 82599 adapters flow director init flow cannot be restarted,
+	 * Workaround 82599 silicon errata by performing the following steps
+	 * before re-writing the FDIRCTRL control register with the same value.
+	 * - write 1 to bit 8 of FDIRCMD register &
+	 * - write 0 to bit 8 of FDIRCMD register
+	 */
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) |
+			 IXGBE_FDIRCMD_CLEARHT));
+	IXGBE_WRITE_FLUSH(hw);
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
+			(IXGBE_READ_REG(hw, IXGBE_FDIRCMD) &
+			 ~IXGBE_FDIRCMD_CLEARHT));
+	IXGBE_WRITE_FLUSH(hw);
+
 	fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
 
 	fdirctrl &= ~IXGBE_FDIRCTRL_FLEX_MASK;
@@ -532,6 +553,14 @@ ixgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
 			break;
 		msec_delay(1);
 	}
+
+	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
+		PMD_DRV_LOG(ERR, "Flow Director poll time exceeded!");
+		return -ETIMEDOUT;
+	}
+
+	fdir_info->flex_bytes_offset = offset;
+
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_flow.c b/dpdk/drivers/net/ixgbe/ixgbe_flow.c
index b2a2bfc02f..d539951896 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_flow.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_flow.c
@@ -870,15 +870,6 @@ ixgbe_parse_ethertype_filter(struct rte_eth_dev *dev,
 	if (ret)
 		return ret;
 
-	/* Ixgbe doesn't support MAC address. */
-	if (filter->flags & RTE_ETHTYPE_FLAGS_MAC) {
-		memset(filter, 0, sizeof(struct rte_eth_ethertype_filter));
-		rte_flow_error_set(error, EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			NULL, "Not supported by ethertype filter");
-		return -rte_errno;
-	}
-
 	if (filter->queue >= dev->data->nb_rx_queues) {
 		memset(filter, 0, sizeof(struct rte_eth_ethertype_filter));
 		rte_flow_error_set(error, EINVAL,
@@ -3146,13 +3137,13 @@ ixgbe_flow_create(struct rte_eth_dev *dev,
 				rte_memcpy(&fdir_info->mask,
 					&fdir_rule.mask,
 					sizeof(struct ixgbe_hw_fdir_mask));
-				fdir_info->flex_bytes_offset =
-					fdir_rule.flex_bytes_offset;
 
-				if (fdir_rule.mask.flex_bytes_mask)
-					ixgbe_fdir_set_flexbytes_offset(dev,
+				if (fdir_rule.mask.flex_bytes_mask) {
+					ret = ixgbe_fdir_set_flexbytes_offset(dev,
 						fdir_rule.flex_bytes_offset);
-
+					if (ret)
+						goto out;
+				}
 				ret = ixgbe_fdir_set_input_mask(dev);
 				if (ret)
 					goto out;
@@ -3170,8 +3161,9 @@ ixgbe_flow_create(struct rte_eth_dev *dev,
 				if (ret)
 					goto out;
 
-				if (fdir_info->flex_bytes_offset !=
-						fdir_rule.flex_bytes_offset)
+				if (fdir_rule.mask.flex_bytes_mask &&
+				    fdir_info->flex_bytes_offset !=
+				    fdir_rule.flex_bytes_offset)
 					goto out;
 			}
 		}
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_pf.c b/dpdk/drivers/net/ixgbe/ixgbe_pf.c
index d0d85e1386..2e46e30b79 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_pf.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_pf.c
@@ -66,7 +66,7 @@ ixgbe_mb_intr_setup(struct rte_eth_dev *dev)
 	return 0;
 }
 
-void ixgbe_pf_host_init(struct rte_eth_dev *eth_dev)
+int ixgbe_pf_host_init(struct rte_eth_dev *eth_dev)
 {
 	struct ixgbe_vf_info **vfinfo =
 		IXGBE_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private);
@@ -78,19 +78,27 @@ void ixgbe_pf_host_init(struct rte_eth_dev *eth_dev)
 		IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
 	uint16_t vf_num;
 	uint8_t nb_queue;
+	int ret = 0;
 
 	PMD_INIT_FUNC_TRACE();
 
 	RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
 	vf_num = dev_num_vf(eth_dev);
 	if (vf_num == 0)
-		return;
+		return ret;
 
 	*vfinfo = rte_zmalloc("vf_info", sizeof(struct ixgbe_vf_info) * vf_num, 0);
 	if (*vfinfo == NULL)
 		rte_panic("Cannot allocate memory for private VF data\n");
 
-	rte_eth_switch_domain_alloc(&(*vfinfo)->switch_domain_id);
+	ret = rte_eth_switch_domain_alloc(&(*vfinfo)->switch_domain_id);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+			"failed to allocate switch domain for device %d", ret);
+		rte_free(*vfinfo);
+		*vfinfo = NULL;
+		return ret;
+	}
 
 	memset(mirror_info, 0, sizeof(struct ixgbe_mirror_info));
 	memset(uta_info, 0, sizeof(struct ixgbe_uta_info));
@@ -118,6 +126,8 @@ void ixgbe_pf_host_init(struct rte_eth_dev *eth_dev)
 
 	/* set mb interrupt mask */
 	ixgbe_mb_intr_setup(eth_dev);
+
+	return ret;
 }
 
 void ixgbe_pf_host_uninit(struct rte_eth_dev *eth_dev)
@@ -542,16 +552,44 @@ static int
 ixgbe_set_vf_lpe(struct rte_eth_dev *dev, __rte_unused uint32_t vf, uint32_t *msgbuf)
 {
 	struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
-	uint32_t new_mtu = msgbuf[1];
+	uint32_t max_frame = msgbuf[1];
 	uint32_t max_frs;
-	int max_frame = new_mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
+	uint32_t hlreg0;
 
 	/* X540 and X550 support jumbo frames in IOV mode */
 	if (hw->mac.type != ixgbe_mac_X540 &&
 		hw->mac.type != ixgbe_mac_X550 &&
 		hw->mac.type != ixgbe_mac_X550EM_x &&
-		hw->mac.type != ixgbe_mac_X550EM_a)
-		return -1;
+		hw->mac.type != ixgbe_mac_X550EM_a) {
+		struct ixgbe_vf_info *vfinfo =
+			*IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private);
+
+		switch (vfinfo[vf].api_version) {
+		case ixgbe_mbox_api_11:
+		case ixgbe_mbox_api_12:
+		case ixgbe_mbox_api_13:
+			 /**
+			  * Version 1.1&1.2&1.3 supports jumbo frames on VFs
+			  * if PF has jumbo frames enabled which means legacy
+			  * VFs are disabled.
+			  */
+			if (dev->data->dev_conf.rxmode.max_rx_pkt_len >
+			    IXGBE_ETH_MAX_LEN)
+				break;
+			/* fall through */
+		default:
+			/**
+			 * If the PF or VF are running w/ jumbo frames enabled,
+			 * we return -1 as we cannot support jumbo frames on
+			 * legacy VFs.
+			 */
+			if (max_frame > IXGBE_ETH_MAX_LEN ||
+			    dev->data->dev_conf.rxmode.max_rx_pkt_len >
+			    IXGBE_ETH_MAX_LEN)
+				return -1;
+			break;
+		}
+	}
 
 	if (max_frame < RTE_ETHER_MIN_LEN ||
 			max_frame > RTE_ETHER_MAX_JUMBO_FRAME_LEN)
@@ -559,8 +597,20 @@ ixgbe_set_vf_lpe(struct rte_eth_dev *dev, __rte_unused uint32_t vf, uint32_t *ms
 
 	max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
 		   IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
-	if (max_frs < new_mtu) {
-		max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+	if (max_frs < max_frame) {
+		hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+		if (max_frame > IXGBE_ETH_MAX_LEN) {
+			dev->data->dev_conf.rxmode.offloads |=
+				DEV_RX_OFFLOAD_JUMBO_FRAME;
+			hlreg0 |= IXGBE_HLREG0_JUMBOEN;
+		} else {
+			dev->data->dev_conf.rxmode.offloads &=
+				~DEV_RX_OFFLOAD_JUMBO_FRAME;
+			hlreg0 &= ~IXGBE_HLREG0_JUMBOEN;
+		}
+		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
+
+		max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT;
 		IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
 	}
 
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_rxtx.c b/dpdk/drivers/net/ixgbe/ixgbe_rxtx.c
index fa572d184d..8b9b009396 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -87,11 +87,6 @@
 #define rte_ixgbe_prefetch(p)   do {} while (0)
 #endif
 
-#ifdef RTE_IXGBE_INC_VECTOR
-uint16_t ixgbe_xmit_fixed_burst_vec(void *tx_queue, struct rte_mbuf **tx_pkts,
-				    uint16_t nb_pkts);
-#endif
-
 /*********************************************************************
  *
  *  TX functions
@@ -993,6 +988,12 @@ ixgbe_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			return i;
 		}
 
+		/* check the size of packet */
+		if (m->pkt_len < IXGBE_TX_MIN_PKT_LEN) {
+			rte_errno = EINVAL;
+			return i;
+		}
+
 #ifdef RTE_LIBRTE_ETHDEV_DEBUG
 		ret = rte_validate_tx_offload(m);
 		if (ret != 0) {
@@ -1439,7 +1440,8 @@ rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags)
 }
 
 static inline uint64_t
-rx_desc_error_to_pkt_flags(uint32_t rx_status)
+rx_desc_error_to_pkt_flags(uint32_t rx_status, uint16_t pkt_info,
+			   uint8_t rx_udp_csum_zero_err)
 {
 	uint64_t pkt_flags;
 
@@ -1456,6 +1458,15 @@ rx_desc_error_to_pkt_flags(uint32_t rx_status)
 	pkt_flags = error_to_pkt_flags_map[(rx_status >>
 		IXGBE_RXDADV_ERR_CKSUM_BIT) & IXGBE_RXDADV_ERR_CKSUM_MSK];
 
+	/* Mask out the bad UDP checksum error if the hardware has UDP zero
+	 * checksum error issue, so that the software application will then
+	 * have to recompute the checksum itself if needed.
+	 */
+	if ((rx_status & IXGBE_RXDADV_ERR_TCPE) &&
+	    (pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) &&
+	    rx_udp_csum_zero_err)
+		pkt_flags &= ~PKT_RX_L4_CKSUM_BAD;
+
 	if ((rx_status & IXGBE_RXD_STAT_OUTERIPCS) &&
 	    (rx_status & IXGBE_RXDADV_ERR_OUTERIPER)) {
 		pkt_flags |= PKT_RX_EIP_CKSUM_BAD;
@@ -1542,7 +1553,9 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq)
 			/* convert descriptor fields to rte mbuf flags */
 			pkt_flags = rx_desc_status_to_pkt_flags(s[j],
 				vlan_flags);
-			pkt_flags |= rx_desc_error_to_pkt_flags(s[j]);
+			pkt_flags |= rx_desc_error_to_pkt_flags(s[j],
+					(uint16_t)pkt_info[j],
+					rxq->rx_udp_csum_zero_err);
 			pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags
 					((uint16_t)pkt_info[j]);
 			mb->ol_flags = pkt_flags;
@@ -1875,7 +1888,9 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan);
 
 		pkt_flags = rx_desc_status_to_pkt_flags(staterr, vlan_flags);
-		pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr);
+		pkt_flags = pkt_flags |
+			rx_desc_error_to_pkt_flags(staterr, (uint16_t)pkt_info,
+						   rxq->rx_udp_csum_zero_err);
 		pkt_flags = pkt_flags |
 			ixgbe_rxd_pkt_info_to_pkt_flags((uint16_t)pkt_info);
 		rxm->ol_flags = pkt_flags;
@@ -1968,7 +1983,8 @@ ixgbe_fill_cluster_head_buf(
 	head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan);
 	pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.data);
 	pkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags);
-	pkt_flags |= rx_desc_error_to_pkt_flags(staterr);
+	pkt_flags |= rx_desc_error_to_pkt_flags(staterr, (uint16_t)pkt_info,
+						rxq->rx_udp_csum_zero_err);
 	pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags((uint16_t)pkt_info);
 	head->ol_flags = pkt_flags;
 	head->packet_type =
@@ -2980,6 +2996,13 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev,
 	else
 		rxq->pkt_type_mask = IXGBE_PACKET_TYPE_MASK_82599;
 
+	/*
+	 * 82599 errata, UDP frames with a 0 checksum can be marked as checksum
+	 * errors.
+	 */
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		rxq->rx_udp_csum_zero_err = 1;
+
 	/*
 	 * Allocate RX ring hardware descriptors. A memzone large enough to
 	 * handle the maximum ring size is allocated in order to allow for
@@ -4785,15 +4808,11 @@ ixgbe_set_rsc(struct rte_eth_dev *dev)
 	/* RFCTL configuration  */
 	rfctl = IXGBE_READ_REG(hw, IXGBE_RFCTL);
 	if ((rsc_capable) && (rx_conf->offloads & DEV_RX_OFFLOAD_TCP_LRO))
-		/*
-		 * Since NFS packets coalescing is not supported - clear
-		 * RFCTL.NFSW_DIS and RFCTL.NFSR_DIS when RSC is
-		 * enabled.
-		 */
-		rfctl &= ~(IXGBE_RFCTL_RSC_DIS | IXGBE_RFCTL_NFSW_DIS |
-			   IXGBE_RFCTL_NFSR_DIS);
+		rfctl &= ~IXGBE_RFCTL_RSC_DIS;
 	else
 		rfctl |= IXGBE_RFCTL_RSC_DIS;
+	/* disable NFS filtering */
+	rfctl |= IXGBE_RFCTL_NFSW_DIS | IXGBE_RFCTL_NFSR_DIS;
 	IXGBE_WRITE_REG(hw, IXGBE_RFCTL, rfctl);
 
 	/* If LRO hasn't been requested - we are done here. */
@@ -5521,8 +5540,12 @@ ixgbevf_dev_rx_init(struct rte_eth_dev *dev)
 	 * ixgbevf_rlpml_set_vf even if jumbo frames are not used. This way,
 	 * VF packets received can work in all cases.
 	 */
-	ixgbevf_rlpml_set_vf(hw,
-		(uint16_t)dev->data->dev_conf.rxmode.max_rx_pkt_len);
+	if (ixgbevf_rlpml_set_vf(hw,
+	    (uint16_t)dev->data->dev_conf.rxmode.max_rx_pkt_len)) {
+		PMD_INIT_LOG(ERR, "Set max packet length to %d failed.",
+			     dev->data->dev_conf.rxmode.max_rx_pkt_len);
+		return -EINVAL;
+	}
 
 	/*
 	 * Assume no header split and no VLAN strip support
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_rxtx.h b/dpdk/drivers/net/ixgbe/ixgbe_rxtx.h
index 505d344b9c..4adfbb3089 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_rxtx.h
+++ b/dpdk/drivers/net/ixgbe/ixgbe_rxtx.h
@@ -53,6 +53,8 @@
 
 #define IXGBE_TX_MAX_SEG                    40
 
+#define IXGBE_TX_MIN_PKT_LEN		     14
+
 #define IXGBE_PACKET_TYPE_MASK_82599        0X7F
 #define IXGBE_PACKET_TYPE_MASK_X550         0X10FF
 #define IXGBE_PACKET_TYPE_MASK_TUNNEL       0XFF
@@ -127,6 +129,8 @@ struct ixgbe_rx_queue {
 	uint8_t             crc_len;  /**< 0 if CRC stripped, 4 otherwise. */
 	uint8_t             drop_en;  /**< If not 0, set SRRCTL.Drop_En. */
 	uint8_t             rx_deferred_start; /**< not in global dev start. */
+	/** UDP frames with a 0 checksum can be marked as checksum errors. */
+	uint8_t             rx_udp_csum_zero_err;
 	/** flags to set in mbuf when a vlan is detected. */
 	uint64_t            vlan_flags;
 	uint64_t	    offloads; /**< Rx offloads with DEV_RX_OFFLOAD_* */
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c b/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
index feb86c61ee..d6d941cbc6 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
@@ -5,13 +5,12 @@
 #include <stdint.h>
 #include <rte_ethdev_driver.h>
 #include <rte_malloc.h>
+#include <rte_vect.h>
 
 #include "ixgbe_ethdev.h"
 #include "ixgbe_rxtx.h"
 #include "ixgbe_rxtx_vec_common.h"
 
-#include <arm_neon.h>
-
 #pragma GCC diagnostic ignored "-Wcast-qual"
 
 static inline void
@@ -82,27 +81,20 @@ ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
 	IXGBE_PCI_REG_WRITE(rxq->rdt_reg_addr, rx_id);
 }
 
-#define VTAG_SHIFT     (3)
-
 static inline void
 desc_to_olflags_v(uint8x16x2_t sterr_tmp1, uint8x16x2_t sterr_tmp2,
-		  uint8x16_t staterr, struct rte_mbuf **rx_pkts)
+		  uint8x16_t staterr, uint8_t vlan_flags, struct rte_mbuf **rx_pkts)
 {
 	uint8x16_t ptype;
-	uint8x16_t vtag;
+	uint8x16_t vtag_lo, vtag_hi, vtag;
+	uint8x16_t temp_csum;
+	uint32x4_t csum = {0, 0, 0, 0};
 
 	union {
-		uint8_t e[4];
-		uint32_t word;
+		uint16_t e[4];
+		uint64_t word;
 	} vol;
 
-	const uint8x16_t pkttype_msk = {
-			PKT_RX_VLAN, PKT_RX_VLAN,
-			PKT_RX_VLAN, PKT_RX_VLAN,
-			0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00};
-
 	const uint8x16_t rsstype_msk = {
 			0x0F, 0x0F, 0x0F, 0x0F,
 			0x00, 0x00, 0x00, 0x00,
@@ -115,15 +107,67 @@ desc_to_olflags_v(uint8x16x2_t sterr_tmp1, uint8x16x2_t sterr_tmp2,
 			PKT_RX_RSS_HASH, 0, 0, 0,
 			0, 0, 0, PKT_RX_FDIR};
 
+	/* mask everything except vlan present and l4/ip csum error */
+	const uint8x16_t vlan_csum_msk = {
+			IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP,
+			IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			(IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 24,
+			(IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 24,
+			(IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 24,
+			(IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 24};
+
+	/* map vlan present (0x8), IPE (0x2), L4E (0x1) to ol_flags */
+	const uint8x16_t vlan_csum_map_lo = {
+			PKT_RX_IP_CKSUM_GOOD,
+			PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_BAD,
+			PKT_RX_IP_CKSUM_BAD,
+			PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD,
+			0, 0, 0, 0,
+			vlan_flags | PKT_RX_IP_CKSUM_GOOD,
+			vlan_flags | PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_BAD,
+			vlan_flags | PKT_RX_IP_CKSUM_BAD,
+			vlan_flags | PKT_RX_IP_CKSUM_BAD | PKT_RX_L4_CKSUM_BAD,
+			0, 0, 0, 0};
+
+	const uint8x16_t vlan_csum_map_hi = {
+			PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0,
+			PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0,
+			0, 0, 0, 0,
+			PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0,
+			PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0,
+			0, 0, 0, 0};
+
 	ptype = vzipq_u8(sterr_tmp1.val[0], sterr_tmp2.val[0]).val[0];
 	ptype = vandq_u8(ptype, rsstype_msk);
 	ptype = vqtbl1q_u8(rss_flags, ptype);
 
-	vtag = vshrq_n_u8(staterr, VTAG_SHIFT);
-	vtag = vandq_u8(vtag, pkttype_msk);
-	vtag = vorrq_u8(ptype, vtag);
+	/* extract vlan_flags and csum_error from staterr */
+	vtag = vandq_u8(staterr, vlan_csum_msk);
+
+	/* csum bits are in the most significant, to use shuffle we need to
+	 * shift them. Change mask from 0xc0 to 0x03.
+	 */
+	temp_csum = vshrq_n_u8(vtag, 6);
+
+	/* 'OR' the most significant 32 bits containing the checksum
+	 * flags with the vlan present flags
+	 * Then bits layout of each lane(8bits) will be 'xxxx,VP,x,IPE,L4E'
+	 */
+	csum = vsetq_lane_u32(vgetq_lane_u32(vreinterpretq_u32_u8(temp_csum), 3), csum, 0);
+	vtag = vorrq_u8(vreinterpretq_u8_u32(csum), vtag);
 
-	vol.word = vgetq_lane_u32(vreinterpretq_u32_u8(vtag), 0);
+	/* convert L4 checksum correct type to vtag_hi */
+	vtag_hi = vqtbl1q_u8(vlan_csum_map_hi, vtag);
+	vtag_hi = vshrq_n_u8(vtag_hi, 7);
+
+	/* convert VP, IPE, L4E to vtag_lo */
+	vtag_lo = vqtbl1q_u8(vlan_csum_map_lo, vtag);
+	vtag_lo = vorrq_u8(ptype, vtag_lo);
+
+	vtag = vzipq_u8(vtag_lo, vtag_hi).val[0];
+	vol.word = vgetq_lane_u64(vreinterpretq_u64_u8(vtag), 0);
 
 	rx_pkts[0]->ol_flags = vol.e[0];
 	rx_pkts[1]->ol_flags = vol.e[1];
@@ -131,17 +175,6 @@ desc_to_olflags_v(uint8x16x2_t sterr_tmp1, uint8x16x2_t sterr_tmp2,
 	rx_pkts[3]->ol_flags = vol.e[3];
 }
 
-/*
- * vPMD raw receive routine, only accept(nb_pkts >= RTE_IXGBE_DESCS_PER_LOOP)
- *
- * Notice:
- * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST
- *   numbers of DD bit
- * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
- * - don't support ol_flags for rss and csum err
- */
-
 #define IXGBE_VPMD_DESC_EOP_MASK	0x02020202
 #define IXGBE_UINT8_BIT			(CHAR_BIT * sizeof(uint8_t))
 
@@ -207,6 +240,13 @@ desc_to_ptype_v(uint64x2_t descs[4], uint16_t pkt_type_mask,
 				vgetq_lane_u32(tunnel_check, 3));
 }
 
+/**
+ * vPMD raw receive routine, only accept(nb_pkts >= RTE_IXGBE_DESCS_PER_LOOP)
+ *
+ * Notice:
+ * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
+ * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
+ */
 static inline uint16_t
 _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		   uint16_t nb_pkts, uint8_t *split_packet)
@@ -226,9 +266,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		};
 	uint16x8_t crc_adjust = {0, 0, rxq->crc_len, 0,
 				 rxq->crc_len, 0, 0, 0};
-
-	/* nb_pkts shall be less equal than RTE_IXGBE_MAX_RX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, RTE_IXGBE_MAX_RX_BURST);
+	uint8_t vlan_flags;
 
 	/* nb_pkts has to be floor-aligned to RTE_IXGBE_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_IXGBE_DESCS_PER_LOOP);
@@ -258,6 +296,10 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	 */
 	sw_ring = &rxq->sw_ring[rxq->rx_tail];
 
+	/* ensure these 2 flags are in the lower 8 bits */
+	RTE_BUILD_BUG_ON((PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED) > UINT8_MAX);
+	vlan_flags = rxq->vlan_flags & UINT8_MAX;
+
 	/* A. load 4 packet in one loop
 	 * B. copy 4 mbuf point from swring to rx_pkts
 	 * C. calc the number of DD bits among the 4 packets
@@ -319,7 +361,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		staterr = vzipq_u8(sterr_tmp1.val[1], sterr_tmp2.val[1]).val[0];
 
 		/* set ol_flags with vlan packet type */
-		desc_to_olflags_v(sterr_tmp1, sterr_tmp2, staterr,
+		desc_to_olflags_v(sterr_tmp1, sterr_tmp2, staterr, vlan_flags,
 				  &rx_pkts[pos]);
 
 		/* D.2 pkt 3,4 set in_port/nb_seg and remove crc */
@@ -383,15 +425,12 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	return nb_pkts_recd;
 }
 
-/*
+/**
  * vPMD receive routine, only accept(nb_pkts >= RTE_IXGBE_DESCS_PER_LOOP)
  *
  * Notice:
  * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST
- *   numbers of DD bit
  * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
- * - don't support ol_flags for rss and csum err
  */
 uint16_t
 ixgbe_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
@@ -400,19 +439,16 @@ ixgbe_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
-/*
+/**
  * vPMD receive routine that reassembles scattered packets
  *
  * Notice:
- * - don't support ol_flags for rss and csum err
  * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST
- *   numbers of DD bit
  * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
  */
-uint16_t
-ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-		uint16_t nb_pkts)
+static uint16_t
+ixgbe_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			       uint16_t nb_pkts)
 {
 	struct ixgbe_rx_queue *rxq = rx_queue;
 	uint8_t split_flags[RTE_IXGBE_MAX_RX_BURST] = {0};
@@ -444,6 +480,32 @@ ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > RTE_IXGBE_MAX_RX_BURST) {
+		uint16_t burst;
+
+		burst = ixgbe_recv_scattered_burst_vec(rx_queue,
+						       rx_pkts + retval,
+						       RTE_IXGBE_MAX_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < RTE_IXGBE_MAX_RX_BURST)
+			return retval;
+	}
+
+	return retval + ixgbe_recv_scattered_burst_vec(rx_queue,
+						       rx_pkts + retval,
+						       nb_pkts);
+}
+
 static inline void
 vtx1(volatile union ixgbe_adv_tx_desc *txdp,
 		struct rte_mbuf *pkt, uint64_t flags)
@@ -576,11 +638,5 @@ ixgbe_txq_vec_setup(struct ixgbe_tx_queue *txq)
 int __attribute__((cold))
 ixgbe_rx_vec_dev_conf_condition_check(struct rte_eth_dev *dev)
 {
-	struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
-
-	/* no csum error report support */
-	if (rxmode->offloads & DEV_RX_OFFLOAD_CHECKSUM)
-		return -1;
-
 	return ixgbe_rx_vec_dev_conf_condition_check_default(dev);
 }
diff --git a/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c b/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c
index 599ba30e51..4b658605bf 100644
--- a/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c
+++ b/dpdk/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c
@@ -132,9 +132,9 @@ desc_to_olflags_v_ipsec(__m128i descs[4], struct rte_mbuf **rx_pkts)
 
 static inline void
 desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
-	struct rte_mbuf **rx_pkts)
+		  uint16_t udp_p_flag, struct rte_mbuf **rx_pkts)
 {
-	__m128i ptype0, ptype1, vtag0, vtag1, csum;
+	__m128i ptype0, ptype1, vtag0, vtag1, csum, udp_csum_skip;
 	__m128i rearm0, rearm1, rearm2, rearm3;
 
 	/* mask everything except rss type */
@@ -161,6 +161,7 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
 		(IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16,
 		IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP,
 		IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP);
+
 	/* map vlan present (0x8), IPE (0x2), L4E (0x1) to ol_flags */
 	const __m128i vlan_csum_map_lo = _mm_set_epi8(
 		0, 0, 0, 0,
@@ -182,12 +183,23 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
 		0, PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0,
 		PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t));
 
+	/* mask everything except UDP header present if specified */
+	const __m128i udp_hdr_p_msk = _mm_set_epi16
+		(0, 0, 0, 0,
+		 udp_p_flag, udp_p_flag, udp_p_flag, udp_p_flag);
+
+	const __m128i udp_csum_bad_shuf = _mm_set_epi8
+		(0, 0, 0, 0, 0, 0, 0, 0,
+		 0, 0, 0, 0, 0, 0, ~(uint8_t)PKT_RX_L4_CKSUM_BAD, 0xFF);
+
 	ptype0 = _mm_unpacklo_epi16(descs[0], descs[1]);
 	ptype1 = _mm_unpacklo_epi16(descs[2], descs[3]);
 	vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]);
 	vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]);
 
 	ptype0 = _mm_unpacklo_epi32(ptype0, ptype1);
+	/* save the UDP header present information */
+	udp_csum_skip = _mm_and_si128(ptype0, udp_hdr_p_msk);
 	ptype0 = _mm_and_si128(ptype0, rsstype_msk);
 	ptype0 = _mm_shuffle_epi8(rss_flags, ptype0);
 
@@ -215,6 +227,15 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags,
 
 	vtag1 = _mm_or_si128(ptype0, vtag1);
 
+	/* convert the UDP header present 0x200 to 0x1 for aligning with each
+	 * PKT_RX_L4_CKSUM_BAD value in low byte of 16 bits word ol_flag in
+	 * vtag1 (4x16). Then mask out the bad checksum value by shuffle and
+	 * bit-mask.
+	 */
+	udp_csum_skip = _mm_srli_epi16(udp_csum_skip, 9);
+	udp_csum_skip = _mm_shuffle_epi8(udp_csum_bad_shuf, udp_csum_skip);
+	vtag1 = _mm_and_si128(vtag1, udp_csum_skip);
+
 	/*
 	 * At this point, we have the 4 sets of flags in the low 64-bits
 	 * of vtag1 (4x16).
@@ -302,13 +323,11 @@ desc_to_ptype_v(__m128i descs[4], uint16_t pkt_type_mask,
 		get_packet_type(3, pkt_info, etqf_check, tunnel_check);
 }
 
-/*
+/**
  * vPMD raw receive routine, only accept(nb_pkts >= RTE_IXGBE_DESCS_PER_LOOP)
  *
  * Notice:
  * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST
- *   numbers of DD bit
  * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
  */
 static inline uint16_t
@@ -343,9 +362,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	__m128i dd_check, eop_check;
 	__m128i mbuf_init;
 	uint8_t vlan_flags;
-
-	/* nb_pkts shall be less equal than RTE_IXGBE_MAX_RX_BURST */
-	nb_pkts = RTE_MIN(nb_pkts, RTE_IXGBE_MAX_RX_BURST);
+	uint16_t udp_p_flag = 0; /* Rx Descriptor UDP header present */
 
 	/* nb_pkts has to be floor-aligned to RTE_IXGBE_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_IXGBE_DESCS_PER_LOOP);
@@ -370,6 +387,9 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 				rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD)))
 		return 0;
 
+	if (rxq->rx_udp_csum_zero_err)
+		udp_p_flag = IXGBE_RXDADV_PKTTYPE_UDP;
+
 	/* 4 packets DD mask */
 	dd_check = _mm_set_epi64x(0x0000000100000001LL, 0x0000000100000001LL);
 
@@ -482,7 +502,8 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 		sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]);
 
 		/* set ol_flags with vlan packet type */
-		desc_to_olflags_v(descs, mbuf_init, vlan_flags, &rx_pkts[pos]);
+		desc_to_olflags_v(descs, mbuf_init, vlan_flags, udp_p_flag,
+				  &rx_pkts[pos]);
 
 #ifdef RTE_LIBRTE_SECURITY
 		if (unlikely(use_ipsec))
@@ -556,13 +577,11 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	return nb_pkts_recd;
 }
 
-/*
+/**
  * vPMD receive routine, only accept(nb_pkts >= RTE_IXGBE_DESCS_PER_LOOP)
  *
  * Notice:
  * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST
- *   numbers of DD bit
  * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
  */
 uint16_t
@@ -572,18 +591,16 @@ ixgbe_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 	return _recv_raw_pkts_vec(rx_queue, rx_pkts, nb_pkts, NULL);
 }
 
-/*
+/**
  * vPMD receive routine that reassembles scattered packets
  *
  * Notice:
  * - nb_pkts < RTE_IXGBE_DESCS_PER_LOOP, just return no packet
- * - nb_pkts > RTE_IXGBE_MAX_RX_BURST, only scan RTE_IXGBE_MAX_RX_BURST
- *   numbers of DD bit
  * - floor align nb_pkts to a RTE_IXGBE_DESC_PER_LOOP power-of-two
  */
-uint16_t
-ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
-		uint16_t nb_pkts)
+static uint16_t
+ixgbe_recv_scattered_burst_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			       uint16_t nb_pkts)
 {
 	struct ixgbe_rx_queue *rxq = rx_queue;
 	uint8_t split_flags[RTE_IXGBE_MAX_RX_BURST] = {0};
@@ -615,6 +632,32 @@ ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
 		&split_flags[i]);
 }
 
+/**
+ * vPMD receive routine that reassembles scattered packets.
+ */
+uint16_t
+ixgbe_recv_scattered_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
+			      uint16_t nb_pkts)
+{
+	uint16_t retval = 0;
+
+	while (nb_pkts > RTE_IXGBE_MAX_RX_BURST) {
+		uint16_t burst;
+
+		burst = ixgbe_recv_scattered_burst_vec(rx_queue,
+						       rx_pkts + retval,
+						       RTE_IXGBE_MAX_RX_BURST);
+		retval += burst;
+		nb_pkts -= burst;
+		if (burst < RTE_IXGBE_MAX_RX_BURST)
+			return retval;
+	}
+
+	return retval + ixgbe_recv_scattered_burst_vec(rx_queue,
+						       rx_pkts + retval,
+						       nb_pkts);
+}
+
 static inline void
 vtx1(volatile union ixgbe_adv_tx_desc *txdp,
 		struct rte_mbuf *pkt, uint64_t flags)
diff --git a/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.c b/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.c
index 8bcaded6e5..9bff557f97 100644
--- a/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.c
+++ b/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.c
@@ -522,6 +522,9 @@ rte_pmd_ixgbe_macsec_enable(uint16_t port, uint8_t en, uint8_t rp)
 
 	dev = &rte_eth_devices[port];
 
+	if (!is_ixgbe_supported(dev))
+		return -ENOTSUP;
+
 	macsec_setting.offload_en = 1;
 	macsec_setting.encrypt_en = en;
 	macsec_setting.replayprotect_en = rp;
@@ -542,6 +545,9 @@ rte_pmd_ixgbe_macsec_disable(uint16_t port)
 
 	dev = &rte_eth_devices[port];
 
+	if (!is_ixgbe_supported(dev))
+		return -ENOTSUP;
+
 	ixgbe_dev_macsec_setting_reset(dev);
 
 	ixgbe_dev_macsec_register_disable(dev);
diff --git a/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.h b/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.h
index f62fd761dd..d1017c7b1a 100644
--- a/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.h
+++ b/dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.h
@@ -11,7 +11,9 @@
 #ifndef _PMD_IXGBE_H_
 #define _PMD_IXGBE_H_
 
-#include <rte_ethdev_driver.h>
+#include <rte_compat.h>
+#include <rte_ethdev.h>
+#include <rte_ether.h>
 
 /**
  * Notify VF when PF link status changes.
diff --git a/dpdk/drivers/net/kni/rte_eth_kni.c b/dpdk/drivers/net/kni/rte_eth_kni.c
index d88cb1778e..c3345f5cb7 100644
--- a/dpdk/drivers/net/kni/rte_eth_kni.c
+++ b/dpdk/drivers/net/kni/rte_eth_kni.c
@@ -47,6 +47,7 @@ struct pmd_queue {
 
 struct pmd_internals {
 	struct rte_kni *kni;
+	uint16_t port_id;
 	int is_kni_started;
 
 	pthread_t thread;
@@ -78,8 +79,11 @@ eth_kni_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 	struct pmd_queue *kni_q = q;
 	struct rte_kni *kni = kni_q->internals->kni;
 	uint16_t nb_pkts;
+	int i;
 
 	nb_pkts = rte_kni_rx_burst(kni, bufs, nb_bufs);
+	for (i = 0; i < nb_pkts; i++)
+		bufs[i]->port = kni_q->internals->port_id;
 
 	kni_q->rx.pkts += nb_pkts;
 
@@ -372,6 +376,7 @@ eth_kni_create(struct rte_vdev_device *vdev,
 		return NULL;
 
 	internals = eth_dev->data->dev_private;
+	internals->port_id = eth_dev->data->port_id;
 	data = eth_dev->data;
 	data->nb_rx_queues = 1;
 	data->nb_tx_queues = 1;
diff --git a/dpdk/drivers/net/liquidio/lio_ethdev.c b/dpdk/drivers/net/liquidio/lio_ethdev.c
index ad4a51ecda..ac0472967c 100644
--- a/dpdk/drivers/net/liquidio/lio_ethdev.c
+++ b/dpdk/drivers/net/liquidio/lio_ethdev.c
@@ -484,7 +484,7 @@ lio_dev_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
 		return -1;
 	}
 
-	if (frame_len > RTE_ETHER_MAX_LEN)
+	if (frame_len > LIO_ETH_MAX_LEN)
 		eth_dev->data->dev_conf.rxmode.offloads |=
 			DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
diff --git a/dpdk/drivers/net/liquidio/lio_ethdev.h b/dpdk/drivers/net/liquidio/lio_ethdev.h
index 74cd2fb6c6..d33be1c44d 100644
--- a/dpdk/drivers/net/liquidio/lio_ethdev.h
+++ b/dpdk/drivers/net/liquidio/lio_ethdev.h
@@ -13,6 +13,9 @@
 #define LIO_LSC_TIMEOUT		100000 /* 100000us (100ms) */
 #define LIO_MAX_CMD_TIMEOUT     10000 /* 10000ms (10s) */
 
+/* The max frame size with default MTU */
+#define LIO_ETH_MAX_LEN (RTE_ETHER_MTU + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)
+
 #define LIO_DEV(_eth_dev)		((_eth_dev)->data->dev_private)
 
 /* LIO Response condition variable */
diff --git a/dpdk/drivers/net/memif/memif_socket.c b/dpdk/drivers/net/memif/memif_socket.c
index ad5e30b96e..c1967c67bf 100644
--- a/dpdk/drivers/net/memif/memif_socket.c
+++ b/dpdk/drivers/net/memif/memif_socket.c
@@ -204,6 +204,13 @@ memif_msg_receive_init(struct memif_control_channel *cc, memif_msg_t *msg)
 		pmd = dev->data->dev_private;
 		if (((pmd->flags & ETH_MEMIF_FLAG_DISABLED) == 0) &&
 		    pmd->id == i->id) {
+			if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING |
+					   ETH_MEMIF_FLAG_CONNECTED)) {
+				memif_msg_enq_disconnect(cc,
+							 "Already connected", 0);
+				return -1;
+			}
+
 			/* assign control channel to device */
 			cc->dev = dev;
 			pmd->cc = cc;
@@ -215,12 +222,6 @@ memif_msg_receive_init(struct memif_control_channel *cc, memif_msg_t *msg)
 				return -1;
 			}
 
-			if (pmd->flags & (ETH_MEMIF_FLAG_CONNECTING |
-					   ETH_MEMIF_FLAG_CONNECTED)) {
-				memif_msg_enq_disconnect(pmd->cc,
-							 "Already connected", 0);
-				return -1;
-			}
 			strlcpy(pmd->remote_name, (char *)i->name,
 				sizeof(pmd->remote_name));
 
@@ -765,6 +766,7 @@ memif_intr_handler(void *arg)
 	ret = memif_msg_receive(cc);
 	/* if driver failed to assign device */
 	if (cc->dev == NULL) {
+		memif_msg_send_from_queue(cc);
 		ret = rte_intr_callback_unregister_pending(&cc->intr_handle,
 							   memif_intr_handler,
 							   cc,
diff --git a/dpdk/drivers/net/memif/rte_eth_memif.c b/dpdk/drivers/net/memif/rte_eth_memif.c
index 8dd1d0d63d..aa75a04278 100644
--- a/dpdk/drivers/net/memif/rte_eth_memif.c
+++ b/dpdk/drivers/net/memif/rte_eth_memif.c
@@ -398,7 +398,11 @@ eth_memif_rx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 
 refill:
 	if (type == MEMIF_RING_M2S) {
-		head = __atomic_load_n(&ring->head, __ATOMIC_ACQUIRE);
+		/* ring->head is updated by the receiver and this function
+		 * is called in the context of receiver thread. The loads in
+		 * the receiver do not need to synchronize with its own stores.
+		 */
+		head = __atomic_load_n(&ring->head, __ATOMIC_RELAXED);
 		n_slots = ring_size - head + mq->last_tail;
 
 		while (n_slots--) {
@@ -561,14 +565,24 @@ eth_memif_tx(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 	ring_size = 1 << mq->log2_ring_size;
 	mask = ring_size - 1;
 
-	n_free = __atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE) - mq->last_tail;
-	mq->last_tail += n_free;
-
 	if (type == MEMIF_RING_S2M) {
-		slot = __atomic_load_n(&ring->head, __ATOMIC_ACQUIRE);
-		n_free = ring_size - slot + mq->last_tail;
+		/* For S2M queues ring->head is updated by the sender and
+		 * this function is called in the context of sending thread.
+		 * The loads in the sender do not need to synchronize with
+		 * its own stores. Hence, the following load can be a
+		 * relaxed load.
+		 */
+		slot = __atomic_load_n(&ring->head, __ATOMIC_RELAXED);
+		n_free = ring_size - slot +
+				__atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE);
 	} else {
-		slot = __atomic_load_n(&ring->tail, __ATOMIC_ACQUIRE);
+		/* For M2S queues ring->tail is updated by the sender and
+		 * this function is called in the context of sending thread.
+		 * The loads in the sender do not need to synchronize with
+		 * its own stores. Hence, the following load can be a
+		 * relaxed load.
+		 */
+		slot = __atomic_load_n(&ring->tail, __ATOMIC_RELAXED);
 		n_free = __atomic_load_n(&ring->head, __ATOMIC_ACQUIRE) - slot;
 	}
 
@@ -1501,7 +1515,7 @@ memif_create(struct rte_vdev_device *vdev, enum memif_role_t role,
 	}
 
 
-	eth_dev->data->dev_flags &= RTE_ETH_DEV_CLOSE_REMOVE;
+	eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
 
 	rte_eth_dev_probing_finish(eth_dev);
 
diff --git a/dpdk/drivers/net/mlx4/meson.build b/dpdk/drivers/net/mlx4/meson.build
index 9eb4988420..a03ab930cc 100644
--- a/dpdk/drivers/net/mlx4/meson.build
+++ b/dpdk/drivers/net/mlx4/meson.build
@@ -9,11 +9,12 @@ if not is_linux
 endif
 build = true
 
-pmd_dlopen = (get_option('ibverbs_link') == 'dlopen')
+static_ibverbs = (get_option('ibverbs_link') == 'static')
+dlopen_ibverbs = (get_option('ibverbs_link') == 'dlopen')
 LIB_GLUE_BASE = 'librte_pmd_mlx4_glue.so'
 LIB_GLUE_VERSION = '18.02.0'
 LIB_GLUE = LIB_GLUE_BASE + '.' + LIB_GLUE_VERSION
-if pmd_dlopen
+if dlopen_ibverbs
 	dpdk_conf.set('RTE_IBVERBS_LINK_DLOPEN', 1)
 	cflags += [
 		'-DMLX4_GLUE="@0@"'.format(LIB_GLUE),
@@ -24,12 +25,16 @@ endif
 libnames = [ 'mlx4', 'ibverbs' ]
 libs = []
 foreach libname:libnames
-	lib = dependency('lib' + libname, required:false)
-	if not lib.found()
+	lib = dependency('lib' + libname, static:static_ibverbs,
+			required:false, method: 'pkg-config')
+	if not lib.found() and not static_ibverbs
 		lib = cc.find_library(libname, required:false)
 	endif
 	if lib.found()
-		libs += [ lib ]
+		libs += lib
+		if not static_ibverbs and not dlopen_ibverbs
+			ext_deps += lib
+		endif
 	else
 		build = false
 		reason = 'missing dependency, "' + libname + '"'
@@ -37,8 +42,17 @@ foreach libname:libnames
 endforeach
 
 if build
+	if static_ibverbs or dlopen_ibverbs
+		# Build without adding shared libs to Requires.private
+		ibv_cflags = run_command(pkgconf, '--cflags', 'libibverbs').stdout()
+		ext_deps += declare_dependency(compile_args: ibv_cflags.split())
+	endif
+	if static_ibverbs
+		# Add static deps ldflags to internal apps and Libs.private
+		ibv_ldflags = run_command(ldflags_ibverbs_static, check:true).stdout()
+		ext_deps += declare_dependency(link_args:ibv_ldflags.split())
+	endif
 	allow_experimental_apis = true
-	ext_deps += libs
 	sources = files(
 		'mlx4.c',
 		'mlx4_ethdev.c',
@@ -51,7 +65,7 @@ if build
 		'mlx4_txq.c',
 		'mlx4_utils.c',
 	)
-	if not pmd_dlopen
+	if not dlopen_ibverbs
 		sources += files('mlx4_glue.c')
 	endif
 	cflags_options = [
@@ -103,7 +117,7 @@ if build
 	configure_file(output : 'mlx4_autoconf.h', configuration : config)
 endif
 # Build Glue Library
-if pmd_dlopen and build
+if dlopen_ibverbs and build
 	dlopen_name = 'mlx4_glue'
 	dlopen_lib_name = driver_name_fmt.format(dlopen_name)
 	dlopen_so_version = LIB_GLUE_VERSION
diff --git a/dpdk/drivers/net/mlx4/mlx4.c b/dpdk/drivers/net/mlx4/mlx4.c
index ab5e6c66cb..4479022a42 100644
--- a/dpdk/drivers/net/mlx4/mlx4.c
+++ b/dpdk/drivers/net/mlx4/mlx4.c
@@ -49,6 +49,10 @@
 #include "mlx4_rxtx.h"
 #include "mlx4_utils.h"
 
+#ifdef MLX4_GLUE
+const struct mlx4_glue *mlx4_glue;
+#endif
+
 static const char *MZ_MLX4_PMD_SHARED_DATA = "mlx4_pmd_shared_data";
 
 /* Shared memory between primary and secondary processes. */
@@ -194,7 +198,7 @@ mlx4_free_verbs_buf(void *ptr, void *data __rte_unused)
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-static int
+int
 mlx4_proc_priv_init(struct rte_eth_dev *dev)
 {
 	struct mlx4_proc_priv *ppriv;
@@ -206,13 +210,13 @@ mlx4_proc_priv_init(struct rte_eth_dev *dev)
 	 */
 	ppriv_size = sizeof(struct mlx4_proc_priv) +
 		     dev->data->nb_tx_queues * sizeof(void *);
-	ppriv = rte_malloc_socket("mlx4_proc_priv", ppriv_size,
-				  RTE_CACHE_LINE_SIZE, dev->device->numa_node);
+	ppriv = rte_zmalloc_socket("mlx4_proc_priv", ppriv_size,
+				   RTE_CACHE_LINE_SIZE, dev->device->numa_node);
 	if (!ppriv) {
 		rte_errno = ENOMEM;
 		return -rte_errno;
 	}
-	ppriv->uar_table_sz = ppriv_size;
+	ppriv->uar_table_sz = dev->data->nb_tx_queues;
 	dev->process_private = ppriv;
 	return 0;
 }
@@ -223,7 +227,7 @@ mlx4_proc_priv_init(struct rte_eth_dev *dev)
  * @param dev
  *   Pointer to Ethernet device structure.
  */
-static void
+void
 mlx4_proc_priv_uninit(struct rte_eth_dev *dev)
 {
 	if (!dev->process_private)
@@ -248,9 +252,6 @@ mlx4_dev_configure(struct rte_eth_dev *dev)
 	struct rte_flow_error error;
 	int ret;
 
-	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
-		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
-
 	/* Prepare internal flow rules. */
 	ret = mlx4_flow_sync(priv, &error);
 	if (ret) {
@@ -461,6 +462,7 @@ mlx4_ibv_device_to_pci_addr(const struct ibv_device *device,
 {
 	FILE *file;
 	char line[32];
+	int rc = -ENOENT;
 	MKSTR(path, "%s/device/uevent", device->ibdev_path);
 
 	file = fopen(path, "rb");
@@ -470,16 +472,18 @@ mlx4_ibv_device_to_pci_addr(const struct ibv_device *device,
 	}
 	while (fgets(line, sizeof(line), file) == line) {
 		size_t len = strlen(line);
-		int ret;
 
 		/* Truncate long lines. */
-		if (len == (sizeof(line) - 1))
+		if (len == (sizeof(line) - 1)) {
 			while (line[(len - 1)] != '\n') {
-				ret = fgetc(file);
+				int ret = fgetc(file);
 				if (ret == EOF)
-					break;
+					goto exit;
 				line[(len - 1)] = ret;
 			}
+			/* No match for long lines. */
+			continue;
+		}
 		/* Extract information. */
 		if (sscanf(line,
 			   "PCI_SLOT_NAME="
@@ -488,12 +492,15 @@ mlx4_ibv_device_to_pci_addr(const struct ibv_device *device,
 			   &pci_addr->bus,
 			   &pci_addr->devid,
 			   &pci_addr->function) == 4) {
-			ret = 0;
+			rc = 0;
 			break;
 		}
 	}
+exit:
 	fclose(file);
-	return 0;
+	if (rc)
+		rte_errno = -rc;
+	return rc;
 }
 
 /**
@@ -760,6 +767,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 	struct ibv_context *attr_ctx = NULL;
 	struct ibv_device_attr device_attr;
 	struct ibv_device_attr_ex device_attr_ex;
+	struct rte_eth_dev *prev_dev = NULL;
 	struct mlx4_conf conf = {
 		.ports.present = 0,
 		.mr_ext_memseg_en = 1,
@@ -874,7 +882,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 				ERROR("can not attach rte ethdev");
 				rte_errno = ENOMEM;
 				err = rte_errno;
-				goto error;
+				goto err_secondary;
 			}
 			priv = eth_dev->data->dev_private;
 			if (!priv->verbs_alloc_ctx.enabled) {
@@ -883,24 +891,24 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 				      " from Verbs");
 				rte_errno = ENOTSUP;
 				err = rte_errno;
-				goto error;
+				goto err_secondary;
 			}
 			eth_dev->device = &pci_dev->device;
 			eth_dev->dev_ops = &mlx4_dev_sec_ops;
 			err = mlx4_proc_priv_init(eth_dev);
 			if (err)
-				goto error;
+				goto err_secondary;
 			/* Receive command fd from primary process. */
 			err = mlx4_mp_req_verbs_cmd_fd(eth_dev);
 			if (err < 0) {
 				err = rte_errno;
-				goto error;
+				goto err_secondary;
 			}
 			/* Remap UAR for Tx queues. */
 			err = mlx4_tx_uar_init_secondary(eth_dev, err);
 			if (err) {
 				err = rte_errno;
-				goto error;
+				goto err_secondary;
 			}
 			/*
 			 * Ethdev pointer is still required as input since
@@ -912,7 +920,14 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			claim_zero(mlx4_glue->close_device(ctx));
 			rte_eth_copy_pci_info(eth_dev, pci_dev);
 			rte_eth_dev_probing_finish(eth_dev);
+			prev_dev = eth_dev;
 			continue;
+err_secondary:
+			claim_zero(mlx4_glue->close_device(ctx));
+			rte_eth_dev_release_port(eth_dev);
+			if (prev_dev)
+				rte_eth_dev_release_port(prev_dev);
+			break;
 		}
 		/* Check port status. */
 		err = mlx4_glue->query_port(ctx, port, &port_attr);
@@ -1029,10 +1044,9 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		eth_dev->device = &pci_dev->device;
 		rte_eth_copy_pci_info(eth_dev, pci_dev);
 		/* Initialize local interrupt handle for current port. */
-		priv->intr_handle = (struct rte_intr_handle){
-			.fd = -1,
-			.type = RTE_INTR_HANDLE_EXT,
-		};
+		memset(&priv->intr_handle, 0, sizeof(struct rte_intr_handle));
+		priv->intr_handle.fd = -1;
+		priv->intr_handle.type = RTE_INTR_HANDLE_EXT;
 		/*
 		 * Override ethdev interrupt handle pointer with private
 		 * handle instead of that of the parent PCI device used by
@@ -1088,6 +1102,7 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 				 priv, mem_event_cb);
 		rte_rwlock_write_unlock(&mlx4_shared_data->mem_event_rwlock);
 		rte_eth_dev_probing_finish(eth_dev);
+		prev_dev = eth_dev;
 		continue;
 port_error:
 		rte_free(priv);
@@ -1102,14 +1117,10 @@ mlx4_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			eth_dev->data->mac_addrs = NULL;
 			rte_eth_dev_release_port(eth_dev);
 		}
+		if (prev_dev)
+			mlx4_dev_close(prev_dev);
 		break;
 	}
-	/*
-	 * XXX if something went wrong in the loop above, there is a resource
-	 * leak (ctx, pd, priv, dpdk ethdev) but we can do nothing about it as
-	 * long as the dpdk does not provide a way to deallocate a ethdev and a
-	 * way to enumerate the registered ethdevs to free the previous ones.
-	 */
 error:
 	if (attr_ctx)
 		claim_zero(mlx4_glue->close_device(attr_ctx));
diff --git a/dpdk/drivers/net/mlx4/mlx4.h b/dpdk/drivers/net/mlx4/mlx4.h
index c6cb29493e..87710d3996 100644
--- a/dpdk/drivers/net/mlx4/mlx4.h
+++ b/dpdk/drivers/net/mlx4/mlx4.h
@@ -197,6 +197,10 @@ struct mlx4_priv {
 #define PORT_ID(priv) ((priv)->dev_data->port_id)
 #define ETH_DEV(priv) (&rte_eth_devices[PORT_ID(priv)])
 
+int mlx4_proc_priv_init(struct rte_eth_dev *dev);
+void mlx4_proc_priv_uninit(struct rte_eth_dev *dev);
+
+
 /* mlx4_ethdev.c */
 
 int mlx4_get_ifname(const struct mlx4_priv *priv, char (*ifname)[IF_NAMESIZE]);
diff --git a/dpdk/drivers/net/mlx4/mlx4_flow.c b/dpdk/drivers/net/mlx4/mlx4_flow.c
index 96479b83dd..2da4f6d965 100644
--- a/dpdk/drivers/net/mlx4/mlx4_flow.c
+++ b/dpdk/drivers/net/mlx4/mlx4_flow.c
@@ -981,12 +981,13 @@ mlx4_drop_get(struct mlx4_priv *priv)
 	priv->drop = drop;
 	return drop;
 error:
-	if (drop->qp)
-		claim_zero(mlx4_glue->destroy_qp(drop->qp));
-	if (drop->cq)
-		claim_zero(mlx4_glue->destroy_cq(drop->cq));
-	if (drop)
+	if (drop) {
+		if (drop->qp)
+			claim_zero(mlx4_glue->destroy_qp(drop->qp));
+		if (drop->cq)
+			claim_zero(mlx4_glue->destroy_cq(drop->cq));
 		rte_free(drop);
+	}
 	rte_errno = ENOMEM;
 	return NULL;
 }
diff --git a/dpdk/drivers/net/mlx4/mlx4_glue.h b/dpdk/drivers/net/mlx4/mlx4_glue.h
index 668ca86700..5d9e985495 100644
--- a/dpdk/drivers/net/mlx4/mlx4_glue.h
+++ b/dpdk/drivers/net/mlx4/mlx4_glue.h
@@ -84,6 +84,6 @@ struct mlx4_glue {
 				   void *attr);
 };
 
-const struct mlx4_glue *mlx4_glue;
+extern const struct mlx4_glue *mlx4_glue;
 
 #endif /* MLX4_GLUE_H_ */
diff --git a/dpdk/drivers/net/mlx4/mlx4_mp.c b/dpdk/drivers/net/mlx4/mlx4_mp.c
index cdb648517a..4da743d9e3 100644
--- a/dpdk/drivers/net/mlx4/mlx4_mp.c
+++ b/dpdk/drivers/net/mlx4/mlx4_mp.c
@@ -112,6 +112,9 @@ mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
 	const struct mlx4_mp_param *param =
 		(const struct mlx4_mp_param *)mp_msg->param;
 	struct rte_eth_dev *dev;
+#ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET
+	struct mlx4_proc_priv *ppriv;
+#endif
 	int ret;
 
 	assert(rte_eal_process_type() == RTE_PROC_SECONDARY);
@@ -127,6 +130,21 @@ mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
 		rte_mb();
 		dev->tx_pkt_burst = mlx4_tx_burst;
 		dev->rx_pkt_burst = mlx4_rx_burst;
+#ifdef HAVE_IBV_MLX4_UAR_MMAP_OFFSET
+		ppriv = (struct mlx4_proc_priv *)dev->process_private;
+		if (ppriv->uar_table_sz != dev->data->nb_tx_queues) {
+			mlx4_tx_uar_uninit_secondary(dev);
+			mlx4_proc_priv_uninit(dev);
+			ret = mlx4_proc_priv_init(dev);
+			if (ret)
+				return -rte_errno;
+			ret = mlx4_tx_uar_init_secondary(dev, mp_msg->fds[0]);
+			if (ret) {
+				mlx4_proc_priv_uninit(dev);
+				return -rte_errno;
+			}
+		}
+#endif
 		mp_init_msg(dev, &mp_res, param->type);
 		res->result = 0;
 		ret = rte_mp_reply(&mp_res, peer);
@@ -164,6 +182,7 @@ mp_req_on_rxtx(struct rte_eth_dev *dev, enum mlx4_mp_req_type type)
 	struct rte_mp_reply mp_rep;
 	struct mlx4_mp_param *res __rte_unused;
 	struct timespec ts = {.tv_sec = MLX4_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
+	struct mlx4_priv *priv;
 	int ret;
 	int i;
 
@@ -176,6 +195,11 @@ mp_req_on_rxtx(struct rte_eth_dev *dev, enum mlx4_mp_req_type type)
 		return;
 	}
 	mp_init_msg(dev, &mp_req, type);
+	if (type == MLX4_MP_REQ_START_RXTX) {
+		priv = dev->data->dev_private;
+		mp_req.num_fds = 1;
+		mp_req.fds[0] = priv->ctx->cmd_fd;
+	}
 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
 	if (ret) {
 		if (rte_errno != ENOTSUP)
diff --git a/dpdk/drivers/net/mlx4/mlx4_rxtx.h b/dpdk/drivers/net/mlx4/mlx4_rxtx.h
index 8baf33fa94..136ca56ca4 100644
--- a/dpdk/drivers/net/mlx4/mlx4_rxtx.h
+++ b/dpdk/drivers/net/mlx4/mlx4_rxtx.h
@@ -124,7 +124,7 @@ struct txq {
 
 /* mlx4_rxq.c */
 
-uint8_t mlx4_rss_hash_key_default[MLX4_RSS_HASH_KEY_SIZE];
+extern uint8_t mlx4_rss_hash_key_default[MLX4_RSS_HASH_KEY_SIZE];
 int mlx4_rss_init(struct mlx4_priv *priv);
 void mlx4_rss_deinit(struct mlx4_priv *priv);
 struct mlx4_rss *mlx4_rss_get(struct mlx4_priv *priv, uint64_t fields,
@@ -157,6 +157,7 @@ uint16_t mlx4_rx_burst_removed(void *dpdk_rxq, struct rte_mbuf **pkts,
 /* mlx4_txq.c */
 
 int mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd);
+void mlx4_tx_uar_uninit_secondary(struct rte_eth_dev *dev);
 uint64_t mlx4_get_tx_port_offloads(struct mlx4_priv *priv);
 int mlx4_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
 			uint16_t desc, unsigned int socket,
diff --git a/dpdk/drivers/net/mlx4/mlx4_txq.c b/dpdk/drivers/net/mlx4/mlx4_txq.c
index 01a5efd80d..824ddbd827 100644
--- a/dpdk/drivers/net/mlx4/mlx4_txq.c
+++ b/dpdk/drivers/net/mlx4/mlx4_txq.c
@@ -158,6 +158,27 @@ mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd)
 	} while (i--);
 	return -rte_errno;
 }
+
+void
+mlx4_tx_uar_uninit_secondary(struct rte_eth_dev *dev)
+{
+	struct mlx4_proc_priv *ppriv =
+			(struct mlx4_proc_priv *)dev->process_private;
+	const size_t page_size = sysconf(_SC_PAGESIZE);
+	void *addr;
+	size_t i;
+
+	if (page_size == (size_t)-1) {
+		ERROR("Failed to get mem page size");
+		return;
+	}
+	for (i = 0; i < ppriv->uar_table_sz; i++) {
+		addr = ppriv->uar_table[i];
+		if (addr)
+			munmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
+	}
+}
+
 #else
 int
 mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev __rte_unused,
@@ -168,6 +189,13 @@ mlx4_tx_uar_init_secondary(struct rte_eth_dev *dev __rte_unused,
 	rte_errno = ENOTSUP;
 	return -rte_errno;
 }
+
+void
+mlx4_tx_uar_uninit_secondary(struct rte_eth_dev *dev __rte_unused)
+{
+	assert(rte_eal_process_type() == RTE_PROC_SECONDARY);
+	ERROR("UAR remap is not supported");
+}
 #endif
 
 /**
diff --git a/dpdk/drivers/net/mlx4/mlx4_utils.h b/dpdk/drivers/net/mlx4/mlx4_utils.h
index 74b9d2ecdc..5718b9c742 100644
--- a/dpdk/drivers/net/mlx4/mlx4_utils.h
+++ b/dpdk/drivers/net/mlx4/mlx4_utils.h
@@ -79,9 +79,10 @@ pmd_drv_log_basename(const char *s)
 
 /** Allocate a buffer on the stack and fill it with a printf format string. */
 #define MKSTR(name, ...) \
-	char name[snprintf(NULL, 0, __VA_ARGS__) + 1]; \
+	int mkstr_size_##name = snprintf(NULL, 0, "" __VA_ARGS__); \
+	char name[mkstr_size_##name + 1]; \
 	\
-	snprintf(name, sizeof(name), __VA_ARGS__)
+	snprintf(name, sizeof(name), "" __VA_ARGS__)
 
 /** Generate a string out of the provided arguments. */
 #define MLX4_STR(...) # __VA_ARGS__
diff --git a/dpdk/drivers/net/mlx5/Makefile b/dpdk/drivers/net/mlx5/Makefile
index c5cf4397ac..605975c245 100644
--- a/dpdk/drivers/net/mlx5/Makefile
+++ b/dpdk/drivers/net/mlx5/Makefile
@@ -193,6 +193,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		infiniband/mlx5dv.h \
 		func mlx5dv_devx_obj_query_async \
 		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
+		HAVE_IBV_DEVX_QP \
+		infiniband/mlx5dv.h \
+		func mlx5dv_devx_qp_query \
+		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
 		HAVE_MLX5DV_DR_ACTION_DEST_DEVX_TIR \
 		infiniband/mlx5dv.h \
diff --git a/dpdk/drivers/net/mlx5/meson.build b/dpdk/drivers/net/mlx5/meson.build
index d6b32db794..139056cbe8 100644
--- a/dpdk/drivers/net/mlx5/meson.build
+++ b/dpdk/drivers/net/mlx5/meson.build
@@ -9,11 +9,12 @@ if not is_linux
 endif
 build = true
 
-pmd_dlopen = (get_option('ibverbs_link') == 'dlopen')
+static_ibverbs = (get_option('ibverbs_link') == 'static')
+dlopen_ibverbs = (get_option('ibverbs_link') == 'dlopen')
 LIB_GLUE_BASE = 'librte_pmd_mlx5_glue.so'
 LIB_GLUE_VERSION = '19.08.0'
 LIB_GLUE = LIB_GLUE_BASE + '.' + LIB_GLUE_VERSION
-if pmd_dlopen
+if dlopen_ibverbs
 	dpdk_conf.set('RTE_IBVERBS_LINK_DLOPEN', 1)
 	cflags += [
 		'-DMLX5_GLUE="@0@"'.format(LIB_GLUE),
@@ -24,12 +25,16 @@ endif
 libnames = [ 'mlx5', 'ibverbs' ]
 libs = []
 foreach libname:libnames
-	lib = dependency('lib' + libname, required:false)
-	if not lib.found()
+	lib = dependency('lib' + libname, static:static_ibverbs,
+			required:false, method: 'pkg-config')
+	if not lib.found() and not static_ibverbs
 		lib = cc.find_library(libname, required:false)
 	endif
 	if lib.found()
 		libs += [ lib ]
+		if not static_ibverbs
+			ext_deps += lib
+		endif
 	else
 		build = false
 		reason = 'missing dependency, "' + libname + '"'
@@ -37,9 +42,18 @@ foreach libname:libnames
 endforeach
 
 if build
+	if static_ibverbs or dlopen_ibverbs
+		# Build without adding shared libs to Requires.private
+		ibv_cflags = run_command(pkgconf, '--cflags', 'libibverbs').stdout()
+		ext_deps += declare_dependency(compile_args: ibv_cflags.split())
+	endif
+	if static_ibverbs
+		# Add static deps ldflags to internal apps and Libs.private
+		ibv_ldflags = run_command(ldflags_ibverbs_static, check:true).stdout()
+		ext_deps += declare_dependency(link_args:ibv_ldflags.split())
+	endif
 	allow_experimental_apis = true
 	deps += ['hash']
-	ext_deps += libs
 	sources = files(
 		'mlx5.c',
 		'mlx5_ethdev.c',
@@ -67,7 +81,7 @@ if build
 		or dpdk_conf.has('RTE_ARCH_PPC_64'))
 		sources += files('mlx5_rxtx_vec.c')
 	endif
-	if not pmd_dlopen
+	if not dlopen_ibverbs
 		sources += files('mlx5_glue.c')
 	endif
 	cflags_options = [
@@ -130,6 +144,8 @@ if build
 		'MLX5DV_FLOW_ACTION_COUNTERS_DEVX' ],
 		[ 'HAVE_IBV_DEVX_ASYNC', 'infiniband/mlx5dv.h',
 		'mlx5dv_devx_obj_query_async' ],
+		[ 'HAVE_IBV_DEVX_QP', 'infiniband/mlx5dv.h',
+		'mlx5dv_devx_qp_query' ],
 		[ 'HAVE_MLX5DV_DR_ACTION_DEST_DEVX_TIR', 'infiniband/mlx5dv.h',
 		'mlx5dv_dr_action_create_dest_devx_tir' ],
 		[ 'HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER', 'infiniband/mlx5dv.h',
@@ -200,7 +216,7 @@ if build
 	configure_file(output : 'mlx5_autoconf.h', configuration : config)
 endif
 # Build Glue Library
-if pmd_dlopen and build
+if dlopen_ibverbs and build
 	dlopen_name = 'mlx5_glue'
 	dlopen_lib_name = driver_name_fmt.format(dlopen_name)
 	dlopen_so_version = LIB_GLUE_VERSION
diff --git a/dpdk/drivers/net/mlx5/mlx5.c b/dpdk/drivers/net/mlx5/mlx5.c
index d84a6f91b4..f8de9e329e 100644
--- a/dpdk/drivers/net/mlx5/mlx5.c
+++ b/dpdk/drivers/net/mlx5/mlx5.c
@@ -12,7 +12,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <net/if.h>
-#include <sys/mman.h>
+#include <fcntl.h>
 #include <linux/rtnetlink.h>
 
 /* Verbs header. */
@@ -62,6 +62,9 @@
 /* Device parameter to configure log 2 of the number of strides for MPRQ. */
 #define MLX5_RX_MPRQ_LOG_STRIDE_NUM "mprq_log_stride_num"
 
+/* Device parameter to configure log 2 of the stride size for MPRQ. */
+#define MLX5_RX_MPRQ_LOG_STRIDE_SIZE "mprq_log_stride_size"
+
 /* Device parameter to limit the size of memcpy'd packet for MPRQ. */
 #define MLX5_RX_MPRQ_MAX_MEMCPY_LEN "mprq_max_memcpy_len"
 
@@ -184,6 +187,10 @@ struct mlx5_dev_spawn_data {
 	struct rte_pci_device *pci_dev; /**< Backend PCI device. */
 };
 
+#ifdef MLX5_GLUE
+const struct mlx5_glue *mlx5_glue;
+#endif
+
 static LIST_HEAD(, mlx5_ibv_shared) mlx5_ibv_list = LIST_HEAD_INITIALIZER();
 static pthread_mutex_t mlx5_ibv_list_mutex = PTHREAD_MUTEX_INITIALIZER;
 
@@ -196,11 +203,14 @@ static pthread_mutex_t mlx5_ibv_list_mutex = PTHREAD_MUTEX_INITIALIZER;
 /**
  * Allocate ID pool structure.
  *
+ * @param[in] max_id
+ *   The maximum id can be allocated from the pool.
+ *
  * @return
  *   Pointer to pool object, NULL value otherwise.
  */
 struct mlx5_flow_id_pool *
-mlx5_flow_id_pool_alloc(void)
+mlx5_flow_id_pool_alloc(uint32_t max_id)
 {
 	struct mlx5_flow_id_pool *pool;
 	void *mem;
@@ -223,6 +233,7 @@ mlx5_flow_id_pool_alloc(void)
 	pool->curr = pool->free_arr;
 	pool->last = pool->free_arr + MLX5_FLOW_MIN_ID_POOL_SIZE;
 	pool->base_index = 0;
+	pool->max_id = max_id;
 	return pool;
 error:
 	rte_free(pool);
@@ -257,7 +268,7 @@ uint32_t
 mlx5_flow_id_get(struct mlx5_flow_id_pool *pool, uint32_t *id)
 {
 	if (pool->curr == pool->free_arr) {
-		if (pool->base_index == UINT32_MAX) {
+		if (pool->base_index == pool->max_id) {
 			rte_errno  = ENOMEM;
 			DRV_LOG(ERR, "no free id");
 			return -rte_errno;
@@ -459,6 +470,85 @@ mlx5_restore_doorbell_mapping_env(int value)
 		setenv(MLX5_SHUT_UP_BF, value ? "1" : "0", 1);
 }
 
+/**
+ * Install shared asynchronous device events handler.
+ * This function is implemented to support event sharing
+ * between multiple ports of single IB device.
+ *
+ * @param sh
+ *   Pointer to mlx5_ibv_shared object.
+ */
+static void
+mlx5_dev_shared_handler_install(struct mlx5_ibv_shared *sh)
+{
+	int ret;
+	int flags;
+
+	sh->intr_handle.fd = -1;
+	flags = fcntl(sh->ctx->async_fd, F_GETFL);
+	ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
+	if (ret) {
+		DRV_LOG(INFO, "failed to change file descriptor async event"
+			" queue");
+	} else {
+		sh->intr_handle.fd = sh->ctx->async_fd;
+		sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
+		if (rte_intr_callback_register(&sh->intr_handle,
+					mlx5_dev_interrupt_handler, sh)) {
+			DRV_LOG(INFO, "Fail to install the shared interrupt.");
+			sh->intr_handle.fd = -1;
+		}
+	}
+	if (sh->devx) {
+#ifdef HAVE_IBV_DEVX_ASYNC
+		sh->intr_handle_devx.fd = -1;
+		sh->devx_comp = mlx5_glue->devx_create_cmd_comp(sh->ctx);
+		if (!sh->devx_comp) {
+			DRV_LOG(INFO, "failed to allocate devx_comp.");
+			return;
+		}
+		flags = fcntl(sh->devx_comp->fd, F_GETFL);
+		ret = fcntl(sh->devx_comp->fd, F_SETFL, flags | O_NONBLOCK);
+		if (ret) {
+			DRV_LOG(INFO, "failed to change file descriptor"
+				" devx comp");
+			return;
+		}
+		sh->intr_handle_devx.fd = sh->devx_comp->fd;
+		sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT;
+		if (rte_intr_callback_register(&sh->intr_handle_devx,
+					mlx5_dev_interrupt_handler_devx, sh)) {
+			DRV_LOG(INFO, "Fail to install the devx shared"
+				" interrupt.");
+			sh->intr_handle_devx.fd = -1;
+		}
+#endif /* HAVE_IBV_DEVX_ASYNC */
+	}
+}
+
+/**
+ * Uninstall shared asynchronous device events handler.
+ * This function is implemented to support event sharing
+ * between multiple ports of single IB device.
+ *
+ * @param dev
+ *   Pointer to mlx5_ibv_shared object.
+ */
+static void
+mlx5_dev_shared_handler_uninstall(struct mlx5_ibv_shared *sh)
+{
+	if (sh->intr_handle.fd >= 0)
+		mlx5_intr_callback_unregister(&sh->intr_handle,
+					      mlx5_dev_interrupt_handler, sh);
+#ifdef HAVE_IBV_DEVX_ASYNC
+	if (sh->intr_handle_devx.fd >= 0)
+		rte_intr_callback_unregister(&sh->intr_handle_devx,
+				  mlx5_dev_interrupt_handler_devx, sh);
+	if (sh->devx_comp)
+		mlx5_glue->devx_destroy_cmd_comp(sh->devx_comp);
+#endif
+}
+
 /**
  * Allocate shared IB device context. If there is multiport device the
  * master and representors will share this context, if there is single
@@ -553,7 +643,6 @@ mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn,
 		sizeof(sh->ibdev_name));
 	strncpy(sh->ibdev_path, sh->ctx->device->ibdev_path,
 		sizeof(sh->ibdev_path));
-	pthread_mutex_init(&sh->intr_mutex, NULL);
 	/*
 	 * Setting port_id to max unallowed value means
 	 * there is no interrupt subhandler installed for
@@ -590,13 +679,19 @@ mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn,
 			goto error;
 		}
 	}
-	sh->flow_id_pool = mlx5_flow_id_pool_alloc();
+	sh->flow_id_pool = mlx5_flow_id_pool_alloc(UINT32_MAX);
 	if (!sh->flow_id_pool) {
 		DRV_LOG(ERR, "can't create flow id pool");
 		err = ENOMEM;
 		goto error;
 	}
 #endif /* HAVE_IBV_FLOW_DV_SUPPORT */
+#ifndef RTE_ARCH_64
+	/* Initialize UAR access locks for 32bit implementations. */
+	rte_spinlock_init(&sh->uar_lock_cq);
+	for (i = 0; i < MLX5_UAR_PAGE_NUM_MAX; i++)
+		rte_spinlock_init(&sh->uar_lock[i]);
+#endif
 	/*
 	 * Once the device is added to the list of memory event
 	 * callback, its global MR cache table cannot be expanded
@@ -613,6 +708,7 @@ mlx5_alloc_shared_ibctx(const struct mlx5_dev_spawn_data *spawn,
 		err = rte_errno;
 		goto error;
 	}
+	mlx5_dev_shared_handler_install(sh);
 	mlx5_flow_counters_mng_init(sh);
 	/* Add device to memory callback list. */
 	rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock);
@@ -673,12 +769,12 @@ mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh)
 	assert(rte_eal_process_type() == RTE_PROC_PRIMARY);
 	if (--sh->refcnt)
 		goto exit;
-	/* Release created Memory Regions. */
-	mlx5_mr_release(sh);
 	/* Remove from memory callback device list. */
 	rte_rwlock_write_lock(&mlx5_shared_data->mem_event_rwlock);
 	LIST_REMOVE(sh, mem_event_cb);
 	rte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock);
+	/* Release created Memory Regions. */
+	mlx5_mr_release(sh);
 	/* Remove context from the global device list. */
 	LIST_REMOVE(sh, next);
 	/*
@@ -686,20 +782,7 @@ mlx5_free_shared_ibctx(struct mlx5_ibv_shared *sh)
 	 *  Only primary process handles async device events.
 	 **/
 	mlx5_flow_counters_mng_close(sh);
-	assert(!sh->intr_cnt);
-	if (sh->intr_cnt)
-		mlx5_intr_callback_unregister
-			(&sh->intr_handle, mlx5_dev_interrupt_handler, sh);
-#ifdef HAVE_MLX5_DEVX_ASYNC_SUPPORT
-	if (sh->devx_intr_cnt) {
-		if (sh->intr_handle_devx.fd)
-			rte_intr_callback_unregister(&sh->intr_handle_devx,
-					  mlx5_dev_interrupt_handler_devx, sh);
-		if (sh->devx_comp)
-			mlx5dv_devx_destroy_cmd_comp(sh->devx_comp);
-	}
-#endif
-	pthread_mutex_destroy(&sh->intr_mutex);
+	mlx5_dev_shared_handler_uninstall(sh);
 	if (sh->pd)
 		claim_zero(mlx5_glue->dealloc_pd(sh->pd));
 	if (sh->tis)
@@ -789,7 +872,7 @@ mlx5_alloc_table_hash_list(struct mlx5_priv *priv)
 	snprintf(s, sizeof(s), "%s_flow_table", priv->sh->ibdev_name);
 	sh->flow_tbls = mlx5_hlist_create(s, MLX5_FLOW_TABLE_HLIST_ARRAY_SIZE);
 	if (!sh->flow_tbls) {
-		DRV_LOG(ERR, "flow tables with hash creation failed.\n");
+		DRV_LOG(ERR, "flow tables with hash creation failed.");
 		err = ENOMEM;
 		return err;
 	}
@@ -868,27 +951,25 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
 {
 	struct mlx5_ibv_shared *sh = priv->sh;
 	char s[MLX5_HLIST_NAMESIZE];
-	int err = mlx5_alloc_table_hash_list(priv);
+	int err;
 
+	assert(sh && sh->refcnt);
+	if (sh->refcnt > 1)
+		return 0;
+	err = mlx5_alloc_table_hash_list(priv);
 	if (err)
 		return err;
 	/* Create tags hash list table. */
 	snprintf(s, sizeof(s), "%s_tags", sh->ibdev_name);
 	sh->tag_table = mlx5_hlist_create(s, MLX5_TAGS_HLIST_ARRAY_SIZE);
 	if (!sh->tag_table) {
-		DRV_LOG(ERR, "tags with hash creation failed.\n");
+		DRV_LOG(ERR, "tags with hash creation failed.");
 		err = ENOMEM;
 		goto error;
 	}
 #ifdef HAVE_MLX5DV_DR
 	void *domain;
 
-	if (sh->dv_refcnt) {
-		/* Shared DV/DR structures is already initialized. */
-		sh->dv_refcnt++;
-		priv->dr_shared = 1;
-		return 0;
-	}
 	/* Reference counter is zero, we should initialize structures. */
 	domain = mlx5_glue->dr_create_domain(sh->ctx,
 					     MLX5DV_DR_DOMAIN_TYPE_NIC_RX);
@@ -922,8 +1003,6 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
 #endif
 	sh->pop_vlan_action = mlx5_glue->dr_create_flow_action_pop_vlan();
 #endif /* HAVE_MLX5DV_DR */
-	sh->dv_refcnt++;
-	priv->dr_shared = 1;
 	return 0;
 error:
 	/* Rollback the created objects. */
@@ -965,17 +1044,12 @@ mlx5_alloc_shared_dr(struct mlx5_priv *priv)
 static void
 mlx5_free_shared_dr(struct mlx5_priv *priv)
 {
-	struct mlx5_ibv_shared *sh;
+	struct mlx5_ibv_shared *sh = priv->sh;
 
-	if (!priv->dr_shared)
+	assert(sh && sh->refcnt);
+	if (sh->refcnt > 1)
 		return;
-	priv->dr_shared = 0;
-	sh = priv->sh;
-	assert(sh);
 #ifdef HAVE_MLX5DV_DR
-	assert(sh->dv_refcnt);
-	if (sh->dv_refcnt && --sh->dv_refcnt)
-		return;
 	if (sh->rx_domain) {
 		mlx5_glue->dr_destroy_domain(sh->rx_domain);
 		sh->rx_domain = NULL;
@@ -1177,13 +1251,13 @@ mlx5_proc_priv_init(struct rte_eth_dev *dev)
 	 */
 	ppriv_size =
 		sizeof(struct mlx5_proc_priv) + priv->txqs_n * sizeof(void *);
-	ppriv = rte_malloc_socket("mlx5_proc_priv", ppriv_size,
+	ppriv = rte_zmalloc_socket("mlx5_proc_priv", ppriv_size,
 				  RTE_CACHE_LINE_SIZE, dev->device->numa_node);
 	if (!ppriv) {
 		rte_errno = ENOMEM;
 		return -rte_errno;
 	}
-	ppriv->uar_table_sz = ppriv_size;
+	ppriv->uar_table_sz = priv->txqs_n;
 	dev->process_private = ppriv;
 	return 0;
 }
@@ -1194,7 +1268,7 @@ mlx5_proc_priv_init(struct rte_eth_dev *dev)
  * @param dev
  *   Pointer to Ethernet device structure.
  */
-static void
+void
 mlx5_proc_priv_uninit(struct rte_eth_dev *dev)
 {
 	if (!dev->process_private)
@@ -1218,12 +1292,20 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 	unsigned int i;
 	int ret;
 
+	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		/* Check if process_private released. */
+		if (!dev->process_private)
+			return;
+		mlx5_tx_uar_uninit_secondary(dev);
+		mlx5_proc_priv_uninit(dev);
+		rte_eth_dev_release_port(dev);
+		return;
+	}
+	if (!priv->sh)
+		return;
 	DRV_LOG(DEBUG, "port %u closing device \"%s\"",
 		dev->data->port_id,
 		((priv->sh->ctx != NULL) ? priv->sh->ctx->device->name : ""));
-	/* In case mlx5_dev_stop() has not been called. */
-	mlx5_dev_interrupt_handler_uninstall(dev);
-	mlx5_dev_interrupt_handler_devx_uninstall(dev);
 	mlx5_traffic_disable(dev);
 	mlx5_flow_flush(dev, NULL);
 	mlx5_flow_meter_flush(dev, NULL);
@@ -1266,16 +1348,13 @@ mlx5_dev_close(struct rte_eth_dev *dev)
 		close(priv->nl_socket_rdma);
 	if (priv->vmwa_context)
 		mlx5_vlan_vmwa_exit(priv->vmwa_context);
-	if (priv->sh) {
-		/*
-		 * Free the shared context in last turn, because the cleanup
-		 * routines above may use some shared fields, like
-		 * mlx5_nl_mac_addr_flush() uses ibdev_path for retrieveing
-		 * ifindex if Netlink fails.
-		 */
-		mlx5_free_shared_ibctx(priv->sh);
-		priv->sh = NULL;
-	}
+	/*
+	 * Free the shared context in last turn, because the cleanup
+	 * routines above may use some shared fields, like
+	 * mlx5_nl_mac_addr_flush() uses ibdev_path for retrieveing
+	 * ifindex if Netlink fails.
+	 */
+	mlx5_free_shared_ibctx(priv->sh);
 	ret = mlx5_hrxq_verify(dev);
 	if (ret)
 		DRV_LOG(WARNING, "port %u some hash Rx queue still remain",
@@ -1490,6 +1569,8 @@ mlx5_args_check(const char *key, const char *val, void *opaque)
 		config->mprq.enabled = !!tmp;
 	} else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_NUM, key) == 0) {
 		config->mprq.stride_num_n = tmp;
+	} else if (strcmp(MLX5_RX_MPRQ_LOG_STRIDE_SIZE, key) == 0) {
+		config->mprq.stride_size_n = tmp;
 	} else if (strcmp(MLX5_RX_MPRQ_MAX_MEMCPY_LEN, key) == 0) {
 		config->mprq.max_memcpy_len = tmp;
 	} else if (strcmp(MLX5_RXQS_MIN_MPRQ, key) == 0) {
@@ -1582,6 +1663,7 @@ mlx5_args(struct mlx5_dev_config *config, struct rte_devargs *devargs)
 		MLX5_RXQ_PKT_PAD_EN,
 		MLX5_RX_MPRQ_EN,
 		MLX5_RX_MPRQ_LOG_STRIDE_NUM,
+		MLX5_RX_MPRQ_LOG_STRIDE_SIZE,
 		MLX5_RX_MPRQ_MAX_MEMCPY_LEN,
 		MLX5_RXQS_MIN_MPRQ,
 		MLX5_TXQ_INLINE,
@@ -1697,7 +1779,7 @@ mlx5_init_once(void)
  *   key is specified in devargs
  * - if DevX is enabled the inline mode is queried from the
  *   device (HCA attributes and NIC vport context if needed).
- * - otherwise L2 mode (18 bytes) is assumed for ConnectX-4/4LX
+ * - otherwise L2 mode (18 bytes) is assumed for ConnectX-4/4 Lx
  *   and none (0 bytes) for other NICs
  *
  * @param spawn
@@ -1931,12 +2013,12 @@ mlx5_get_dbr(struct rte_eth_dev *dev, struct mlx5_devx_dbr_page **dbr_page)
 	     i++)
 		; /* Empty. */
 	/* Find the first clear bit. */
+	assert(i < MLX5_DBR_BITMAP_SIZE);
 	j = rte_bsf64(~page->dbr_bitmap[i]);
-	assert(i < (MLX5_DBR_PER_PAGE / 64));
-	page->dbr_bitmap[i] |= (1 << j);
+	page->dbr_bitmap[i] |= (UINT64_C(1) << j);
 	page->dbr_count++;
 	*dbr_page = page;
-	return (((i * 64) + j) * sizeof(uint64_t));
+	return (i * CHAR_BIT * sizeof(uint64_t) + j) * MLX5_DBR_SIZE;
 }
 
 /**
@@ -1978,7 +2060,7 @@ mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id, uint64_t offset)
 		int i = offset / 64;
 		int j = offset % 64;
 
-		page->dbr_bitmap[i] &= ~(1 << j);
+		page->dbr_bitmap[i] &= ~(UINT64_C(1) << j);
 	}
 	return ret;
 }
@@ -2145,11 +2227,11 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		/* Receive command fd from primary process */
 		err = mlx5_mp_req_verbs_cmd_fd(eth_dev);
 		if (err < 0)
-			return NULL;
+			goto err_secondary;
 		/* Remap UAR for Tx queues. */
 		err = mlx5_tx_uar_init_secondary(eth_dev, err);
 		if (err)
-			return NULL;
+			goto err_secondary;
 		/*
 		 * Ethdev pointer is still required as input since
 		 * the primary device is not accessible from the
@@ -2158,6 +2240,9 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		eth_dev->rx_pkt_burst = mlx5_select_rx_function(eth_dev);
 		eth_dev->tx_pkt_burst = mlx5_select_tx_function(eth_dev);
 		return eth_dev;
+err_secondary:
+		mlx5_dev_close(eth_dev);
+		return NULL;
 	}
 	/*
 	 * Some parameters ("tx_db_nc" in particularly) are needed in
@@ -2236,8 +2321,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 			mprq_caps.min_single_wqe_log_num_of_strides;
 		mprq_max_stride_num_n =
 			mprq_caps.max_single_wqe_log_num_of_strides;
-		config.mprq.stride_num_n = RTE_MAX(MLX5_MPRQ_STRIDE_NUM_N,
-						   mprq_min_stride_num_n);
 	}
 #endif
 	if (RTE_CACHE_LINE_SIZE == 128 &&
@@ -2307,12 +2390,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 	priv->ibv_port = spawn->ibv_port;
 	priv->pci_dev = spawn->pci_dev;
 	priv->mtu = RTE_ETHER_MTU;
-#ifndef RTE_ARCH_64
-	/* Initialize UAR access locks for 32bit implementations. */
-	rte_spinlock_init(&priv->uar_lock_cq);
-	for (i = 0; i < MLX5_UAR_PAGE_NUM_MAX; i++)
-		rte_spinlock_init(&priv->uar_lock[i]);
-#endif
 	/* Some internal functions rely on Netlink sockets, open them now. */
 	priv->nl_socket_rdma = mlx5_nl_init(NETLINK_RDMA);
 	priv->nl_socket_route =	mlx5_nl_init(NETLINK_ROUTE);
@@ -2543,6 +2620,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 				priv->mtr_color_reg = ffs(reg_c_mask) - 1 +
 						      REG_C_0;
 				priv->mtr_en = 1;
+				priv->mtr_reg_share =
+				      config.hca_attr.qos.flow_meter_reg_share;
 				DRV_LOG(DEBUG, "The REG_C meter uses is %d",
 					priv->mtr_color_reg);
 			}
@@ -2550,17 +2629,32 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 #endif
 	}
 	if (config.mprq.enabled && mprq) {
-		if (config.mprq.stride_num_n > mprq_max_stride_num_n ||
-		    config.mprq.stride_num_n < mprq_min_stride_num_n) {
+		if (config.mprq.stride_num_n &&
+		    (config.mprq.stride_num_n > mprq_max_stride_num_n ||
+		     config.mprq.stride_num_n < mprq_min_stride_num_n)) {
 			config.mprq.stride_num_n =
-				RTE_MAX(MLX5_MPRQ_STRIDE_NUM_N,
-					mprq_min_stride_num_n);
+				RTE_MIN(RTE_MAX(MLX5_MPRQ_STRIDE_NUM_N,
+						mprq_min_stride_num_n),
+					mprq_max_stride_num_n);
 			DRV_LOG(WARNING,
 				"the number of strides"
 				" for Multi-Packet RQ is out of range,"
 				" setting default value (%u)",
 				1 << config.mprq.stride_num_n);
 		}
+		if (config.mprq.stride_size_n &&
+		    (config.mprq.stride_size_n > mprq_max_stride_size_n ||
+		     config.mprq.stride_size_n < mprq_min_stride_size_n)) {
+			config.mprq.stride_size_n =
+				RTE_MIN(RTE_MAX(MLX5_MPRQ_STRIDE_SIZE_N,
+						mprq_min_stride_size_n),
+					mprq_max_stride_size_n);
+			DRV_LOG(WARNING,
+				"the size of a stride"
+				" for Multi-Packet RQ is out of range,"
+				" setting default value (%u)",
+				1 << config.mprq.stride_size_n);
+		}
 		config.mprq.min_stride_size_n = mprq_min_stride_size_n;
 		config.mprq.max_stride_size_n = mprq_max_stride_size_n;
 	} else if (config.mprq.enabled && !mprq) {
@@ -2675,7 +2769,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
 		err = mlx5_alloc_shared_dr(priv);
 		if (err)
 			goto error;
-		priv->qrss_id_pool = mlx5_flow_id_pool_alloc();
+		/*
+		 * RSS id is shared with meter flow id. Meter flow id can only
+		 * use the 24 MSB of the register.
+		 */
+		priv->qrss_id_pool = mlx5_flow_id_pool_alloc(UINT32_MAX >>
+				     MLX5_MTR_COLOR_BITS);
 		if (!priv->qrss_id_pool) {
 			DRV_LOG(ERR, "can't create flow id pool");
 			err = ENOMEM;
@@ -3074,7 +3173,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		/*
 		 * Single IB device with multiple ports found,
 		 * it may be E-Switch master device and representors.
-		 * We have to perform identification trough the ports.
+		 * We have to perform identification through the ports.
 		 */
 		assert(nl_rdma >= 0);
 		assert(ns == 0);
@@ -3274,7 +3373,8 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		.mr_ext_memseg_en = 1,
 		.mprq = {
 			.enabled = 0, /* Disabled by default. */
-			.stride_num_n = MLX5_MPRQ_STRIDE_NUM_N,
+			.stride_num_n = 0,
+			.stride_size_n = 0,
 			.max_memcpy_len = MLX5_MPRQ_MEMCPY_DEFAULT_LEN,
 			.min_rxqs_num = MLX5_MPRQ_MIN_RXQS,
 		},
@@ -3289,7 +3389,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 	case PCI_DEVICE_ID_MELLANOX_CONNECTX5EXVF:
 	case PCI_DEVICE_ID_MELLANOX_CONNECTX5BFVF:
 	case PCI_DEVICE_ID_MELLANOX_CONNECTX6VF:
-	case PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF:
+	case PCI_DEVICE_ID_MELLANOX_CONNECTXVF:
 		dev_config.vf = 1;
 		break;
 	default:
@@ -3311,7 +3411,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
 		rte_eth_copy_pci_info(list[i].eth_dev, pci_dev);
 		/* Restore non-PCI flags cleared by the above call. */
 		list[i].eth_dev->data->dev_flags |= restore;
-		mlx5_dev_interrupt_handler_devx_install(list[i].eth_dev);
 		rte_eth_dev_probing_finish(list[i].eth_dev);
 	}
 	if (i != ns) {
@@ -3405,8 +3504,16 @@ mlx5_pci_remove(struct rte_pci_device *pci_dev)
 {
 	uint16_t port_id;
 
-	RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device)
-		rte_eth_dev_close(port_id);
+	RTE_ETH_FOREACH_DEV_OF(port_id, &pci_dev->device) {
+		/*
+		 * mlx5_dev_close() is not registered to secondary process,
+		 * call the close function explicitly for secondary process.
+		 */
+		if (rte_eal_process_type() == RTE_PROC_SECONDARY)
+			mlx5_dev_close(&rte_eth_devices[port_id]);
+		else
+			rte_eth_dev_close(port_id);
+	}
 	return 0;
 }
 
@@ -3465,7 +3572,7 @@ static const struct rte_pci_id mlx5_pci_id_map[] = {
 	},
 	{
 		RTE_PCI_DEVICE(PCI_VENDOR_ID_MELLANOX,
-				PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF)
+				PCI_DEVICE_ID_MELLANOX_CONNECTXVF)
 	},
 	{
 		.vendor_id = 0
diff --git a/dpdk/drivers/net/mlx5/mlx5.h b/dpdk/drivers/net/mlx5/mlx5.h
index 0c3a90e1bf..0e4a5f870d 100644
--- a/dpdk/drivers/net/mlx5/mlx5.h
+++ b/dpdk/drivers/net/mlx5/mlx5.h
@@ -57,7 +57,7 @@ enum {
 	PCI_DEVICE_ID_MELLANOX_CONNECTX6 = 0x101b,
 	PCI_DEVICE_ID_MELLANOX_CONNECTX6VF = 0x101c,
 	PCI_DEVICE_ID_MELLANOX_CONNECTX6DX = 0x101d,
-	PCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF = 0x101e,
+	PCI_DEVICE_ID_MELLANOX_CONNECTXVF = 0x101e,
 };
 
 /* Request types for IPC. */
@@ -148,12 +148,15 @@ struct mlx5_xstats_ctrl {
 	/* Index in the device counters table. */
 	uint16_t dev_table_idx[MLX5_MAX_XSTATS];
 	uint64_t base[MLX5_MAX_XSTATS];
+	uint64_t xstats[MLX5_MAX_XSTATS];
+	uint64_t hw_stats[MLX5_MAX_XSTATS];
 	struct mlx5_counter_ctrl info[MLX5_MAX_XSTATS];
 };
 
 struct mlx5_stats_ctrl {
 	/* Base for imissed counter. */
 	uint64_t imissed_base;
+	uint64_t imissed;
 };
 
 /* devX creation object */
@@ -173,6 +176,8 @@ struct mlx5_devx_mkey_attr {
 struct mlx5_hca_qos_attr {
 	uint32_t sup:1;	/* Whether QOS is supported. */
 	uint32_t srtcm_sup:1; /* Whether srTCM mode is supported. */
+	uint32_t flow_meter_reg_share:1;
+	/* Whether reg_c share is supported. */
 	uint8_t log_max_flow_meter;
 	/* Power of the maximum supported meters. */
 	uint8_t flow_meter_reg_c_ids;
@@ -262,6 +267,7 @@ struct mlx5_dev_config {
 	struct {
 		unsigned int enabled:1; /* Whether MPRQ is enabled. */
 		unsigned int stride_num_n; /* Number of strides. */
+		unsigned int stride_size_n; /* Size of a stride. */
 		unsigned int min_stride_size_n; /* Min size of a stride. */
 		unsigned int max_stride_size_n; /* Max size of a stride. */
 		unsigned int max_memcpy_len;
@@ -364,7 +370,7 @@ struct mlx5_devx_tir_attr {
 	uint32_t rx_hash_fn:4;
 	uint32_t self_lb_block:2;
 	uint32_t transport_domain:24;
-	uint32_t rx_hash_toeplitz_key[10];
+	uint8_t rx_hash_toeplitz_key[MLX5_RSS_HASH_KEY_LEN];
 	struct mlx5_rx_hash_field_select rx_hash_field_selector_outer;
 	struct mlx5_rx_hash_field_select rx_hash_field_selector_inner;
 };
@@ -480,7 +486,8 @@ struct mlx5_flow_counter {
 	uint32_t shared:1; /**< Share counter ID with other flow rules. */
 	uint32_t batch: 1;
 	/**< Whether the counter was allocated by batch command. */
-	uint32_t ref_cnt:30; /**< Reference counter. */
+	uint32_t ref_cnt:29; /**< Reference counter. */
+	uint32_t skipped:1; /* This counter is skipped or not. */
 	uint32_t id; /**< Counter ID. */
 	union {  /**< Holds the counters for the rule. */
 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
@@ -512,6 +519,7 @@ struct mlx5_flow_counter_pool {
 	/* The devx object of the minimum counter ID. */
 	rte_atomic64_t query_gen;
 	uint32_t n_counters: 16; /* Number of devx allocated counters. */
+	uint32_t skip_cnt:1; /* Pool contains skipped counter. */
 	rte_spinlock_t sl; /* The pool lock. */
 	struct mlx5_counter_stats_raw *raw;
 	struct mlx5_counter_stats_raw *raw_hw; /* The raw on HW working. */
@@ -594,20 +602,22 @@ struct mlx5_flow_tbl_resource {
 };
 
 #define MLX5_MAX_TABLES UINT16_MAX
-#define MLX5_FLOW_TABLE_LEVEL_METER (UINT16_MAX - 3)
-#define MLX5_FLOW_TABLE_LEVEL_SUFFIX (UINT16_MAX - 2)
 #define MLX5_HAIRPIN_TX_TABLE (UINT16_MAX - 1)
 /* Reserve the last two tables for metadata register copy. */
 #define MLX5_FLOW_MREG_ACT_TABLE_GROUP (MLX5_MAX_TABLES - 1)
 #define MLX5_FLOW_MREG_CP_TABLE_GROUP (MLX5_MAX_TABLES - 2)
 /* Tables for metering splits should be added here. */
-#define MLX5_MAX_TABLES_EXTERNAL (MLX5_MAX_TABLES - 3)
+#define MLX5_FLOW_TABLE_LEVEL_SUFFIX (MLX5_MAX_TABLES - 3)
+#define MLX5_FLOW_TABLE_LEVEL_METER (MLX5_MAX_TABLES - 4)
+#define MLX5_MAX_TABLES_EXTERNAL MLX5_FLOW_TABLE_LEVEL_METER
 #define MLX5_MAX_TABLES_FDB UINT16_MAX
 
-#define MLX5_DBR_PAGE_SIZE 4096 /* Must be >= 512. */
-#define MLX5_DBR_SIZE 8
-#define MLX5_DBR_PER_PAGE (MLX5_DBR_PAGE_SIZE / MLX5_DBR_SIZE)
-#define MLX5_DBR_BITMAP_SIZE (MLX5_DBR_PER_PAGE / 64)
+#define MLX5_DBR_SIZE RTE_CACHE_LINE_SIZE
+#define MLX5_DBR_PER_PAGE 64
+/* Must be >= CHAR_BIT * sizeof(uint64_t) */
+#define MLX5_DBR_PAGE_SIZE (MLX5_DBR_PER_PAGE * MLX5_DBR_SIZE)
+/* Page size must be >= 512. */
+#define MLX5_DBR_BITMAP_SIZE (MLX5_DBR_PER_PAGE / (CHAR_BIT * sizeof(uint64_t)))
 
 struct mlx5_devx_dbr_page {
 	/* Door-bell records, must be first member in structure. */
@@ -626,6 +636,7 @@ struct mlx5_flow_id_pool {
 	/**< The next index that can be used without any free elements. */
 	uint32_t *curr; /**< Pointer to the index to pop. */
 	uint32_t *last; /**< Pointer to the last element in the empty arrray. */
+	uint32_t max_id; /**< Maximum id can be allocated from the pool. */
 };
 
 /*
@@ -658,16 +669,14 @@ struct mlx5_ibv_shared {
 	uint32_t dv_meta_mask; /* flow META metadata supported mask. */
 	uint32_t dv_mark_mask; /* flow MARK metadata supported mask. */
 	uint32_t dv_regc0_mask; /* available bits of metatada reg_c[0]. */
-	uint32_t dv_refcnt; /* DV/DR data reference counter. */
 	void *fdb_domain; /* FDB Direct Rules name space handle. */
-	struct mlx5_flow_tbl_resource *fdb_mtr_sfx_tbl;
-	/* FDB meter suffix rules table. */
 	void *rx_domain; /* RX Direct Rules name space handle. */
-	struct mlx5_flow_tbl_resource *rx_mtr_sfx_tbl;
-	/* RX meter suffix rules table. */
 	void *tx_domain; /* TX Direct Rules name space handle. */
-	struct mlx5_flow_tbl_resource *tx_mtr_sfx_tbl;
-	/* TX meter suffix rules table. */
+#ifndef RTE_ARCH_64
+	rte_spinlock_t uar_lock_cq; /* CQs share a common distinct UAR */
+	rte_spinlock_t uar_lock[MLX5_UAR_PAGE_NUM_MAX];
+	/* UAR same-page access control required in 32bit implementations. */
+#endif
 	struct mlx5_hlist *flow_tbls;
 	/* Direct Rules tables for FDB, NIC TX+RX */
 	void *esw_drop_action; /* Pointer to DR E-Switch drop action. */
@@ -681,10 +690,7 @@ struct mlx5_ibv_shared {
 		push_vlan_action_list; /* List of push VLAN actions. */
 	struct mlx5_flow_counter_mng cmng; /* Counters management structure. */
 	/* Shared interrupt handler section. */
-	pthread_mutex_t intr_mutex; /* Interrupt config mutex. */
-	uint32_t intr_cnt; /* Interrupt handler reference counter. */
 	struct rte_intr_handle intr_handle; /* Interrupt handler for device. */
-	uint32_t devx_intr_cnt; /* Devx interrupt handler reference counter. */
 	struct rte_intr_handle intr_handle_devx; /* DEVX interrupt handler. */
 	struct mlx5dv_devx_cmd_comp *devx_comp; /* DEVX async comp obj. */
 	struct mlx5_devx_obj *tis; /* TIS object. */
@@ -693,7 +699,10 @@ struct mlx5_ibv_shared {
 	struct mlx5_ibv_shared_port port[]; /* per device port data array. */
 };
 
-/* Per-process private structure. */
+/*
+ * Per-process private structure.
+ * Caution, secondary process may rebuild the struct during port start.
+ */
 struct mlx5_proc_priv {
 	size_t uar_table_sz;
 	/* Size of UAR register table. */
@@ -724,9 +733,9 @@ struct mlx5_priv {
 	unsigned int isolated:1; /* Whether isolated mode is enabled. */
 	unsigned int representor:1; /* Device is a port representor. */
 	unsigned int master:1; /* Device is a E-Switch master. */
-	unsigned int dr_shared:1; /* DV/DR data is shared. */
 	unsigned int counter_fallback:1; /* Use counter fallback management. */
 	unsigned int mtr_en:1; /* Whether support meter. */
+	unsigned int mtr_reg_share:1; /* Whether support meter REG_C share. */
 	uint16_t domain_id; /* Switch domain identifier. */
 	uint16_t vport_id; /* Associated VF vport index (if any). */
 	uint32_t vport_meta_tag; /* Used for vport index match ove VF LAG. */
@@ -778,12 +787,8 @@ struct mlx5_priv {
 	uint8_t mtr_color_reg; /* Meter color match REG_C. */
 	struct mlx5_mtr_profiles flow_meter_profiles; /* MTR profile list. */
 	struct mlx5_flow_meters flow_meters; /* MTR list. */
-#ifndef RTE_ARCH_64
-	rte_spinlock_t uar_lock_cq; /* CQs share a common distinct UAR */
-	rte_spinlock_t uar_lock[MLX5_UAR_PAGE_NUM_MAX];
-	/* UAR same-page access control required in 32bit implementations. */
-#endif
 	uint8_t skip_default_rss_reta; /* Skip configuration of default reta. */
+	uint8_t fdb_def_rule; /* Whether fdb jump to table 1 is configured. */
 };
 
 #define PORT_ID(priv) ((priv)->dev_data->port_id)
@@ -797,6 +802,7 @@ int64_t mlx5_get_dbr(struct rte_eth_dev *dev,
 		     struct mlx5_devx_dbr_page **dbr_page);
 int32_t mlx5_release_dbr(struct rte_eth_dev *dev, uint32_t umem_id,
 			 uint64_t offset);
+void mlx5_proc_priv_uninit(struct rte_eth_dev *dev);
 int mlx5_udp_tunnel_port_add(struct rte_eth_dev *dev,
 			      struct rte_eth_udp_tunnel *udp_tunnel);
 uint16_t mlx5_eth_find_next(uint16_t port_id, struct rte_pci_device *pci_dev);
@@ -835,8 +841,6 @@ void mlx5_dev_interrupt_handler(void *arg);
 void mlx5_dev_interrupt_handler_devx(void *arg);
 void mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev);
 void mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev);
-void mlx5_dev_interrupt_handler_devx_uninstall(struct rte_eth_dev *dev);
-void mlx5_dev_interrupt_handler_devx_install(struct rte_eth_dev *dev);
 int mlx5_set_link_down(struct rte_eth_dev *dev);
 int mlx5_set_link_up(struct rte_eth_dev *dev);
 int mlx5_is_removed(struct rte_eth_dev *dev);
@@ -972,6 +976,7 @@ struct mlx5_flow_counter *mlx5_counter_alloc(struct rte_eth_dev *dev);
 void mlx5_counter_free(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt);
 int mlx5_counter_query(struct rte_eth_dev *dev, struct mlx5_flow_counter *cnt,
 		       bool clear, uint64_t *pkts, uint64_t *bytes);
+void mlx5_flow_rxq_dynf_metadata_set(struct rte_eth_dev *dev);
 
 /* mlx5_mp.c */
 void mlx5_mp_req_start_rxtx(struct rte_eth_dev *dev);
diff --git a/dpdk/drivers/net/mlx5/mlx5_defs.h b/dpdk/drivers/net/mlx5/mlx5_defs.h
index 042e1f31ee..2836099b75 100644
--- a/dpdk/drivers/net/mlx5/mlx5_defs.h
+++ b/dpdk/drivers/net/mlx5/mlx5_defs.h
@@ -61,7 +61,7 @@
 
 /* Switch port ID parameters for bonding configurations. */
 #define MLX5_PORT_ID_BONDING_PF_MASK 0xf
-#define MLX5_PORT_ID_BONDING_PF_SHIFT 0xf
+#define MLX5_PORT_ID_BONDING_PF_SHIFT 12
 
 /* Alarm timeout. */
 #define MLX5_ALARM_TIMEOUT_US 100000
@@ -146,6 +146,9 @@
 /* Log 2 of the default number of strides per WQE for Multi-Packet RQ. */
 #define MLX5_MPRQ_STRIDE_NUM_N 6U
 
+/* Log 2 of the default size of a stride per WQE for Multi-Packet RQ. */
+#define MLX5_MPRQ_STRIDE_SIZE_N 11U
+
 /* Two-byte shift is disabled for Multi-Packet RQ. */
 #define MLX5_MPRQ_TWO_BYTE_SHIFT 0
 
@@ -176,6 +179,10 @@
 #define MLX5_FLOW_MREG_HNAME "MARK_COPY_TABLE"
 #define MLX5_DEFAULT_COPY_ID UINT32_MAX
 
+/* Hairpin TX/RX queue configuration parameters. */
+#define MLX5_HAIRPIN_QUEUE_STRIDE 6
+#define MLX5_HAIRPIN_JUMBO_LOG_SIZE (15 + 2)
+
 /* Definition of static_assert found in /usr/include/assert.h */
 #ifndef HAVE_STATIC_ASSERT
 #define static_assert _Static_assert
diff --git a/dpdk/drivers/net/mlx5/mlx5_devx_cmds.c b/dpdk/drivers/net/mlx5/mlx5_devx_cmds.c
index 9893287ba8..f9c4043c11 100644
--- a/dpdk/drivers/net/mlx5/mlx5_devx_cmds.c
+++ b/dpdk/drivers/net/mlx5/mlx5_devx_cmds.c
@@ -362,6 +362,8 @@ mlx5_devx_cmd_query_hca_attr(struct ibv_context *ctx,
 				MLX5_GET(qos_cap, hcattr, log_max_flow_meter);
 		attr->qos.flow_meter_reg_c_ids =
 			MLX5_GET(qos_cap, hcattr, flow_meter_reg_id);
+		attr->qos.flow_meter_reg_share =
+			MLX5_GET(qos_cap, hcattr, flow_meter_reg_share);
 	}
 	if (!attr->eth_net_offloads)
 		return 0;
@@ -633,9 +635,8 @@ mlx5_devx_cmd_create_tir(struct ibv_context *ctx,
 {
 	uint32_t in[MLX5_ST_SZ_DW(create_tir_in)] = {0};
 	uint32_t out[MLX5_ST_SZ_DW(create_tir_out)] = {0};
-	void *tir_ctx, *outer, *inner;
+	void *tir_ctx, *outer, *inner, *rss_key;
 	struct mlx5_devx_obj *tir = NULL;
-	int i;
 
 	tir = rte_calloc(__func__, 1, sizeof(*tir), 0);
 	if (!tir) {
@@ -658,10 +659,8 @@ mlx5_devx_cmd_create_tir(struct ibv_context *ctx,
 	MLX5_SET(tirc, tir_ctx, rx_hash_fn, tir_attr->rx_hash_fn);
 	MLX5_SET(tirc, tir_ctx, self_lb_block, tir_attr->self_lb_block);
 	MLX5_SET(tirc, tir_ctx, transport_domain, tir_attr->transport_domain);
-	for (i = 0; i < 10; i++) {
-		MLX5_SET(tirc, tir_ctx, rx_hash_toeplitz_key[i],
-			 tir_attr->rx_hash_toeplitz_key[i]);
-	}
+	rss_key = MLX5_ADDR_OF(tirc, tir_ctx, rx_hash_toeplitz_key);
+	memcpy(rss_key, tir_attr->rx_hash_toeplitz_key, MLX5_RSS_HASH_KEY_LEN);
 	outer = MLX5_ADDR_OF(tirc, tir_ctx, rx_hash_field_selector_outer);
 	MLX5_SET(rx_hash_field_select, outer, l3_prot_type,
 		 tir_attr->rx_hash_field_selector_outer.l3_prot_type);
@@ -779,7 +778,7 @@ mlx5_devx_cmd_create_sq(struct ibv_context *ctx,
 	MLX5_SET(sqc, sq_ctx, fre, sq_attr->fre);
 	MLX5_SET(sqc, sq_ctx, flush_in_error_en, sq_attr->flush_in_error_en);
 	MLX5_SET(sqc, sq_ctx, allow_multi_pkt_send_wqe,
-		 sq_attr->flush_in_error_en);
+		 sq_attr->allow_multi_pkt_send_wqe);
 	MLX5_SET(sqc, sq_ctx, min_wqe_inline_mode,
 		 sq_attr->min_wqe_inline_mode);
 	MLX5_SET(sqc, sq_ctx, state, sq_attr->state);
diff --git a/dpdk/drivers/net/mlx5/mlx5_ethdev.c b/dpdk/drivers/net/mlx5/mlx5_ethdev.c
index d80ae458bc..efcc69ca44 100644
--- a/dpdk/drivers/net/mlx5/mlx5_ethdev.c
+++ b/dpdk/drivers/net/mlx5/mlx5_ethdev.c
@@ -405,9 +405,6 @@ mlx5_dev_configure(struct rte_eth_dev *dev)
 		return -rte_errno;
 	}
 
-	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
-		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
-
 	memcpy(priv->rss_conf.rss_key,
 	       use_app_rss_key ?
 	       dev->data->dev_conf.rx_adv_conf.rss_conf.rss_key :
@@ -476,7 +473,7 @@ mlx5_dev_configure_rss_reta(struct rte_eth_dev *dev)
 
 		rxq_data = (*priv->rxqs)[i];
 		rxq_ctrl = container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
-		if (rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
+		if (rxq_ctrl && rxq_ctrl->type == MLX5_RXQ_TYPE_STANDARD)
 			rss_queue_arr[j++] = i;
 	}
 	rss_queue_n = j;
@@ -649,14 +646,22 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 			 * representors (more than 4K) or PFs (more than 15)
 			 * this approach must be reconsidered.
 			 */
-			if ((info->switch_info.port_id >>
-				MLX5_PORT_ID_BONDING_PF_SHIFT) ||
+			/* Switch port ID for VF representors: 0 - 0xFFE */
+			if ((info->switch_info.port_id != 0xffff &&
+				info->switch_info.port_id >=
+				((1 << MLX5_PORT_ID_BONDING_PF_SHIFT) - 1)) ||
 			    priv->pf_bond > MLX5_PORT_ID_BONDING_PF_MASK) {
 				DRV_LOG(ERR, "can't update switch port ID"
 					     " for bonding device");
 				assert(false);
 				return -ENODEV;
 			}
+			/*
+			 * Switch port ID for Host PF representor
+			 * (representor_id is -1) , set to 0xFFF
+			 */
+			if (info->switch_info.port_id == 0xffff)
+				info->switch_info.port_id = 0xfff;
 			info->switch_info.port_id |=
 				priv->pf_bond << MLX5_PORT_ID_BONDING_PF_SHIFT;
 		}
@@ -1226,6 +1231,7 @@ mlx5_dev_to_pci_addr(const char *dev_path,
 {
 	FILE *file;
 	char line[32];
+	int rc = -ENOENT;
 	MKSTR(path, "%s/device/uevent", dev_path);
 
 	file = fopen(path, "rb");
@@ -1235,16 +1241,18 @@ mlx5_dev_to_pci_addr(const char *dev_path,
 	}
 	while (fgets(line, sizeof(line), file) == line) {
 		size_t len = strlen(line);
-		int ret;
 
 		/* Truncate long lines. */
-		if (len == (sizeof(line) - 1))
+		if (len == (sizeof(line) - 1)) {
 			while (line[(len - 1)] != '\n') {
-				ret = fgetc(file);
+				int ret = fgetc(file);
 				if (ret == EOF)
-					break;
+					goto exit;
 				line[(len - 1)] = ret;
 			}
+			/* No match for long lines. */
+			continue;
+		}
 		/* Extract information. */
 		if (sscanf(line,
 			   "PCI_SLOT_NAME="
@@ -1253,12 +1261,15 @@ mlx5_dev_to_pci_addr(const char *dev_path,
 			   &pci_addr->bus,
 			   &pci_addr->devid,
 			   &pci_addr->function) == 4) {
-			ret = 0;
+			rc = 0;
 			break;
 		}
 	}
+exit:
 	fclose(file);
-	return 0;
+	if (rc)
+		rte_errno = -rc;
+	return rc;
 }
 
 /**
@@ -1475,249 +1486,6 @@ mlx5_dev_interrupt_handler_devx(void *cb_arg)
 #endif /* HAVE_IBV_DEVX_ASYNC */
 }
 
-/**
- * Uninstall shared asynchronous device events handler.
- * This function is implemented to support event sharing
- * between multiple ports of single IB device.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-static void
-mlx5_dev_shared_handler_uninstall(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_ibv_shared *sh = priv->sh;
-
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return;
-	pthread_mutex_lock(&sh->intr_mutex);
-	assert(priv->ibv_port);
-	assert(priv->ibv_port <= sh->max_port);
-	assert(dev->data->port_id < RTE_MAX_ETHPORTS);
-	if (sh->port[priv->ibv_port - 1].ih_port_id >= RTE_MAX_ETHPORTS)
-		goto exit;
-	assert(sh->port[priv->ibv_port - 1].ih_port_id ==
-					(uint32_t)dev->data->port_id);
-	assert(sh->intr_cnt);
-	sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
-	if (!sh->intr_cnt || --sh->intr_cnt)
-		goto exit;
-	mlx5_intr_callback_unregister(&sh->intr_handle,
-				     mlx5_dev_interrupt_handler, sh);
-	sh->intr_handle.fd = 0;
-	sh->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN;
-exit:
-	pthread_mutex_unlock(&sh->intr_mutex);
-}
-
-/**
- * Uninstall devx shared asynchronous device events handler.
- * This function is implemeted to support event sharing
- * between multiple ports of single IB device.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-static void
-mlx5_dev_shared_handler_devx_uninstall(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_ibv_shared *sh = priv->sh;
-
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return;
-	pthread_mutex_lock(&sh->intr_mutex);
-	assert(priv->ibv_port);
-	assert(priv->ibv_port <= sh->max_port);
-	assert(dev->data->port_id < RTE_MAX_ETHPORTS);
-	if (sh->port[priv->ibv_port - 1].devx_ih_port_id >= RTE_MAX_ETHPORTS)
-		goto exit;
-	assert(sh->port[priv->ibv_port - 1].devx_ih_port_id ==
-					(uint32_t)dev->data->port_id);
-	sh->port[priv->ibv_port - 1].devx_ih_port_id = RTE_MAX_ETHPORTS;
-	if (!sh->devx_intr_cnt || --sh->devx_intr_cnt)
-		goto exit;
-	if (sh->intr_handle_devx.fd) {
-		rte_intr_callback_unregister(&sh->intr_handle_devx,
-					     mlx5_dev_interrupt_handler_devx,
-					     sh);
-		sh->intr_handle_devx.fd = 0;
-		sh->intr_handle_devx.type = RTE_INTR_HANDLE_UNKNOWN;
-	}
-	if (sh->devx_comp) {
-		mlx5_glue->devx_destroy_cmd_comp(sh->devx_comp);
-		sh->devx_comp = NULL;
-	}
-exit:
-	pthread_mutex_unlock(&sh->intr_mutex);
-}
-
-/**
- * Install shared asynchronous device events handler.
- * This function is implemented to support event sharing
- * between multiple ports of single IB device.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-static void
-mlx5_dev_shared_handler_install(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_ibv_shared *sh = priv->sh;
-	int ret;
-	int flags;
-
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return;
-	pthread_mutex_lock(&sh->intr_mutex);
-	assert(priv->ibv_port);
-	assert(priv->ibv_port <= sh->max_port);
-	assert(dev->data->port_id < RTE_MAX_ETHPORTS);
-	if (sh->port[priv->ibv_port - 1].ih_port_id < RTE_MAX_ETHPORTS) {
-		/* The handler is already installed for this port. */
-		assert(sh->intr_cnt);
-		goto exit;
-	}
-	if (sh->intr_cnt) {
-		sh->port[priv->ibv_port - 1].ih_port_id =
-						(uint32_t)dev->data->port_id;
-		sh->intr_cnt++;
-		goto exit;
-	}
-	/* No shared handler installed. */
-	assert(sh->ctx->async_fd > 0);
-	flags = fcntl(sh->ctx->async_fd, F_GETFL);
-	ret = fcntl(sh->ctx->async_fd, F_SETFL, flags | O_NONBLOCK);
-	if (ret) {
-		DRV_LOG(INFO, "failed to change file descriptor async event"
-			" queue");
-		/* Indicate there will be no interrupts. */
-		dev->data->dev_conf.intr_conf.lsc = 0;
-		dev->data->dev_conf.intr_conf.rmv = 0;
-	} else {
-		sh->intr_handle.fd = sh->ctx->async_fd;
-		sh->intr_handle.type = RTE_INTR_HANDLE_EXT;
-		rte_intr_callback_register(&sh->intr_handle,
-					   mlx5_dev_interrupt_handler, sh);
-		sh->intr_cnt++;
-		sh->port[priv->ibv_port - 1].ih_port_id =
-						(uint32_t)dev->data->port_id;
-	}
-exit:
-	pthread_mutex_unlock(&sh->intr_mutex);
-}
-
-/**
- * Install devx shared asyncronous device events handler.
- * This function is implemeted to support event sharing
- * between multiple ports of single IB device.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-static void
-mlx5_dev_shared_handler_devx_install(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_ibv_shared *sh = priv->sh;
-
-	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-		return;
-	pthread_mutex_lock(&sh->intr_mutex);
-	assert(priv->ibv_port);
-	assert(priv->ibv_port <= sh->max_port);
-	assert(dev->data->port_id < RTE_MAX_ETHPORTS);
-	if (sh->port[priv->ibv_port - 1].devx_ih_port_id < RTE_MAX_ETHPORTS) {
-		/* The handler is already installed for this port. */
-		assert(sh->devx_intr_cnt);
-		goto exit;
-	}
-	if (sh->devx_intr_cnt) {
-		sh->devx_intr_cnt++;
-		sh->port[priv->ibv_port - 1].devx_ih_port_id =
-					(uint32_t)dev->data->port_id;
-		goto exit;
-	}
-	if (priv->config.devx) {
-#ifndef HAVE_IBV_DEVX_ASYNC
-		goto exit;
-#else
-		sh->devx_comp = mlx5_glue->devx_create_cmd_comp(sh->ctx);
-		if (sh->devx_comp) {
-			int flags = fcntl(sh->devx_comp->fd, F_GETFL);
-			int ret = fcntl(sh->devx_comp->fd, F_SETFL,
-				    flags | O_NONBLOCK);
-
-			if (ret) {
-				DRV_LOG(INFO, "failed to change file descriptor"
-					" devx async event queue");
-			} else {
-				sh->intr_handle_devx.fd = sh->devx_comp->fd;
-				sh->intr_handle_devx.type = RTE_INTR_HANDLE_EXT;
-				rte_intr_callback_register
-					(&sh->intr_handle_devx,
-					 mlx5_dev_interrupt_handler_devx, sh);
-				sh->devx_intr_cnt++;
-				sh->port[priv->ibv_port - 1].devx_ih_port_id =
-						(uint32_t)dev->data->port_id;
-			}
-		}
-#endif /* HAVE_IBV_DEVX_ASYNC */
-	}
-exit:
-	pthread_mutex_unlock(&sh->intr_mutex);
-}
-
-/**
- * Uninstall interrupt handler.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-void
-mlx5_dev_interrupt_handler_uninstall(struct rte_eth_dev *dev)
-{
-	mlx5_dev_shared_handler_uninstall(dev);
-}
-
-/**
- * Install interrupt handler.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-void
-mlx5_dev_interrupt_handler_install(struct rte_eth_dev *dev)
-{
-	mlx5_dev_shared_handler_install(dev);
-}
-
-/**
- * Devx uninstall interrupt handler.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-void
-mlx5_dev_interrupt_handler_devx_uninstall(struct rte_eth_dev *dev)
-{
-	mlx5_dev_shared_handler_devx_uninstall(dev);
-}
-
-/**
- * Devx install interrupt handler.
- *
- * @param dev
- *   Pointer to Ethernet device.
- */
-void
-mlx5_dev_interrupt_handler_devx_install(struct rte_eth_dev *dev)
-{
-	mlx5_dev_shared_handler_devx_install(dev);
-}
-
 /**
  * DPDK callback to bring the link DOWN.
  *
@@ -2189,12 +1957,13 @@ int mlx5_get_module_eeprom(struct rte_eth_dev *dev,
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
-int mlx5_hairpin_cap_get(struct rte_eth_dev *dev,
-			 struct rte_eth_hairpin_cap *cap)
+int
+mlx5_hairpin_cap_get(struct rte_eth_dev *dev, struct rte_eth_hairpin_cap *cap)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_dev_config *config = &priv->config;
 
-	if (priv->sh->devx == 0) {
+	if (!priv->sh->devx || !config->dest_tir || !config->dv_flow_en) {
 		rte_errno = ENOTSUP;
 		return -rte_errno;
 	}
diff --git a/dpdk/drivers/net/mlx5/mlx5_flow.c b/dpdk/drivers/net/mlx5/mlx5_flow.c
index 008716367c..74f17d3710 100644
--- a/dpdk/drivers/net/mlx5/mlx5_flow.c
+++ b/dpdk/drivers/net/mlx5/mlx5_flow.c
@@ -165,7 +165,9 @@ static const struct rte_flow_expand_node mlx5_support_expansion[] = {
 		.rss_types = ETH_RSS_NONFRAG_IPV6_TCP,
 	},
 	[MLX5_EXPANSION_VXLAN] = {
-		.next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH),
+		.next = RTE_FLOW_EXPAND_RSS_NEXT(MLX5_EXPANSION_ETH,
+						 MLX5_EXPANSION_IPV4,
+						 MLX5_EXPANSION_IPV6),
 		.type = RTE_FLOW_ITEM_TYPE_VXLAN,
 	},
 	[MLX5_EXPANSION_VXLAN_GPE] = {
@@ -336,7 +338,7 @@ static struct mlx5_flow_tunnel_info tunnels_info[] = {
  *   The request register on success, a negative errno
  *   value otherwise and rte_errno is set.
  */
-enum modify_reg
+int
 mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 		     enum mlx5_feature_name feature,
 		     uint32_t id,
@@ -345,6 +347,7 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_dev_config *config = &priv->config;
 	enum modify_reg start_reg;
+	bool skip_mtr_reg = false;
 
 	switch (feature) {
 	case MLX5_HAIRPIN_RX:
@@ -383,30 +386,37 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 			return REG_C_0;
 		}
 		break;
-	case MLX5_COPY_MARK:
 	case MLX5_MTR_SFX:
 		/*
-		 * Metadata COPY_MARK register using is in meter suffix sub
-		 * flow while with meter. It's safe to share the same register.
+		 * If meter color and flow match share one register, flow match
+		 * should use the meter color register for match.
 		 */
-		return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3;
+		if (priv->mtr_reg_share)
+			return priv->mtr_color_reg;
+		else
+			return priv->mtr_color_reg != REG_C_2 ? REG_C_2 :
+			       REG_C_3;
 	case MLX5_MTR_COLOR:
 		RTE_ASSERT(priv->mtr_color_reg != REG_NONE);
 		return priv->mtr_color_reg;
+	case MLX5_COPY_MARK:
+		/*
+		 * Metadata COPY_MARK register using is in meter suffix sub
+		 * flow while with meter. It's safe to share the same register.
+		 */
+		return priv->mtr_color_reg != REG_C_2 ? REG_C_2 : REG_C_3;
 	case MLX5_APP_TAG:
 		/*
-		 * If meter is enable, it will engage two registers for color
+		 * If meter is enable, it will engage the register for color
 		 * match and flow match. If meter color match is not using the
 		 * REG_C_2, need to skip the REG_C_x be used by meter color
 		 * match.
 		 * If meter is disable, free to use all available registers.
 		 */
-		if (priv->mtr_color_reg != REG_NONE)
-			start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_3 :
-				    REG_C_4;
-		else
-			start_reg = REG_C_2;
-		if (id > (REG_C_7 - start_reg))
+		start_reg = priv->mtr_color_reg != REG_C_2 ? REG_C_2 :
+			    (priv->mtr_reg_share ? REG_C_3 : REG_C_4);
+		skip_mtr_reg = !!(priv->mtr_en && start_reg == REG_C_2);
+		if (id > (uint32_t)(REG_C_7 - start_reg))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "invalid tag id");
@@ -420,12 +430,16 @@ mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 		 * If the available index REG_C_y >= REG_C_x, skip the
 		 * color register.
 		 */
-		if (start_reg == REG_C_3 && config->flow_mreg_c
-		    [id + REG_C_3 - REG_C_0] >= priv->mtr_color_reg) {
-			if (config->flow_mreg_c[id + 1 + REG_C_3 - REG_C_0] !=
-			    REG_NONE)
+		if (skip_mtr_reg && config->flow_mreg_c
+		    [id + start_reg - REG_C_0] >= priv->mtr_color_reg) {
+			if (id >= (uint32_t)(REG_C_7 - start_reg))
+				return rte_flow_error_set(error, EINVAL,
+						       RTE_FLOW_ERROR_TYPE_ITEM,
+							NULL, "invalid tag id");
+			if (config->flow_mreg_c
+			    [id + 1 + start_reg - REG_C_0] != REG_NONE)
 				return config->flow_mreg_c
-						[id + 1 + REG_C_3 - REG_C_0];
+					       [id + 1 + start_reg - REG_C_0];
 			return rte_flow_error_set(error, ENOTSUP,
 						  RTE_FLOW_ERROR_TYPE_ITEM,
 						  NULL, "unsupported tag id");
@@ -859,6 +873,35 @@ flow_rxq_flags_clear(struct rte_eth_dev *dev)
 	}
 }
 
+/**
+ * Set the Rx queue dynamic metadata (mask and offset) for a flow
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ */
+void
+mlx5_flow_rxq_dynf_metadata_set(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_rxq_data *data;
+	unsigned int i;
+
+	for (i = 0; i != priv->rxqs_n; ++i) {
+		if (!(*priv->rxqs)[i])
+			continue;
+		data = (*priv->rxqs)[i];
+		if (!rte_flow_dynf_metadata_avail()) {
+			data->dynf_meta = 0;
+			data->flow_meta_mask = 0;
+			data->flow_meta_offset = -1;
+		} else {
+			data->dynf_meta = 1;
+			data->flow_meta_mask = rte_flow_dynf_metadata_mask;
+			data->flow_meta_offset = rte_flow_dynf_metadata_offs;
+		}
+	}
+}
+
 /*
  * return a pointer to the desired action in the list of actions.
  *
@@ -900,11 +943,6 @@ mlx5_flow_validate_action_flag(uint64_t action_flags,
 			       const struct rte_flow_attr *attr,
 			       struct rte_flow_error *error)
 {
-
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and flag in same flow");
 	if (action_flags & MLX5_FLOW_ACTION_MARK)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -956,10 +994,6 @@ mlx5_flow_validate_action_mark(const struct rte_flow_action *action,
 					  &mark->id,
 					  "mark id must in 0 <= id < "
 					  RTE_STR(MLX5_FLOW_MARK_MAX));
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and mark in same flow");
 	if (action_flags & MLX5_FLOW_ACTION_FLAG)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -991,24 +1025,10 @@ mlx5_flow_validate_action_mark(const struct rte_flow_action *action,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_flow_validate_action_drop(uint64_t action_flags,
+mlx5_flow_validate_action_drop(uint64_t action_flags __rte_unused,
 			       const struct rte_flow_attr *attr,
 			       struct rte_flow_error *error)
 {
-	if (action_flags & MLX5_FLOW_ACTION_FLAG)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and flag in same flow");
-	if (action_flags & MLX5_FLOW_ACTION_MARK)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and mark in same flow");
-	if (action_flags & (MLX5_FLOW_FATE_ACTIONS |
-			    MLX5_FLOW_FATE_ESWITCH_ACTIONS))
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't have 2 fate actions in"
-					  " same flow");
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
@@ -1101,6 +1121,7 @@ mlx5_flow_validate_action_rss(const struct rte_flow_action *action,
 	struct mlx5_priv *priv = dev->data->dev_private;
 	const struct rte_flow_action_rss *rss = action->conf;
 	int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	enum mlx5_rxq_type rxq_type = MLX5_RXQ_TYPE_UNDEFINED;
 	unsigned int i;
 
 	if (action_flags & MLX5_FLOW_FATE_ACTIONS)
@@ -1159,6 +1180,8 @@ mlx5_flow_validate_action_rss(const struct rte_flow_action *action,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  NULL, "No queues configured");
 	for (i = 0; i != rss->queue_num; ++i) {
+		struct mlx5_rxq_ctrl *rxq_ctrl;
+
 		if (rss->queue[i] >= priv->rxqs_n)
 			return rte_flow_error_set
 				(error, EINVAL,
@@ -1168,6 +1191,15 @@ mlx5_flow_validate_action_rss(const struct rte_flow_action *action,
 			return rte_flow_error_set
 				(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 				 &rss->queue[i], "queue is not configured");
+		rxq_ctrl = container_of((*priv->rxqs)[rss->queue[i]],
+					struct mlx5_rxq_ctrl, rxq);
+		if (i == 0)
+			rxq_type = rxq_ctrl->type;
+		if (rxq_type != rxq_ctrl->type)
+			return rte_flow_error_set
+				(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+				 &rss->queue[i],
+				 "combining hairpin and regular RSS queues is not supported");
 	}
 	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
@@ -1634,7 +1666,6 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item,
 				"\xff\xff\xff\xff\xff\xff\xff\xff",
 			.vtc_flow = RTE_BE32(0xffffffff),
 			.proto = 0xff,
-			.hop_limits = 0xff,
 		},
 	};
 	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
@@ -1831,7 +1862,6 @@ mlx5_flow_validate_item_vxlan(const struct rte_flow_item *item,
 		uint32_t vlan_id;
 		uint8_t vni[4];
 	} id = { .vlan_id = 0, };
-	uint32_t vlan_id = 0;
 
 
 	if (item_flags & MLX5_FLOW_LAYER_TUNNEL)
@@ -1858,23 +1888,8 @@ mlx5_flow_validate_item_vxlan(const struct rte_flow_item *item,
 		return ret;
 	if (spec) {
 		memcpy(&id.vni[1], spec->vni, 3);
-		vlan_id = id.vlan_id;
 		memcpy(&id.vni[1], mask->vni, 3);
-		vlan_id &= id.vlan_id;
 	}
-	/*
-	 * Tunnel id 0 is equivalent as not adding a VXLAN layer, if
-	 * only this layer is defined in the Verbs specification it is
-	 * interpreted as wildcard and all packets will match this
-	 * rule, if it follows a full stack layer (ex: eth / ipv4 /
-	 * udp), all packets matching the layers before will also
-	 * match this rule.  To avoid such situation, VNI 0 is
-	 * currently refused.
-	 */
-	if (!vlan_id)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
-					  "VXLAN vni cannot be 0");
 	if (!(item_flags & MLX5_FLOW_LAYER_OUTER))
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -1913,7 +1928,6 @@ mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item,
 		uint32_t vlan_id;
 		uint8_t vni[4];
 	} id = { .vlan_id = 0, };
-	uint32_t vlan_id = 0;
 
 	if (!priv->config.l3_vxlan_en)
 		return rte_flow_error_set(error, ENOTSUP,
@@ -1951,22 +1965,8 @@ mlx5_flow_validate_item_vxlan_gpe(const struct rte_flow_item *item,
 						  "VxLAN-GPE protocol"
 						  " not supported");
 		memcpy(&id.vni[1], spec->vni, 3);
-		vlan_id = id.vlan_id;
 		memcpy(&id.vni[1], mask->vni, 3);
-		vlan_id &= id.vlan_id;
 	}
-	/*
-	 * Tunnel id 0 is equivalent as not adding a VXLAN layer, if only this
-	 * layer is defined in the Verbs specification it is interpreted as
-	 * wildcard and all packets will match this rule, if it follows a full
-	 * stack layer (ex: eth / ipv4 / udp), all packets matching the layers
-	 * before will also match this rule.  To avoid such situation, VNI 0
-	 * is currently refused.
-	 */
-	if (!vlan_id)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ITEM, item,
-					  "VXLAN-GPE vni cannot be 0");
 	if (!(item_flags & MLX5_FLOW_LAYER_OUTER))
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
@@ -2131,9 +2131,7 @@ mlx5_flow_validate_item_geneve(const struct rte_flow_item *item,
 		.protocol = RTE_BE16(UINT16_MAX),
 	};
 
-	if (!(priv->config.hca_attr.flex_parser_protocols &
-	      MLX5_HCA_FLEX_GENEVE_ENABLED) ||
-	    !priv->config.hca_attr.tunnel_stateless_geneve_rx)
+	if (!priv->config.hca_attr.tunnel_stateless_geneve_rx)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
 					  "L3 Geneve is not enabled by device"
@@ -2223,7 +2221,8 @@ mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev __rte_unused,
 	/* MPLS over IP, UDP, GRE is allowed */
 	if (!(prev_layer & (MLX5_FLOW_LAYER_OUTER_L3 |
 			    MLX5_FLOW_LAYER_OUTER_L4_UDP |
-			    MLX5_FLOW_LAYER_GRE)))
+			    MLX5_FLOW_LAYER_GRE |
+			    MLX5_FLOW_LAYER_GRE_KEY)))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
 					  "protocol filtering not compatible"
@@ -2244,11 +2243,12 @@ mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev __rte_unused,
 	if (ret < 0)
 		return ret;
 	return 0;
-#endif
+#else
 	return rte_flow_error_set(error, ENOTSUP,
 				  RTE_FLOW_ERROR_TYPE_ITEM, item,
 				  "MPLS is not supported by Verbs, please"
 				  " update.");
+#endif
 }
 
 /**
@@ -2349,6 +2349,7 @@ flow_null_validate(struct rte_eth_dev *dev __rte_unused,
 		   const struct rte_flow_item items[] __rte_unused,
 		   const struct rte_flow_action actions[] __rte_unused,
 		   bool external __rte_unused,
+		   int hairpin __rte_unused,
 		   struct rte_flow_error *error)
 {
 	return rte_flow_error_set(error, ENOTSUP,
@@ -2463,6 +2464,8 @@ flow_get_drv_type(struct rte_eth_dev *dev, const struct rte_flow_attr *attr)
  *   Pointer to the list of actions.
  * @param[in] external
  *   This flow rule is created by request external to PMD.
+ * @param[in] hairpin
+ *   Number of hairpin TX actions, 0 means classic flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -2474,13 +2477,14 @@ flow_drv_validate(struct rte_eth_dev *dev,
 		  const struct rte_flow_attr *attr,
 		  const struct rte_flow_item items[],
 		  const struct rte_flow_action actions[],
-		  bool external, struct rte_flow_error *error)
+		  bool external, int hairpin, struct rte_flow_error *error)
 {
 	const struct mlx5_flow_driver_ops *fops;
 	enum mlx5_flow_drv_type type = flow_get_drv_type(dev, attr);
 
 	fops = flow_get_drv_ops(type);
-	return fops->validate(dev, attr, items, actions, external, error);
+	return fops->validate(dev, attr, items, actions, external,
+			      hairpin, error);
 }
 
 /**
@@ -2638,47 +2642,6 @@ flow_drv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
 	fops->destroy(dev, flow);
 }
 
-/**
- * Validate a flow supported by the NIC.
- *
- * @see rte_flow_validate()
- * @see rte_flow_ops
- */
-int
-mlx5_flow_validate(struct rte_eth_dev *dev,
-		   const struct rte_flow_attr *attr,
-		   const struct rte_flow_item items[],
-		   const struct rte_flow_action actions[],
-		   struct rte_flow_error *error)
-{
-	int ret;
-
-	ret = flow_drv_validate(dev, attr, items, actions, true, error);
-	if (ret < 0)
-		return ret;
-	return 0;
-}
-
-/**
- * Get port id item from the item list.
- *
- * @param[in] item
- *   Pointer to the list of items.
- *
- * @return
- *   Pointer to the port id item if exist, else return NULL.
- */
-static const struct rte_flow_item *
-find_port_id_item(const struct rte_flow_item *item)
-{
-	assert(item);
-	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-		if (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID)
-			return item;
-	}
-	return NULL;
-}
-
 /**
  * Get RSS action from the action list.
  *
@@ -2723,7 +2686,44 @@ find_graph_root(const struct rte_flow_item pattern[], uint32_t rss_level)
 }
 
 /**
- * Get QUEUE/RSS action from the action list.
+ *  Get layer flags from the prefix flow.
+ *
+ *  Some flows may be split to several subflows, the prefix subflow gets the
+ *  match items and the suffix sub flow gets the actions.
+ *  Some actions need the user defined match item flags to get the detail for
+ *  the action.
+ *  This function helps the suffix flow to get the item layer flags from prefix
+ *  subflow.
+ *
+ * @param[in] dev_flow
+ *   Pointer the created preifx subflow.
+ *
+ * @return
+ *   The layers get from prefix subflow.
+ */
+static inline uint64_t
+flow_get_prefix_layer_flags(struct mlx5_flow *dev_flow)
+{
+	uint64_t layers = 0;
+
+	/* If no decap actions, use the layers directly. */
+	if (!(dev_flow->actions & MLX5_FLOW_ACTION_DECAP))
+		return dev_flow->layers;
+	/* Convert L3 layers with decap action. */
+	if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L3_IPV4)
+		layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV4;
+	else if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L3_IPV6)
+		layers |= MLX5_FLOW_LAYER_OUTER_L3_IPV6;
+	/* Convert L4 layers with decap action.  */
+	if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L4_TCP)
+		layers |= MLX5_FLOW_LAYER_OUTER_L4_TCP;
+	else if (dev_flow->layers & MLX5_FLOW_LAYER_INNER_L4_UDP)
+		layers |= MLX5_FLOW_LAYER_OUTER_L4_UDP;
+	return layers;
+}
+
+/**
+ * Get metadata split action information.
  *
  * @param[in] actions
  *   Pointer to the list of actions.
@@ -2732,18 +2732,38 @@ find_graph_root(const struct rte_flow_item pattern[], uint32_t rss_level)
  * @param[out] qrss_type
  *   Pointer to the action type to return. RTE_FLOW_ACTION_TYPE_END is returned
  *   if no QUEUE/RSS is found.
+ * @param[out] encap_idx
+ *   Pointer to the index of the encap action if exists, otherwise the last
+ *   action index.
  *
  * @return
  *   Total number of actions.
  */
 static int
-flow_parse_qrss_action(const struct rte_flow_action actions[],
-		       const struct rte_flow_action **qrss)
+flow_parse_metadata_split_actions_info(const struct rte_flow_action actions[],
+				       const struct rte_flow_action **qrss,
+				       int *encap_idx)
 {
+	const struct rte_flow_action_raw_encap *raw_encap;
 	int actions_n = 0;
+	int raw_decap_idx = -1;
 
+	*encap_idx = -1;
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
 		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+			*encap_idx = actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			raw_decap_idx = actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			raw_encap = actions->conf;
+			if (raw_encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
+				*encap_idx = raw_decap_idx != -1 ?
+						      raw_decap_idx : actions_n;
+			break;
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			*qrss = actions;
@@ -2753,6 +2773,8 @@ flow_parse_qrss_action(const struct rte_flow_action actions[],
 		}
 		actions_n++;
 	}
+	if (*encap_idx == -1)
+		*encap_idx = actions_n;
 	/* Count RTE_FLOW_ACTION_TYPE_END. */
 	return actions_n + 1;
 }
@@ -2790,10 +2812,10 @@ flow_check_meter_action(const struct rte_flow_action actions[], uint32_t *mtr)
 }
 
 /**
- * Check if the flow should be splited due to hairpin.
+ * Check if the flow should be split due to hairpin.
  * The reason for the split is that in current HW we can't
- * support encap on Rx, so if a flow have encap we move it
- * to Tx.
+ * support encap and push-vlan on Rx, so if a flow contains
+ * these actions we move it to Tx.
  *
  * @param dev
  *   Pointer to Ethernet device.
@@ -2813,7 +2835,7 @@ flow_check_hairpin_split(struct rte_eth_dev *dev,
 {
 	int queue_action = 0;
 	int action_n = 0;
-	int encap = 0;
+	int split = 0;
 	const struct rte_flow_action_queue *queue;
 	const struct rte_flow_action_rss *rss;
 	const struct rte_flow_action_raw_encap *raw_encap;
@@ -2844,7 +2866,10 @@ flow_check_hairpin_split(struct rte_eth_dev *dev,
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
-			encap = 1;
+		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+			split++;
 			action_n++;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
@@ -2852,7 +2877,7 @@ flow_check_hairpin_split(struct rte_eth_dev *dev,
 			if (raw_encap->size >
 			    (sizeof(struct rte_flow_item_eth) +
 			     sizeof(struct rte_flow_item_ipv4)))
-				encap = 1;
+				split++;
 			action_n++;
 			break;
 		default:
@@ -2860,7 +2885,7 @@ flow_check_hairpin_split(struct rte_eth_dev *dev,
 			break;
 		}
 	}
-	if (encap == 1 && queue_action)
+	if (split && queue_action)
 		return action_n;
 	return 0;
 }
@@ -2922,7 +2947,7 @@ flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id,
 	};
 	struct mlx5_flow_action_copy_mreg cp_mreg = {
 		.dst = REG_B,
-		.src = 0,
+		.src = REG_NONE,
 	};
 	struct rte_flow_action_jump jump = {
 		.group = MLX5_FLOW_MREG_ACT_TABLE_GROUP,
@@ -2958,18 +2983,21 @@ flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id,
 	/* Build a new flow. */
 	if (mark_id != MLX5_DEFAULT_COPY_ID) {
 		items[0] = (struct rte_flow_item){
-			.type = MLX5_RTE_FLOW_ITEM_TYPE_TAG,
+			.type = (enum rte_flow_item_type)
+				MLX5_RTE_FLOW_ITEM_TYPE_TAG,
 			.spec = &tag_spec,
 		};
 		items[1] = (struct rte_flow_item){
 			.type = RTE_FLOW_ITEM_TYPE_END,
 		};
 		actions[0] = (struct rte_flow_action){
-			.type = MLX5_RTE_FLOW_ACTION_TYPE_MARK,
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_MARK,
 			.conf = &ftag,
 		};
 		actions[1] = (struct rte_flow_action){
-			.type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
 			.conf = &cp_mreg,
 		};
 		actions[2] = (struct rte_flow_action){
@@ -2986,7 +3014,8 @@ flow_mreg_add_copy_action(struct rte_eth_dev *dev, uint32_t mark_id,
 			.type = RTE_FLOW_ITEM_TYPE_END,
 		};
 		actions[0] = (struct rte_flow_action){
-			.type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
 			.conf = &cp_mreg,
 		};
 		actions[1] = (struct rte_flow_action){
@@ -3263,7 +3292,8 @@ flow_mreg_update_copy_table(struct rte_eth_dev *dev,
 
 /**
  * Split the hairpin flow.
- * Since HW can't support encap on Rx we move the encap to Tx.
+ * Since HW can't support encap and push-vlan on Rx, we move these
+ * actions to Tx.
  * If the count action is after the encap then we also
  * move the count action. in this case the count will also measure
  * the outer bytes.
@@ -3307,6 +3337,9 @@ flow_hairpin_split(struct rte_eth_dev *dev,
 		switch (actions->type) {
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
 			rte_memcpy(actions_tx, actions,
 			       sizeof(struct rte_flow_action));
 			actions_tx++;
@@ -3360,7 +3393,8 @@ flow_hairpin_split(struct rte_eth_dev *dev,
 	}
 	/* Add set meta action and end action for the Rx flow. */
 	tag_action = actions_rx;
-	tag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG;
+	tag_action->type = (enum rte_flow_action_type)
+			   MLX5_RTE_FLOW_ACTION_TYPE_TAG;
 	actions_rx++;
 	rte_memcpy(actions_rx, actions, sizeof(struct rte_flow_action));
 	actions_rx++;
@@ -3373,7 +3407,8 @@ flow_hairpin_split(struct rte_eth_dev *dev,
 	rte_memcpy(actions_tx, actions, sizeof(struct rte_flow_action));
 	addr = (void *)&pattern_tx[2];
 	item = pattern_tx;
-	item->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG;
+	item->type = (enum rte_flow_item_type)
+		     MLX5_RTE_FLOW_ITEM_TYPE_TAG;
 	tag_item = (void *)addr;
 	tag_item->data = *flow_id;
 	tag_item->id = mlx5_flow_get_reg_id(dev, MLX5_HAIRPIN_TX, 0, NULL);
@@ -3384,7 +3419,6 @@ flow_hairpin_split(struct rte_eth_dev *dev,
 	tag_item->data = UINT32_MAX;
 	tag_item->id = UINT16_MAX;
 	item->mask = tag_item;
-	addr += sizeof(struct mlx5_rte_flow_item_tag);
 	item->last = NULL;
 	item++;
 	item->type = RTE_FLOW_ITEM_TYPE_END;
@@ -3401,6 +3435,8 @@ flow_hairpin_split(struct rte_eth_dev *dev,
  *   Parent flow structure pointer.
  * @param[in, out] sub_flow
  *   Pointer to return the created subflow, may be NULL.
+ * @param[in] prefix_layers
+ *   Prefix subflow layers, may be 0.
  * @param[in] attr
  *   Flow rule attributes.
  * @param[in] items
@@ -3418,6 +3454,7 @@ static int
 flow_create_split_inner(struct rte_eth_dev *dev,
 			struct rte_flow *flow,
 			struct mlx5_flow **sub_flow,
+			uint64_t prefix_layers,
 			const struct rte_flow_attr *attr,
 			const struct rte_flow_item items[],
 			const struct rte_flow_action actions[],
@@ -3432,6 +3469,12 @@ flow_create_split_inner(struct rte_eth_dev *dev,
 	dev_flow->external = external;
 	/* Subflow object was created, we must include one in the list. */
 	LIST_INSERT_HEAD(&flow->dev_flows, dev_flow, next);
+	/*
+	 * If dev_flow is as one of the suffix flow, some actions in suffix
+	 * flow may need some user defined item layer flags.
+	 */
+	if (prefix_layers)
+		dev_flow->layers = prefix_layers;
 	if (sub_flow)
 		*sub_flow = dev_flow;
 	return flow_drv_translate(dev, dev_flow, attr, items, actions, error);
@@ -3451,6 +3494,10 @@ flow_create_split_inner(struct rte_eth_dev *dev,
  *
  * @param dev
  *   Pointer to Ethernet device.
+ * @param[in] items
+ *   Pattern specification (list terminated by the END pattern item).
+ * @param[out] sfx_items
+ *   Suffix flow match items (list terminated by the END pattern item).
  * @param[in] actions
  *   Associated actions (list terminated by the END action).
  * @param[out] actions_sfx
@@ -3467,66 +3514,61 @@ flow_create_split_inner(struct rte_eth_dev *dev,
  */
 static int
 flow_meter_split_prep(struct rte_eth_dev *dev,
+		 const struct rte_flow_item items[],
+		 struct rte_flow_item sfx_items[],
 		 const struct rte_flow_action actions[],
 		 struct rte_flow_action actions_sfx[],
 		 struct rte_flow_action actions_pre[])
 {
-	struct rte_flow_action *tag_action;
+	struct rte_flow_action *tag_action = NULL;
+	struct rte_flow_item *tag_item;
 	struct mlx5_rte_flow_action_set_tag *set_tag;
 	struct rte_flow_error error;
 	const struct rte_flow_action_raw_encap *raw_encap;
 	const struct rte_flow_action_raw_decap *raw_decap;
+	struct mlx5_rte_flow_item_tag *tag_spec;
+	struct mlx5_rte_flow_item_tag *tag_mask;
 	uint32_t tag_id;
+	bool copy_vlan = false;
 
-	/* Add the extra tag action first. */
-	tag_action = actions_pre;
-	tag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG;
-	actions_pre++;
 	/* Prepare the actions for prefix and suffix flow. */
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		struct rte_flow_action **action_cur = NULL;
+
 		switch (actions->type) {
 		case RTE_FLOW_ACTION_TYPE_METER:
+			/* Add the extra tag action first. */
+			tag_action = actions_pre;
+			tag_action->type = (enum rte_flow_action_type)
+					   MLX5_RTE_FLOW_ACTION_TYPE_TAG;
+			actions_pre++;
+			action_cur = &actions_pre;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
-			memcpy(actions_pre, actions,
-			       sizeof(struct rte_flow_action));
-			actions_pre++;
+			action_cur = &actions_pre;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
 			raw_encap = actions->conf;
-			if (raw_encap->size >
-			    (sizeof(struct rte_flow_item_eth) +
-			     sizeof(struct rte_flow_item_ipv4))) {
-				memcpy(actions_sfx, actions,
-				       sizeof(struct rte_flow_action));
-				actions_sfx++;
-			} else {
-				rte_memcpy(actions_pre, actions,
-					   sizeof(struct rte_flow_action));
-				actions_pre++;
-			}
+			if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE)
+				action_cur = &actions_pre;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
 			raw_decap = actions->conf;
-			/* Size 0 decap means 50 bytes as vxlan decap. */
-			if (raw_decap->size && (raw_decap->size <
-			    (sizeof(struct rte_flow_item_eth) +
-			     sizeof(struct rte_flow_item_ipv4)))) {
-				memcpy(actions_sfx, actions,
-				       sizeof(struct rte_flow_action));
-				actions_sfx++;
-			} else {
-				rte_memcpy(actions_pre, actions,
-					   sizeof(struct rte_flow_action));
-				actions_pre++;
-			}
+			if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
+				action_cur = &actions_pre;
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+			copy_vlan = true;
 			break;
 		default:
-			memcpy(actions_sfx, actions,
-				sizeof(struct rte_flow_action));
-			actions_sfx++;
 			break;
 		}
+		if (!action_cur)
+			action_cur = &actions_sfx;
+		memcpy(*action_cur, actions, sizeof(struct rte_flow_action));
+		(*action_cur)++;
 	}
 	/* Add end action to the actions. */
 	actions_sfx->type = RTE_FLOW_ACTION_TYPE_END;
@@ -3539,8 +3581,47 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
 	 * Get the id from the qrss_pool to make qrss share the id with meter.
 	 */
 	tag_id = flow_qrss_get_id(dev);
-	set_tag->data = rte_cpu_to_be_32(tag_id);
+	set_tag->data = tag_id << MLX5_MTR_COLOR_BITS;
+	assert(tag_action);
 	tag_action->conf = set_tag;
+	/* Prepare the suffix subflow items. */
+	tag_item = sfx_items++;
+	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
+		int item_type = items->type;
+
+		switch (item_type) {
+		case RTE_FLOW_ITEM_TYPE_PORT_ID:
+			memcpy(sfx_items, items, sizeof(*sfx_items));
+			sfx_items++;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VLAN:
+			if (copy_vlan) {
+				memcpy(sfx_items, items, sizeof(*sfx_items));
+				/*
+				 * Convert to internal match item, it is used
+				 * for vlan push and set vid.
+				 */
+				sfx_items->type = (enum rte_flow_item_type)
+						  MLX5_RTE_FLOW_ITEM_TYPE_VLAN;
+				sfx_items++;
+			}
+			break;
+		default:
+			break;
+		}
+	}
+	sfx_items->type = RTE_FLOW_ITEM_TYPE_END;
+	sfx_items++;
+	tag_spec = (struct mlx5_rte_flow_item_tag *)sfx_items;
+	tag_spec->data = tag_id << MLX5_MTR_COLOR_BITS;
+	tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error);
+	tag_mask = tag_spec + 1;
+	tag_mask->data = 0xffffff00;
+	tag_item->type = (enum rte_flow_item_type)
+			 MLX5_RTE_FLOW_ITEM_TYPE_TAG;
+	tag_item->spec = tag_spec;
+	tag_item->last = NULL;
+	tag_item->mask = tag_mask;
 	return tag_id;
 }
 
@@ -3640,7 +3721,8 @@ flow_mreg_split_qrss_prep(struct rte_eth_dev *dev,
 		/* Construct new actions array. */
 		/* Replace QUEUE/RSS action. */
 		split_actions[qrss_idx] = (struct rte_flow_action){
-			.type = MLX5_RTE_FLOW_ACTION_TYPE_TAG,
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_TAG,
 			.conf = set_tag,
 		};
 	}
@@ -3673,6 +3755,8 @@ flow_mreg_split_qrss_prep(struct rte_eth_dev *dev,
  *   Number of actions in the list.
  * @param[out] error
  *   Perform verbose error reporting if not NULL.
+ * @param[in] encap_idx
+ *   The encap action inndex.
  *
  * @return
  *   0 on success, negative value otherwise
@@ -3681,7 +3765,8 @@ static int
 flow_mreg_tx_copy_prep(struct rte_eth_dev *dev,
 		       struct rte_flow_action *ext_actions,
 		       const struct rte_flow_action *actions,
-		       int actions_n, struct rte_flow_error *error)
+		       int actions_n, struct rte_flow_error *error,
+		       int encap_idx)
 {
 	struct mlx5_flow_action_copy_mreg *cp_mreg =
 		(struct mlx5_flow_action_copy_mreg *)
@@ -3696,15 +3781,26 @@ flow_mreg_tx_copy_prep(struct rte_eth_dev *dev,
 	if (ret < 0)
 		return ret;
 	cp_mreg->src = ret;
-	memcpy(ext_actions, actions,
-			sizeof(*ext_actions) * actions_n);
-	ext_actions[actions_n - 1] = (struct rte_flow_action){
-		.type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
-		.conf = cp_mreg,
-	};
-	ext_actions[actions_n] = (struct rte_flow_action){
-		.type = RTE_FLOW_ACTION_TYPE_END,
-	};
+	if (encap_idx != 0)
+		memcpy(ext_actions, actions, sizeof(*ext_actions) * encap_idx);
+	if (encap_idx == actions_n - 1) {
+		ext_actions[actions_n - 1] = (struct rte_flow_action){
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
+			.conf = cp_mreg,
+		};
+		ext_actions[actions_n] = (struct rte_flow_action){
+			.type = RTE_FLOW_ACTION_TYPE_END,
+		};
+	} else {
+		ext_actions[encap_idx] = (struct rte_flow_action){
+			.type = (enum rte_flow_action_type)
+				MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
+			.conf = cp_mreg,
+		};
+		memcpy(ext_actions + encap_idx + 1, actions + encap_idx,
+				sizeof(*ext_actions) * (actions_n - encap_idx));
+	}
 	return 0;
 }
 
@@ -3722,6 +3818,8 @@ flow_mreg_tx_copy_prep(struct rte_eth_dev *dev,
  *   Pointer to Ethernet device.
  * @param[in] flow
  *   Parent flow structure pointer.
+ * @param[in] prefix_layers
+ *   Prefix flow layer flags.
  * @param[in] attr
  *   Flow rule attributes.
  * @param[in] items
@@ -3738,6 +3836,7 @@ flow_mreg_tx_copy_prep(struct rte_eth_dev *dev,
 static int
 flow_create_split_metadata(struct rte_eth_dev *dev,
 			   struct rte_flow *flow,
+			   uint64_t prefix_layers,
 			   const struct rte_flow_attr *attr,
 			   const struct rte_flow_item items[],
 			   const struct rte_flow_action actions[],
@@ -3752,15 +3851,18 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 	int mtr_sfx = 0;
 	size_t act_size;
 	int actions_n;
+	int encap_idx;
 	int ret;
 
 	/* Check whether extensive metadata feature is engaged. */
 	if (!config->dv_flow_en ||
 	    config->dv_xmeta_en == MLX5_XMETA_MODE_LEGACY ||
 	    !mlx5_flow_ext_mreg_supported(dev))
-		return flow_create_split_inner(dev, flow, NULL, attr, items,
-					       actions, external, error);
-	actions_n = flow_parse_qrss_action(actions, &qrss);
+		return flow_create_split_inner(dev, flow, NULL, prefix_layers,
+					       attr, items, actions, external,
+					       error);
+	actions_n = flow_parse_metadata_split_actions_info(actions, &qrss,
+							   &encap_idx);
 	if (qrss) {
 		/* Exclude hairpin flows from splitting. */
 		if (qrss->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
@@ -3807,6 +3909,7 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 						RTE_FLOW_ACTION_TYPE_VOID;
 		else
 			ext_actions[qrss - actions].type =
+						(enum rte_flow_action_type)
 						MLX5_RTE_FLOW_ACTION_TYPE_TAG;
 		/*
 		 * Create the new actions list with removed Q/RSS action
@@ -3835,14 +3938,14 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 						  "metadata flow");
 		/* Create the action list appended with copy register. */
 		ret = flow_mreg_tx_copy_prep(dev, ext_actions, actions,
-					     actions_n, error);
+					     actions_n, error, encap_idx);
 		if (ret < 0)
 			goto exit;
 	}
 	/* Add the unmodified original or prefix subflow. */
-	ret = flow_create_split_inner(dev, flow, &dev_flow, attr, items,
-				      ext_actions ? ext_actions : actions,
-				      external, error);
+	ret = flow_create_split_inner(dev, flow, &dev_flow, prefix_layers, attr,
+				      items, ext_actions ? ext_actions :
+				      actions, external, error);
 	if (ret < 0)
 		goto exit;
 	assert(dev_flow);
@@ -3854,11 +3957,12 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 		/* Internal PMD action to set register. */
 		struct mlx5_rte_flow_item_tag q_tag_spec = {
 			.data = qrss_id,
-			.id = 0,
+			.id = REG_NONE,
 		};
 		struct rte_flow_item q_items[] = {
 			{
-				.type = MLX5_RTE_FLOW_ITEM_TYPE_TAG,
+				.type = (enum rte_flow_item_type)
+					MLX5_RTE_FLOW_ITEM_TYPE_TAG,
 				.spec = &q_tag_spec,
 				.last = NULL,
 				.mask = NULL,
@@ -3876,7 +3980,7 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 				.type = RTE_FLOW_ACTION_TYPE_END,
 			},
 		};
-		uint64_t hash_fields = dev_flow->hash_fields;
+		uint64_t layers = flow_get_prefix_layer_flags(dev_flow);
 
 		/*
 		 * Configure the tag item only if there is no meter subflow.
@@ -3903,14 +4007,13 @@ flow_create_split_metadata(struct rte_eth_dev *dev,
 		}
 		dev_flow = NULL;
 		/* Add suffix subflow to execute Q/RSS. */
-		ret = flow_create_split_inner(dev, flow, &dev_flow,
+		ret = flow_create_split_inner(dev, flow, &dev_flow, layers,
 					      &q_attr, mtr_sfx ? items :
 					      q_items, q_actions,
 					      external, error);
 		if (ret < 0)
 			goto exit;
 		assert(dev_flow);
-		dev_flow->hash_fields = hash_fields;
 	}
 
 exit:
@@ -3963,7 +4066,6 @@ flow_create_split_meter(struct rte_eth_dev *dev,
 	struct rte_flow_action *sfx_actions = NULL;
 	struct rte_flow_action *pre_actions = NULL;
 	struct rte_flow_item *sfx_items = NULL;
-	const  struct rte_flow_item *sfx_port_id_item;
 	struct mlx5_flow *dev_flow = NULL;
 	struct rte_flow_attr sfx_attr = *attr;
 	uint32_t mtr = 0;
@@ -3976,63 +4078,47 @@ flow_create_split_meter(struct rte_eth_dev *dev,
 	if (priv->mtr_en)
 		actions_n = flow_check_meter_action(actions, &mtr);
 	if (mtr) {
-		struct mlx5_rte_flow_item_tag *tag_spec;
 		/* The five prefix actions: meter, decap, encap, tag, end. */
 		act_size = sizeof(struct rte_flow_action) * (actions_n + 5) +
-			   sizeof(struct rte_flow_action_set_tag);
-		/* tag, end. */
-#define METER_SUFFIX_ITEM 3
+			   sizeof(struct mlx5_rte_flow_action_set_tag);
+		/* tag, vlan, port id, end. */
+#define METER_SUFFIX_ITEM 4
 		item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM +
-			    sizeof(struct mlx5_rte_flow_item_tag);
+			    sizeof(struct mlx5_rte_flow_item_tag) * 2;
 		sfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0);
 		if (!sfx_actions)
 			return rte_flow_error_set(error, ENOMEM,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL, "no memory to split "
 						  "meter flow");
+		sfx_items = (struct rte_flow_item *)((char *)sfx_actions +
+			     act_size);
 		pre_actions = sfx_actions + actions_n;
-		mtr_tag_id = flow_meter_split_prep(dev, actions, sfx_actions,
-						     pre_actions);
+		mtr_tag_id = flow_meter_split_prep(dev, items, sfx_items,
+						   actions, sfx_actions,
+						   pre_actions);
 		if (!mtr_tag_id) {
 			ret = -rte_errno;
 			goto exit;
 		}
 		/* Add the prefix subflow. */
-		ret = flow_create_split_inner(dev, flow, &dev_flow, attr, items,
-						  pre_actions, external, error);
+		ret = flow_create_split_inner(dev, flow, &dev_flow, 0, attr,
+					      items, pre_actions, external,
+					      error);
 		if (ret) {
 			ret = -rte_errno;
 			goto exit;
 		}
 		dev_flow->mtr_flow_id = mtr_tag_id;
-		/* Prepare the suffix flow match pattern. */
-		sfx_items = (struct rte_flow_item *)((char *)sfx_actions +
-			     act_size);
-		tag_spec = (struct mlx5_rte_flow_item_tag *)(sfx_items +
-			    METER_SUFFIX_ITEM);
-		tag_spec->data = rte_cpu_to_be_32(dev_flow->mtr_flow_id);
-		tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0,
-						    error);
-		sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG;
-		sfx_items->spec = tag_spec;
-		sfx_items->last = NULL;
-		sfx_items->mask = NULL;
-		sfx_items++;
-		sfx_port_id_item = find_port_id_item(items);
-		if (sfx_port_id_item) {
-			memcpy(sfx_items, sfx_port_id_item,
-			       sizeof(*sfx_items));
-			sfx_items++;
-		}
-		sfx_items->type = RTE_FLOW_ITEM_TYPE_END;
-		sfx_items -= METER_SUFFIX_ITEM;
 		/* Setting the sfx group atrr. */
 		sfx_attr.group = sfx_attr.transfer ?
 				(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
 				 MLX5_FLOW_TABLE_LEVEL_SUFFIX;
 	}
 	/* Add the prefix subflow. */
-	ret = flow_create_split_metadata(dev, flow, &sfx_attr,
+	ret = flow_create_split_metadata(dev, flow, dev_flow ?
+					 flow_get_prefix_layer_flags(dev_flow) :
+					 0, &sfx_attr,
 					 sfx_items ? sfx_items : items,
 					 sfx_actions ? sfx_actions : actions,
 					 external, error);
@@ -4146,14 +4232,18 @@ flow_list_create(struct rte_eth_dev *dev, struct mlx5_flows *list,
 	} items_tx;
 	struct rte_flow_expand_rss *buf = &expand_buffer.buf;
 	const struct rte_flow_action *p_actions_rx = actions;
-	int ret;
 	uint32_t i;
 	uint32_t flow_size;
-	int hairpin_flow = 0;
+	int hairpin_flow;
 	uint32_t hairpin_id = 0;
 	struct rte_flow_attr attr_tx = { .priority = 0 };
+	int ret;
 
 	hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
+	ret = flow_drv_validate(dev, attr, items, p_actions_rx,
+				external, hairpin_flow, error);
+	if (ret < 0)
+		return NULL;
 	if (hairpin_flow > 0) {
 		if (hairpin_flow > MLX5_MAX_SPLIT_ACTIONS) {
 			rte_errno = EINVAL;
@@ -4164,10 +4254,6 @@ flow_list_create(struct rte_eth_dev *dev, struct mlx5_flows *list,
 				   &hairpin_id);
 		p_actions_rx = actions_rx.actions;
 	}
-	ret = flow_drv_validate(dev, attr, items, p_actions_rx, external,
-				error);
-	if (ret < 0)
-		goto error_before_flow;
 	flow_size = sizeof(struct rte_flow);
 	rss = flow_get_rss_action(p_actions_rx);
 	if (rss)
@@ -4334,6 +4420,26 @@ mlx5_flow_create_esw_table_zero_flow(struct rte_eth_dev *dev)
 				actions, false, &error);
 }
 
+/**
+ * Validate a flow supported by the NIC.
+ *
+ * @see rte_flow_validate()
+ * @see rte_flow_ops
+ */
+int
+mlx5_flow_validate(struct rte_eth_dev *dev,
+		   const struct rte_flow_attr *attr,
+		   const struct rte_flow_item items[],
+		   const struct rte_flow_action actions[],
+		   struct rte_flow_error *error)
+{
+	int hairpin_flow;
+
+	hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
+	return flow_drv_validate(dev, attr, items, actions,
+				true, hairpin_flow, error);
+}
+
 /**
  * Create a flow.
  *
@@ -4518,7 +4624,8 @@ mlx5_ctrl_flow_source_queue(struct rte_eth_dev *dev,
 	};
 	struct rte_flow_item items[] = {
 		{
-			.type = MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE,
+			.type = (enum rte_flow_item_type)
+				MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE,
 			.spec = &queue_spec,
 			.last = NULL,
 			.mask = &queue_mask,
@@ -4623,6 +4730,8 @@ mlx5_ctrl_flow_vlan(struct rte_eth_dev *dev,
 	if (!priv->reta_idx_n || !priv->rxqs_n) {
 		return 0;
 	}
+	if (!(dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG))
+		action_rss.types = 0;
 	for (i = 0; i != priv->reta_idx_n; ++i)
 		queue[i] = (*priv->reta_idx)[i];
 	flow = flow_list_create(dev, &priv->ctrl_flows,
@@ -5498,6 +5607,11 @@ mlx5_flow_query_alarm(void *arg)
 		goto set_alarm;
 	dcs = (struct mlx5_devx_obj *)(uintptr_t)rte_atomic64_read
 							      (&pool->a64_dcs);
+	if (dcs->id & (MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT - 1)) {
+		/* Pool without valid counter. */
+		pool->raw_hw = NULL;
+		goto next_pool;
+	}
 	offset = batch ? 0 : dcs->id % MLX5_COUNTERS_PER_POOL;
 	ret = mlx5_devx_cmd_flow_counter_query(dcs, 0, MLX5_COUNTERS_PER_POOL -
 					       offset, NULL, NULL,
@@ -5515,6 +5629,7 @@ mlx5_flow_query_alarm(void *arg)
 	pool->raw_hw->min_dcs_id = dcs->id;
 	LIST_REMOVE(pool->raw_hw, next);
 	sh->cmng.pending_queries++;
+next_pool:
 	pool_index++;
 	if (pool_index >= rte_atomic16_read(&cont->n_valid)) {
 		batch ^= 0x1;
@@ -5570,6 +5685,8 @@ mlx5_flow_async_pool_query_handle(struct mlx5_ibv_shared *sh,
  *   Value is part of flow rule created by request external to PMD.
  * @param[in] group
  *   rte_flow group index value.
+ * @param[out] fdb_def_rule
+ *   Whether fdb jump to table 1 is configured.
  * @param[out] table
  *   HW table value.
  * @param[out] error
@@ -5580,10 +5697,10 @@ mlx5_flow_async_pool_query_handle(struct mlx5_ibv_shared *sh,
  */
 int
 mlx5_flow_group_to_table(const struct rte_flow_attr *attributes, bool external,
-			 uint32_t group, uint32_t *table,
+			 uint32_t group, bool fdb_def_rule, uint32_t *table,
 			 struct rte_flow_error *error)
 {
-	if (attributes->transfer && external) {
+	if (attributes->transfer && external && fdb_def_rule) {
 		if (group == UINT32_MAX)
 			return rte_flow_error_set
 						(error, EINVAL,
@@ -5633,7 +5750,8 @@ mlx5_flow_discover_mreg_c(struct rte_eth_dev *dev)
 		};
 		struct rte_flow_action actions[] = {
 			[0] = {
-				.type = MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
+				.type = (enum rte_flow_action_type)
+					MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
 				.conf = &(struct mlx5_flow_action_copy_mreg){
 					.src = REG_C_1,
 					.dst = idx,
diff --git a/dpdk/drivers/net/mlx5/mlx5_flow.h b/dpdk/drivers/net/mlx5/mlx5_flow.h
index 3fff5dd7da..4300e62fad 100644
--- a/dpdk/drivers/net/mlx5/mlx5_flow.h
+++ b/dpdk/drivers/net/mlx5/mlx5_flow.h
@@ -33,6 +33,7 @@ enum mlx5_rte_flow_item_type {
 	MLX5_RTE_FLOW_ITEM_TYPE_END = INT_MIN,
 	MLX5_RTE_FLOW_ITEM_TYPE_TAG,
 	MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE,
+	MLX5_RTE_FLOW_ITEM_TYPE_VLAN,
 };
 
 /* Private (internal) rte flow actions. */
@@ -188,20 +189,16 @@ enum mlx5_feature_name {
 #define MLX5_FLOW_ACTION_DEC_TTL (1u << 19)
 #define MLX5_FLOW_ACTION_SET_MAC_SRC (1u << 20)
 #define MLX5_FLOW_ACTION_SET_MAC_DST (1u << 21)
-#define MLX5_FLOW_ACTION_VXLAN_ENCAP (1u << 22)
-#define MLX5_FLOW_ACTION_VXLAN_DECAP (1u << 23)
-#define MLX5_FLOW_ACTION_NVGRE_ENCAP (1u << 24)
-#define MLX5_FLOW_ACTION_NVGRE_DECAP (1u << 25)
-#define MLX5_FLOW_ACTION_RAW_ENCAP (1u << 26)
-#define MLX5_FLOW_ACTION_RAW_DECAP (1u << 27)
-#define MLX5_FLOW_ACTION_INC_TCP_SEQ (1u << 28)
-#define MLX5_FLOW_ACTION_DEC_TCP_SEQ (1u << 29)
-#define MLX5_FLOW_ACTION_INC_TCP_ACK (1u << 30)
-#define MLX5_FLOW_ACTION_DEC_TCP_ACK (1u << 31)
-#define MLX5_FLOW_ACTION_SET_TAG (1ull << 32)
-#define MLX5_FLOW_ACTION_MARK_EXT (1ull << 33)
-#define MLX5_FLOW_ACTION_SET_META (1ull << 34)
-#define MLX5_FLOW_ACTION_METER (1ull << 35)
+#define MLX5_FLOW_ACTION_ENCAP (1u << 22)
+#define MLX5_FLOW_ACTION_DECAP (1u << 23)
+#define MLX5_FLOW_ACTION_INC_TCP_SEQ (1u << 24)
+#define MLX5_FLOW_ACTION_DEC_TCP_SEQ (1u << 25)
+#define MLX5_FLOW_ACTION_INC_TCP_ACK (1u << 26)
+#define MLX5_FLOW_ACTION_DEC_TCP_ACK (1u << 27)
+#define MLX5_FLOW_ACTION_SET_TAG (1ull << 28)
+#define MLX5_FLOW_ACTION_MARK_EXT (1ull << 29)
+#define MLX5_FLOW_ACTION_SET_META (1ull << 30)
+#define MLX5_FLOW_ACTION_METER (1ull << 31)
 
 #define MLX5_FLOW_FATE_ACTIONS \
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | \
@@ -211,15 +208,6 @@ enum mlx5_feature_name {
 	(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_PORT_ID | \
 	 MLX5_FLOW_ACTION_JUMP)
 
-#define MLX5_FLOW_ENCAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
-				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
-				 MLX5_FLOW_ACTION_RAW_ENCAP | \
-				 MLX5_FLOW_ACTION_OF_PUSH_VLAN)
-
-#define MLX5_FLOW_DECAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
-				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
-				 MLX5_FLOW_ACTION_RAW_DECAP | \
-				 MLX5_FLOW_ACTION_OF_POP_VLAN)
 
 #define MLX5_FLOW_MODIFY_HDR_ACTIONS (MLX5_FLOW_ACTION_SET_IPV4_SRC | \
 				      MLX5_FLOW_ACTION_SET_IPV4_DST | \
@@ -242,6 +230,9 @@ enum mlx5_feature_name {
 
 #define MLX5_FLOW_VLAN_ACTIONS (MLX5_FLOW_ACTION_OF_POP_VLAN | \
 				MLX5_FLOW_ACTION_OF_PUSH_VLAN)
+
+#define MLX5_FLOW_XCAP_ACTIONS (MLX5_FLOW_ACTION_ENCAP | MLX5_FLOW_ACTION_DECAP)
+
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
 #endif
@@ -288,6 +279,27 @@ enum mlx5_feature_name {
 /* IBV hash source bits  for IPV6. */
 #define MLX5_IPV6_IBV_RX_HASH (IBV_RX_HASH_SRC_IPV6 | IBV_RX_HASH_DST_IPV6)
 
+/* IBV hash bits for L3 SRC. */
+#define MLX5_L3_SRC_IBV_RX_HASH (IBV_RX_HASH_SRC_IPV4 | IBV_RX_HASH_SRC_IPV6)
+
+/* IBV hash bits for L3 DST. */
+#define MLX5_L3_DST_IBV_RX_HASH (IBV_RX_HASH_DST_IPV4 | IBV_RX_HASH_DST_IPV6)
+
+/* IBV hash bits for TCP. */
+#define MLX5_TCP_IBV_RX_HASH (IBV_RX_HASH_SRC_PORT_TCP | \
+			      IBV_RX_HASH_DST_PORT_TCP)
+
+/* IBV hash bits for UDP. */
+#define MLX5_UDP_IBV_RX_HASH (IBV_RX_HASH_SRC_PORT_UDP | \
+			      IBV_RX_HASH_DST_PORT_UDP)
+
+/* IBV hash bits for L4 SRC. */
+#define MLX5_L4_SRC_IBV_RX_HASH (IBV_RX_HASH_SRC_PORT_TCP | \
+				 IBV_RX_HASH_SRC_PORT_UDP)
+
+/* IBV hash bits for L4 DST. */
+#define MLX5_L4_DST_IBV_RX_HASH (IBV_RX_HASH_DST_PORT_TCP | \
+				 IBV_RX_HASH_DST_PORT_UDP)
 
 /* Geneve header first 16Bit */
 #define MLX5_GENEVE_VER_MASK 0x3
@@ -315,6 +327,26 @@ enum mlx5_feature_name {
 #define MLX5_GENEVE_OPT_LEN_0 14
 #define MLX5_GENEVE_OPT_LEN_1 63
 
+#define MLX5_ENCAPSULATION_DECISION_SIZE (sizeof(struct rte_ether_hdr) + \
+					  sizeof(struct rte_ipv4_hdr))
+
+/* Software header modify action numbers of a flow. */
+#define MLX5_ACT_NUM_MDF_IPV4		1
+#define MLX5_ACT_NUM_MDF_IPV6		4
+#define MLX5_ACT_NUM_MDF_MAC		2
+#define MLX5_ACT_NUM_MDF_VID		1
+#define MLX5_ACT_NUM_MDF_PORT		2
+#define MLX5_ACT_NUM_MDF_TTL		1
+#define MLX5_ACT_NUM_DEC_TTL		MLX5_ACT_NUM_MDF_TTL
+#define MLX5_ACT_NUM_MDF_TCPSEQ		1
+#define MLX5_ACT_NUM_MDF_TCPACK		1
+#define MLX5_ACT_NUM_SET_REG		1
+#define MLX5_ACT_NUM_SET_TAG		1
+#define MLX5_ACT_NUM_CPY_MREG		MLX5_ACT_NUM_SET_TAG
+#define MLX5_ACT_NUM_SET_MARK		MLX5_ACT_NUM_SET_TAG
+#define MLX5_ACT_NUM_SET_META		MLX5_ACT_NUM_SET_TAG
+#define MLX5_ACT_NUM_SET_DSCP		1
+
 enum mlx5_flow_drv_type {
 	MLX5_FLOW_TYPE_MIN,
 	MLX5_FLOW_TYPE_DV,
@@ -370,11 +402,16 @@ struct mlx5_flow_dv_tag_resource {
 
 /*
  * Number of modification commands.
- * If extensive metadata registers are supported
- * the maximal actions amount is 16 and 8 otherwise.
+ * The maximal actions amount in FW is some constant, and it is 16 in the
+ * latest releases. In some old releases, it will be limited to 8.
+ * Since there is no interface to query the capacity, the maximal value should
+ * be used to allow PMD to create the flow. The validation will be done in the
+ * lower driver layer or FW. A failure will be returned if exceeds the maximal
+ * supported actions number on the root table.
+ * On non-root tables, there is no limitation, but 32 is enough right now.
  */
-#define MLX5_MODIFY_NUM 16
-#define MLX5_MODIFY_NUM_NO_MREG 8
+#define MLX5_MAX_MODIFY_NUM			32
+#define MLX5_ROOT_TBL_MODIFY_NUM		16
 
 /* Modify resource structure */
 struct mlx5_flow_dv_modify_hdr_resource {
@@ -385,9 +422,9 @@ struct mlx5_flow_dv_modify_hdr_resource {
 	/**< Verbs modify header action object. */
 	uint8_t ft_type; /**< Flow table type, Rx or Tx. */
 	uint32_t actions_num; /**< Number of modification actions. */
-	struct mlx5_modification_cmd actions[MLX5_MODIFY_NUM];
-	/**< Modification actions. */
 	uint64_t flags; /**< Flags for RDMA API. */
+	struct mlx5_modification_cmd actions[];
+	/**< Modification actions. */
 };
 
 /* Jump action resource structure. */
@@ -554,6 +591,8 @@ struct mlx5_flow_policer_stats {
 struct mlx5_meter_domain_info {
 	struct mlx5_flow_tbl_resource *tbl;
 	/**< Meter table. */
+	struct mlx5_flow_tbl_resource *sfx_tbl;
+	/**< Meter suffix table. */
 	void *any_matcher;
 	/**< Meter color not match default criteria. */
 	void *color_matcher;
@@ -657,6 +696,7 @@ typedef int (*mlx5_flow_validate_t)(struct rte_eth_dev *dev,
 				    const struct rte_flow_item items[],
 				    const struct rte_flow_action actions[],
 				    bool external,
+				    int hairpin,
 				    struct rte_flow_error *error);
 typedef struct mlx5_flow *(*mlx5_flow_prepare_t)
 	(const struct rte_flow_attr *attr, const struct rte_flow_item items[],
@@ -724,20 +764,20 @@ struct mlx5_flow_driver_ops {
 
 /* mlx5_flow.c */
 
-struct mlx5_flow_id_pool *mlx5_flow_id_pool_alloc(void);
+struct mlx5_flow_id_pool *mlx5_flow_id_pool_alloc(uint32_t max_id);
 void mlx5_flow_id_pool_release(struct mlx5_flow_id_pool *pool);
 uint32_t mlx5_flow_id_get(struct mlx5_flow_id_pool *pool, uint32_t *id);
 uint32_t mlx5_flow_id_release(struct mlx5_flow_id_pool *pool,
 			      uint32_t id);
 int mlx5_flow_group_to_table(const struct rte_flow_attr *attributes,
-			     bool external, uint32_t group, uint32_t *table,
-			     struct rte_flow_error *error);
+			     bool external, uint32_t group, bool fdb_def_rule,
+			     uint32_t *table, struct rte_flow_error *error);
 uint64_t mlx5_flow_hashfields_adjust(struct mlx5_flow *dev_flow, int tunnel,
 				     uint64_t layer_types,
 				     uint64_t hash_fields);
 uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				   uint32_t subpriority);
-enum modify_reg mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
+int mlx5_flow_get_reg_id(struct rte_eth_dev *dev,
 				     enum mlx5_feature_name feature,
 				     uint32_t id,
 				     struct rte_flow_error *error);
diff --git a/dpdk/drivers/net/mlx5/mlx5_flow_dv.c b/dpdk/drivers/net/mlx5/mlx5_flow_dv.c
index 73aaea4536..a1b805c105 100644
--- a/dpdk/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/dpdk/drivers/net/mlx5/mlx5_flow_dv.c
@@ -27,6 +27,7 @@
 #include <rte_ip.h>
 #include <rte_gre.h>
 #include <rte_vxlan.h>
+#include <rte_mpls.h>
 
 #include "mlx5.h"
 #include "mlx5_defs.h"
@@ -51,8 +52,6 @@
 #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1
 #endif
 
-#define MLX5_ENCAPSULATION_DECISION_SIZE (sizeof(struct rte_flow_item_eth) + \
-					  sizeof(struct rte_flow_item_ipv4))
 /* VLAN header definitions */
 #define MLX5DV_FLOW_VLAN_PCP_SHIFT 13
 #define MLX5DV_FLOW_VLAN_PCP_MASK (0x7 << MLX5DV_FLOW_VLAN_PCP_SHIFT)
@@ -72,6 +71,10 @@ union flow_dv_attr {
 	uint32_t attr;
 };
 
+static int
+flow_dv_tbl_resource_release(struct rte_eth_dev *dev,
+			     struct mlx5_flow_tbl_resource *tbl);
+
 /**
  * Initialize flow attributes structure according to flow items' types.
  *
@@ -82,19 +85,74 @@ union flow_dv_attr {
  *   Pointer to item specification.
  * @param[out] attr
  *   Pointer to flow attributes structure.
+ * @param[in] dev_flow
+ *   Pointer to the sub flow.
+ * @param[in] tunnel_decap
+ *   Whether action is after tunnel decapsulation.
  */
 static void
-flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr)
+flow_dv_attr_init(const struct rte_flow_item *item, union flow_dv_attr *attr,
+		  struct mlx5_flow *dev_flow, bool tunnel_decap)
 {
+	/*
+	 * If layers is already initialized, it means this dev_flow is the
+	 * suffix flow, the layers flags is set by the prefix flow. Need to
+	 * use the layer flags from prefix flow as the suffix flow may not
+	 * have the user defined items as the flow is split.
+	 */
+	if (dev_flow->layers) {
+		if (dev_flow->layers & MLX5_FLOW_LAYER_OUTER_L3_IPV4)
+			attr->ipv4 = 1;
+		else if (dev_flow->layers & MLX5_FLOW_LAYER_OUTER_L3_IPV6)
+			attr->ipv6 = 1;
+		if (dev_flow->layers & MLX5_FLOW_LAYER_OUTER_L4_TCP)
+			attr->tcp = 1;
+		else if (dev_flow->layers & MLX5_FLOW_LAYER_OUTER_L4_UDP)
+			attr->udp = 1;
+		attr->valid = 1;
+		return;
+	}
 	for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+		uint8_t next_protocol = 0xff;
 		switch (item->type) {
+		case RTE_FLOW_ITEM_TYPE_GRE:
+		case RTE_FLOW_ITEM_TYPE_NVGRE:
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+		case RTE_FLOW_ITEM_TYPE_GENEVE:
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			if (tunnel_decap)
+				attr->attr = 0;
+			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
 			if (!attr->ipv6)
 				attr->ipv4 = 1;
+			if (item->mask != NULL &&
+			    ((const struct rte_flow_item_ipv4 *)
+			    item->mask)->hdr.next_proto_id)
+				next_protocol =
+				    ((const struct rte_flow_item_ipv4 *)
+				      (item->spec))->hdr.next_proto_id &
+				    ((const struct rte_flow_item_ipv4 *)
+				      (item->mask))->hdr.next_proto_id;
+			if ((next_protocol == IPPROTO_IPIP ||
+			    next_protocol == IPPROTO_IPV6) && tunnel_decap)
+				attr->attr = 0;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
 			if (!attr->ipv4)
 				attr->ipv6 = 1;
+			if (item->mask != NULL &&
+			    ((const struct rte_flow_item_ipv6 *)
+			    item->mask)->hdr.proto)
+				next_protocol =
+				    ((const struct rte_flow_item_ipv6 *)
+				      (item->spec))->hdr.proto &
+				    ((const struct rte_flow_item_ipv6 *)
+				      (item->mask))->hdr.proto;
+			if ((next_protocol == IPPROTO_IPIP ||
+			    next_protocol == IPPROTO_IPV6) && tunnel_decap)
+				attr->attr = 0;
 			break;
 		case RTE_FLOW_ITEM_TYPE_UDP:
 			if (!attr->tcp)
@@ -222,7 +280,7 @@ flow_dv_shared_lock(struct rte_eth_dev *dev)
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_ibv_shared *sh = priv->sh;
 
-	if (sh->dv_refcnt > 1) {
+	if (sh->refcnt > 1) {
 		int ret;
 
 		ret = pthread_mutex_lock(&sh->dv_mutex);
@@ -237,7 +295,7 @@ flow_dv_shared_unlock(struct rte_eth_dev *dev)
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_ibv_shared *sh = priv->sh;
 
-	if (sh->dv_refcnt > 1) {
+	if (sh->refcnt > 1) {
 		int ret;
 
 		ret = pthread_mutex_unlock(&sh->dv_mutex);
@@ -363,7 +421,7 @@ flow_dv_convert_modify_action(struct rte_flow_item *item,
 		uint32_t mask;
 		uint32_t data;
 
-		if (i >= MLX5_MODIFY_NUM)
+		if (i >= MLX5_MAX_MODIFY_NUM)
 			return rte_flow_error_set(error, EINVAL,
 				 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 				 "too many items to modify");
@@ -380,10 +438,12 @@ flow_dv_convert_modify_action(struct rte_flow_item *item,
 			 off_b - __builtin_clz(mask);
 		assert(size_b);
 		size_b = size_b == sizeof(uint32_t) * CHAR_BIT ? 0 : size_b;
-		actions[i].action_type = type;
-		actions[i].field = field->id;
-		actions[i].offset = off_b;
-		actions[i].length = size_b;
+		actions[i] = (struct mlx5_modification_cmd) {
+			.action_type = type,
+			.field = field->id,
+			.offset = off_b,
+			.length = size_b,
+		};
 		/* Convert entire record to expected big-endian format. */
 		actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
 		if (type == MLX5_MODIFICATION_TYPE_COPY) {
@@ -404,11 +464,11 @@ flow_dv_convert_modify_action(struct rte_flow_item *item,
 		++i;
 		++field;
 	} while (field->size);
-	resource->actions_num = i;
-	if (!resource->actions_num)
+	if (resource->actions_num == i)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "invalid modification flow item");
+	resource->actions_num = i;
 	return 0;
 }
 
@@ -566,17 +626,19 @@ flow_dv_convert_action_modify_vlan_vid
 	const struct rte_flow_action_of_set_vlan_vid *conf =
 		(const struct rte_flow_action_of_set_vlan_vid *)(action->conf);
 	int i = resource->actions_num;
-	struct mlx5_modification_cmd *actions = &resource->actions[i];
+	struct mlx5_modification_cmd *actions = resource->actions;
 	struct field_modify_info *field = modify_vlan_out_first_vid;
 
-	if (i >= MLX5_MODIFY_NUM)
+	if (i >= MLX5_MAX_MODIFY_NUM)
 		return rte_flow_error_set(error, EINVAL,
 			 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 			 "too many items to modify");
-	actions[i].action_type = MLX5_MODIFICATION_TYPE_SET;
-	actions[i].field = field->id;
-	actions[i].length = field->size;
-	actions[i].offset = field->offset;
+	actions[i] = (struct mlx5_modification_cmd) {
+		.action_type = MLX5_MODIFICATION_TYPE_SET,
+		.field = field->id,
+		.length = field->size,
+		.offset = field->offset,
+	};
 	actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
 	actions[i].data1 = conf->vlan_vid;
 	actions[i].data1 = actions[i].data1 << 16;
@@ -595,6 +657,10 @@ flow_dv_convert_action_modify_vlan_vid
  *   Pointer to rte_flow_item objects list.
  * @param[in] attr
  *   Pointer to flow attributes structure.
+ * @param[in] dev_flow
+ *   Pointer to the sub flow.
+ * @param[in] tunnel_decap
+ *   Whether action is after tunnel decapsulation.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -606,8 +672,8 @@ flow_dv_convert_action_modify_tp
 			(struct mlx5_flow_dv_modify_hdr_resource *resource,
 			 const struct rte_flow_action *action,
 			 const struct rte_flow_item *items,
-			 union flow_dv_attr *attr,
-			 struct rte_flow_error *error)
+			 union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
+			 bool tunnel_decap, struct rte_flow_error *error)
 {
 	const struct rte_flow_action_set_tp *conf =
 		(const struct rte_flow_action_set_tp *)(action->conf);
@@ -619,7 +685,7 @@ flow_dv_convert_action_modify_tp
 	struct field_modify_info *field;
 
 	if (!attr->valid)
-		flow_dv_attr_init(items, attr);
+		flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
 	if (attr->udp) {
 		memset(&udp, 0, sizeof(udp));
 		memset(&udp_mask, 0, sizeof(udp_mask));
@@ -636,8 +702,8 @@ flow_dv_convert_action_modify_tp
 		item.spec = &udp;
 		item.mask = &udp_mask;
 		field = modify_udp;
-	}
-	if (attr->tcp) {
+	} else {
+		assert(attr->tcp);
 		memset(&tcp, 0, sizeof(tcp));
 		memset(&tcp_mask, 0, sizeof(tcp_mask));
 		if (action->type == RTE_FLOW_ACTION_TYPE_SET_TP_SRC) {
@@ -669,6 +735,10 @@ flow_dv_convert_action_modify_tp
  *   Pointer to rte_flow_item objects list.
  * @param[in] attr
  *   Pointer to flow attributes structure.
+ * @param[in] dev_flow
+ *   Pointer to the sub flow.
+ * @param[in] tunnel_decap
+ *   Whether action is after tunnel decapsulation.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -680,8 +750,8 @@ flow_dv_convert_action_modify_ttl
 			(struct mlx5_flow_dv_modify_hdr_resource *resource,
 			 const struct rte_flow_action *action,
 			 const struct rte_flow_item *items,
-			 union flow_dv_attr *attr,
-			 struct rte_flow_error *error)
+			 union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
+			 bool tunnel_decap, struct rte_flow_error *error)
 {
 	const struct rte_flow_action_set_ttl *conf =
 		(const struct rte_flow_action_set_ttl *)(action->conf);
@@ -693,7 +763,7 @@ flow_dv_convert_action_modify_ttl
 	struct field_modify_info *field;
 
 	if (!attr->valid)
-		flow_dv_attr_init(items, attr);
+		flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
 	if (attr->ipv4) {
 		memset(&ipv4, 0, sizeof(ipv4));
 		memset(&ipv4_mask, 0, sizeof(ipv4_mask));
@@ -703,8 +773,8 @@ flow_dv_convert_action_modify_ttl
 		item.spec = &ipv4;
 		item.mask = &ipv4_mask;
 		field = modify_ipv4;
-	}
-	if (attr->ipv6) {
+	} else {
+		assert(attr->ipv6);
 		memset(&ipv6, 0, sizeof(ipv6));
 		memset(&ipv6_mask, 0, sizeof(ipv6_mask));
 		ipv6.hdr.hop_limits = conf->ttl_value;
@@ -729,6 +799,10 @@ flow_dv_convert_action_modify_ttl
  *   Pointer to rte_flow_item objects list.
  * @param[in] attr
  *   Pointer to flow attributes structure.
+ * @param[in] dev_flow
+ *   Pointer to the sub flow.
+ * @param[in] tunnel_decap
+ *   Whether action is after tunnel decapsulation.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -739,8 +813,8 @@ static int
 flow_dv_convert_action_modify_dec_ttl
 			(struct mlx5_flow_dv_modify_hdr_resource *resource,
 			 const struct rte_flow_item *items,
-			 union flow_dv_attr *attr,
-			 struct rte_flow_error *error)
+			 union flow_dv_attr *attr, struct mlx5_flow *dev_flow,
+			 bool tunnel_decap, struct rte_flow_error *error)
 {
 	struct rte_flow_item item;
 	struct rte_flow_item_ipv4 ipv4;
@@ -750,7 +824,7 @@ flow_dv_convert_action_modify_dec_ttl
 	struct field_modify_info *field;
 
 	if (!attr->valid)
-		flow_dv_attr_init(items, attr);
+		flow_dv_attr_init(items, attr, dev_flow, tunnel_decap);
 	if (attr->ipv4) {
 		memset(&ipv4, 0, sizeof(ipv4));
 		memset(&ipv4_mask, 0, sizeof(ipv4_mask));
@@ -760,8 +834,8 @@ flow_dv_convert_action_modify_dec_ttl
 		item.spec = &ipv4;
 		item.mask = &ipv4_mask;
 		field = modify_ipv4;
-	}
-	if (attr->ipv6) {
+	} else {
+		assert(attr->ipv6);
 		memset(&ipv6, 0, sizeof(ipv6));
 		memset(&ipv6_mask, 0, sizeof(ipv6_mask));
 		ipv6.hdr.hop_limits = 0xFF;
@@ -902,22 +976,20 @@ flow_dv_convert_action_set_reg
 	struct mlx5_modification_cmd *actions = resource->actions;
 	uint32_t i = resource->actions_num;
 
-	if (i >= MLX5_MODIFY_NUM)
+	if (i >= MLX5_MAX_MODIFY_NUM)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "too many items to modify");
 	assert(conf->id != REG_NONE);
-	assert(conf->id < RTE_DIM(reg_to_field));
-	actions[i].action_type = MLX5_MODIFICATION_TYPE_SET;
-	actions[i].field = reg_to_field[conf->id];
+	assert(conf->id < (enum modify_reg)RTE_DIM(reg_to_field));
+	actions[i] = (struct mlx5_modification_cmd) {
+		.action_type = MLX5_MODIFICATION_TYPE_SET,
+		.field = reg_to_field[conf->id],
+	};
 	actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
 	actions[i].data1 = rte_cpu_to_be_32(conf->data);
 	++i;
 	resource->actions_num = i;
-	if (!resource->actions_num)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "invalid modification flow item");
 	return 0;
 }
 
@@ -1075,10 +1147,9 @@ flow_dv_convert_action_mark(struct rte_eth_dev *dev,
 		.mask = &mask,
 	};
 	struct field_modify_info reg_c_x[] = {
-		{4, 0, 0}, /* dynamic instead of MLX5_MODI_META_REG_C_1. */
-		{0, 0, 0},
+		[1] = {0, 0, 0},
 	};
-	enum modify_reg reg;
+	int reg;
 
 	if (!mask)
 		return rte_flow_error_set(error, EINVAL,
@@ -1088,7 +1159,15 @@ flow_dv_convert_action_mark(struct rte_eth_dev *dev,
 	if (reg < 0)
 		return reg;
 	assert(reg > 0);
-	reg_c_x[0].id = reg_to_field[reg];
+	if (reg == REG_C_0) {
+		uint32_t msk_c0 = priv->sh->dv_regc0_mask;
+		uint32_t shl_c0 = rte_bsf32(msk_c0);
+
+		data = rte_cpu_to_be_32(rte_cpu_to_be_32(data) << shl_c0);
+		mask = rte_cpu_to_be_32(mask) & msk_c0;
+		mask = rte_cpu_to_be_32(mask << shl_c0);
+	}
+	reg_c_x[0] = (struct field_modify_info){4, 0, reg_to_field[reg]};
 	return flow_dv_convert_modify_action(&item, reg_c_x, NULL, resource,
 					     MLX5_MODIFICATION_TYPE_SET, error);
 }
@@ -1112,7 +1191,7 @@ flow_dv_get_metadata_reg(struct rte_eth_dev *dev,
 			 const struct rte_flow_attr *attr,
 			 struct rte_flow_error *error)
 {
-	enum modify_reg reg =
+	int reg =
 		mlx5_flow_get_reg_id(dev, attr->transfer ?
 					  MLX5_METADATA_FDB :
 					    attr->egress ?
@@ -1160,7 +1239,7 @@ flow_dv_convert_action_set_meta
 	struct field_modify_info reg_c_x[] = {
 		[1] = {0, 0, 0},
 	};
-	enum modify_reg reg = flow_dv_get_metadata_reg(dev, attr, error);
+	int reg = flow_dv_get_metadata_reg(dev, attr, error);
 
 	if (reg < 0)
 		return reg;
@@ -1250,6 +1329,11 @@ flow_dv_validate_item_mark(struct rte_eth_dev *dev,
 					  "mark id exceeds the limit");
 	if (!mask)
 		mask = &nic_mask;
+	if (!mask->id)
+		return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
+					"mask cannot be zero");
+
 	ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
 					(const uint8_t *)&nic_mask,
 					sizeof(struct rte_flow_item_mark),
@@ -1287,7 +1371,7 @@ flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused,
 	struct rte_flow_item_meta nic_mask = {
 		.data = UINT32_MAX
 	};
-	enum modify_reg reg;
+	int reg;
 	int ret;
 
 	if (!spec)
@@ -1295,10 +1379,6 @@ flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused,
 					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
 					  item->spec,
 					  "data cannot be empty");
-	if (!spec->data)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
-					  "data cannot be zero");
 	if (config->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
 		if (!mlx5_flow_ext_mreg_supported(dev))
 			return rte_flow_error_set(error, ENOTSUP,
@@ -1315,9 +1395,21 @@ flow_dv_validate_item_meta(struct rte_eth_dev *dev __rte_unused,
 					  "isn't supported");
 		if (reg != REG_A)
 			nic_mask.data = priv->sh->dv_meta_mask;
+	} else if (attr->transfer) {
+		return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ITEM, item,
+					"extended metadata feature "
+					"should be enabled when "
+					"meta item is requested "
+					"with e-switch mode ");
 	}
 	if (!mask)
 		mask = &rte_flow_item_meta_mask;
+	if (!mask->data)
+		return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
+					"mask cannot be zero");
+
 	ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
 					(const uint8_t *)&nic_mask,
 					sizeof(struct rte_flow_item_meta),
@@ -1366,6 +1458,11 @@ flow_dv_validate_item_tag(struct rte_eth_dev *dev,
 					  "data cannot be empty");
 	if (!mask)
 		mask = &rte_flow_item_tag_mask;
+	if (!mask->data)
+		return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ITEM_SPEC, NULL,
+					"mask cannot be zero");
+
 	ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
 					(const uint8_t *)&nic_mask,
 					sizeof(struct rte_flow_item_tag),
@@ -1465,6 +1562,79 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
 	return 0;
 }
 
+/**
+ * Validate VLAN item.
+ *
+ * @param[in] item
+ *   Item specification.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
+ * @param[in] dev
+ *   Ethernet device flow is being created on.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_item_vlan(const struct rte_flow_item *item,
+			   uint64_t item_flags,
+			   struct rte_eth_dev *dev,
+			   struct rte_flow_error *error)
+{
+	const struct rte_flow_item_vlan *mask = item->mask;
+	const struct rte_flow_item_vlan nic_mask = {
+		.tci = RTE_BE16(UINT16_MAX),
+		.inner_type = RTE_BE16(UINT16_MAX),
+	};
+	const int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+	int ret;
+	const uint64_t l34m = tunnel ? (MLX5_FLOW_LAYER_INNER_L3 |
+					MLX5_FLOW_LAYER_INNER_L4) :
+				       (MLX5_FLOW_LAYER_OUTER_L3 |
+					MLX5_FLOW_LAYER_OUTER_L4);
+	const uint64_t vlanm = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
+					MLX5_FLOW_LAYER_OUTER_VLAN;
+
+	if (item_flags & vlanm)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "multiple VLAN layers not supported");
+	else if ((item_flags & l34m) != 0)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ITEM, item,
+					  "VLAN cannot follow L3/L4 layer");
+	if (!mask)
+		mask = &rte_flow_item_vlan_mask;
+	ret = mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
+					(const uint8_t *)&nic_mask,
+					sizeof(struct rte_flow_item_vlan),
+					error);
+	if (ret)
+		return ret;
+	if (!tunnel && mask->tci != RTE_BE16(0x0fff)) {
+		struct mlx5_priv *priv = dev->data->dev_private;
+
+		if (priv->vmwa_context) {
+			/*
+			 * Non-NULL context means we have a virtual machine
+			 * and SR-IOV enabled, we have to create VLAN interface
+			 * to make hypervisor to setup E-Switch vport
+			 * context correctly. We avoid creating the multiple
+			 * VLAN interfaces, so we cannot support VLAN tag mask.
+			 */
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ITEM,
+						  item,
+						  "VLAN tag mask is not"
+						  " supported in virtual"
+						  " environment");
+		}
+	}
+	return 0;
+}
+
 /**
  * Validate the pop VLAN action.
  *
@@ -1492,7 +1662,7 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
 				 const struct rte_flow_attr *attr,
 				 struct rte_flow_error *error)
 {
-	struct mlx5_priv *priv = dev->data->dev_private;
+	const struct mlx5_priv *priv = dev->data->dev_private;
 
 	(void)action;
 	(void)attr;
@@ -1501,19 +1671,28 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 					  NULL,
 					  "pop vlan action is not supported");
-	/*
-	 * Check for inconsistencies:
-	 *  fail strip_vlan in a flow that matches packets without VLAN tags.
-	 *  fail strip_vlan in a flow that matches packets without explicitly a
-	 *  matching on VLAN tag ?
-	 */
-	if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN)
+	if (attr->egress)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
 					  NULL,
-					  "no support for multiple vlan pop "
+					  "pop vlan action not supported for "
+					  "egress");
+	if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "no support for multiple VLAN "
 					  "actions");
-	if (!(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
+	/* Pop VLAN with preceding Decap requires inner header with VLAN. */
+	if ((action_flags & MLX5_FLOW_ACTION_DECAP) &&
+	    !(item_flags & MLX5_FLOW_LAYER_INNER_VLAN))
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "cannot pop vlan after decap without "
+					  "match on inner vlan in the flow");
+	/* Pop VLAN without preceding Decap requires outer header with VLAN. */
+	if (!(action_flags & MLX5_FLOW_ACTION_DECAP) &&
+	    !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 					  NULL,
@@ -1524,20 +1703,21 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "wrong action order, port_id should "
 					  "be after pop VLAN action");
+	if (!attr->transfer && priv->representor)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "pop vlan action for VF representor "
+					  "not supported on NIC table");
 	return 0;
 }
 
 /**
  * Get VLAN default info from vlan match info.
  *
- * @param[in] dev
- *   Pointer to the rte_eth_dev structure.
- * @param[in] item
+ * @param[in] items
  *   the list of item specifications.
  * @param[out] vlan
  *   pointer VLAN info to fill to.
- * @param[out] error
- *   Pointer to error structure.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
@@ -1554,19 +1734,26 @@ flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
 
 	if (items == NULL)
 		return;
-	for (; items->type != RTE_FLOW_ITEM_TYPE_END &&
-	       items->type != RTE_FLOW_ITEM_TYPE_VLAN; items++)
-		;
-	if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) {
+	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
+		int type = items->type;
+
+		if (type == RTE_FLOW_ITEM_TYPE_VLAN ||
+		    type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN)
+			break;
+	}
+	if (items->type != RTE_FLOW_ITEM_TYPE_END) {
 		const struct rte_flow_item_vlan *vlan_m = items->mask;
 		const struct rte_flow_item_vlan *vlan_v = items->spec;
 
+		/* If VLAN item in pattern doesn't contain data, return here. */
+		if (!vlan_v)
+			return;
 		if (!vlan_m)
 			vlan_m = &nic_mask;
 		/* Only full match values are accepted */
 		if ((vlan_m->tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) ==
 		     MLX5DV_FLOW_VLAN_PCP_MASK_BE) {
-			vlan->vlan_tci &= MLX5DV_FLOW_VLAN_PCP_MASK;
+			vlan->vlan_tci &= ~MLX5DV_FLOW_VLAN_PCP_MASK;
 			vlan->vlan_tci |=
 				rte_be_to_cpu_16(vlan_v->tci &
 						 MLX5DV_FLOW_VLAN_PCP_MASK_BE);
@@ -1587,10 +1774,14 @@ flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
 /**
  * Validate the push VLAN action.
  *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
  * @param[in] action_flags
  *   Holds the actions detected until now.
+ * @param[in] item_flags
+ *   The items found in this flow rule.
  * @param[in] action
- *   Pointer to the encap action.
+ *   Pointer to the action structure.
  * @param[in] attr
  *   Pointer to flow attributes
  * @param[out] error
@@ -1600,38 +1791,57 @@ flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_dv_validate_action_push_vlan(uint64_t action_flags,
-				  uint64_t item_flags,
+flow_dv_validate_action_push_vlan(struct rte_eth_dev *dev,
+				  uint64_t action_flags,
+				  const struct rte_flow_item_vlan *vlan_m,
 				  const struct rte_flow_action *action,
 				  const struct rte_flow_attr *attr,
 				  struct rte_flow_error *error)
 {
 	const struct rte_flow_action_of_push_vlan *push_vlan = action->conf;
+	const struct mlx5_priv *priv = dev->data->dev_private;
 
 	if (push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_VLAN) &&
 	    push_vlan->ethertype != RTE_BE16(RTE_ETHER_TYPE_QINQ))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "invalid vlan ethertype");
-	if (action_flags &
-		(MLX5_FLOW_ACTION_OF_POP_VLAN | MLX5_FLOW_ACTION_OF_PUSH_VLAN))
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "no support for multiple VLAN "
-					  "actions");
-	if (!mlx5_flow_find_action
-			(action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) &&
-	    !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
-		return rte_flow_error_set(error, ENOTSUP,
-				RTE_FLOW_ERROR_TYPE_ACTION, action,
-				"push VLAN needs to match on VLAN in order to "
-				"get VLAN VID information because there is "
-				"no followed set VLAN VID action");
 	if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "wrong action order, port_id should "
 					  "be after push VLAN");
+	if (!attr->transfer && priv->representor)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "push vlan action for VF representor "
+					  "not supported on NIC table");
+	if (vlan_m &&
+	    (vlan_m->tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) &&
+	    (vlan_m->tci & MLX5DV_FLOW_VLAN_PCP_MASK_BE) !=
+		MLX5DV_FLOW_VLAN_PCP_MASK_BE &&
+	    !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_PCP) &&
+	    !(mlx5_flow_find_action
+		(action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP)))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "not full match mask on VLAN PCP and "
+					  "there is no of_set_vlan_pcp action, "
+					  "push VLAN action cannot figure out "
+					  "PCP value");
+	if (vlan_m &&
+	    (vlan_m->tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) &&
+	    (vlan_m->tci & MLX5DV_FLOW_VLAN_VID_MASK_BE) !=
+		MLX5DV_FLOW_VLAN_VID_MASK_BE &&
+	    !(action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID) &&
+	    !(mlx5_flow_find_action
+		(action + 1, RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID)))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "not full match mask on VLAN VID and "
+					  "there is no of_set_vlan_vid action, "
+					  "push VLAN action cannot figure out "
+					  "VID value");
 	(void)attr;
 	return 0;
 }
@@ -1643,8 +1853,6 @@ flow_dv_validate_action_push_vlan(uint64_t action_flags,
  *   Holds the actions detected until now.
  * @param[in] actions
  *   Pointer to the list of actions remaining in the flow rule.
- * @param[in] attr
- *   Pointer to flow attributes
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -1686,10 +1894,10 @@ flow_dv_validate_action_set_vlan_pcp(uint64_t action_flags,
  *
  * @param[in] item_flags
  *   Holds the items detected in this rule.
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
  * @param[in] actions
  *   Pointer to the list of actions remaining in the flow rule.
- * @param[in] attr
- *   Pointer to flow attributes
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -1705,37 +1913,21 @@ flow_dv_validate_action_set_vlan_vid(uint64_t item_flags,
 	const struct rte_flow_action *action = actions;
 	const struct rte_flow_action_of_set_vlan_vid *conf = action->conf;
 
-	if (conf->vlan_vid > RTE_BE16(0xFFE))
+	if (rte_be_to_cpu_16(conf->vlan_vid) > 0xFFE)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "VLAN VID value is too big");
-	/* there is an of_push_vlan action before us */
-	if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
-		if (mlx5_flow_find_action(actions + 1,
-					  RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID))
-			return rte_flow_error_set(error, ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION, action,
-					"Multiple VLAN VID modifications are "
-					"not supported");
-		else
-			return 0;
-	}
-
-	/*
-	 * Action is on an existing VLAN header:
-	 *    Need to verify this is a single modify CID action.
-	 *   Rule mast include a match on outer VLAN.
-	 */
+	if (!(action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) &&
+	    !(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "set VLAN VID action must follow push"
+					  " VLAN action or match on VLAN item");
 	if (action_flags & MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "Multiple VLAN VID modifications are "
 					  "not supported");
-	if (!(item_flags & MLX5_FLOW_LAYER_OUTER_VLAN))
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "match on VLAN is required in order "
-					  "to set VLAN VID");
 	if (action_flags & MLX5_FLOW_ACTION_PORT_ID)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -1788,10 +1980,6 @@ flow_dv_validate_action_flag(struct rte_eth_dev *dev,
 	if (ret < 0)
 		return ret;
 	assert(ret > 0);
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and flag in same flow");
 	if (action_flags & MLX5_FLOW_ACTION_MARK)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -1861,10 +2049,6 @@ flow_dv_validate_action_mark(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  &mark->id,
 					  "mark id exceeds the limit");
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and mark in same flow");
 	if (action_flags & MLX5_FLOW_ACTION_FLAG)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -1883,7 +2067,7 @@ flow_dv_validate_action_mark(struct rte_eth_dev *dev,
  * @param[in] dev
  *   Pointer to the rte_eth_dev structure.
  * @param[in] action
- *   Pointer to the encap action.
+ *   Pointer to the action structure.
  * @param[in] action_flags
  *   Holds the actions detected until now.
  * @param[in] attr
@@ -1903,7 +2087,7 @@ flow_dv_validate_action_set_meta(struct rte_eth_dev *dev,
 {
 	const struct rte_flow_action_set_meta *conf;
 	uint32_t nic_mask = UINT32_MAX;
-	enum modify_reg reg;
+	int reg;
 
 	if (!mlx5_flow_ext_mreg_supported(dev))
 		return rte_flow_error_set(error, ENOTSUP,
@@ -1931,10 +2115,6 @@ flow_dv_validate_action_set_meta(struct rte_eth_dev *dev,
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "meta data must be within reg C0");
-	if (!(conf->data & conf->mask))
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "zero value has no effect");
 	return 0;
 }
 
@@ -1944,7 +2124,7 @@ flow_dv_validate_action_set_meta(struct rte_eth_dev *dev,
  * @param[in] dev
  *   Pointer to the rte_eth_dev structure.
  * @param[in] action
- *   Pointer to the encap action.
+ *   Pointer to the action structure.
  * @param[in] action_flags
  *   Holds the actions detected until now.
  * @param[in] attr
@@ -1998,7 +2178,7 @@ flow_dv_validate_action_set_tag(struct rte_eth_dev *dev,
  * Validate count action.
  *
  * @param[in] dev
- *   device otr.
+ *   Pointer to rte_eth_dev structure.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2027,12 +2207,14 @@ flow_dv_validate_action_count(struct rte_eth_dev *dev,
 /**
  * Validate the L2 encap action.
  *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
  * @param[in] action_flags
  *   Holds the actions detected until now.
  * @param[in] action
- *   Pointer to the encap action.
+ *   Pointer to the action structure.
  * @param[in] attr
- *   Pointer to flow attributes
+ *   Pointer to flow attributes.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2040,38 +2222,42 @@ flow_dv_validate_action_count(struct rte_eth_dev *dev,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_dv_validate_action_l2_encap(uint64_t action_flags,
+flow_dv_validate_action_l2_encap(struct rte_eth_dev *dev,
+				 uint64_t action_flags,
 				 const struct rte_flow_action *action,
 				 const struct rte_flow_attr *attr,
 				 struct rte_flow_error *error)
 {
+	const struct mlx5_priv *priv = dev->data->dev_private;
+
 	if (!(action->conf))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "configuration cannot be null");
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and encap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
+	if (action_flags & MLX5_FLOW_ACTION_ENCAP)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single encap or"
-					  " decap action in a flow");
-	if (!attr->transfer && attr->ingress)
+					  "can only have a single encap action "
+					  "in a flow");
+	if (!attr->transfer && priv->representor)
 		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-					  NULL,
-					  "encap action not supported for "
-					  "ingress");
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "encap action for VF representor "
+					  "not supported on NIC table");
 	return 0;
 }
 
 /**
- * Validate the L2 decap action.
+ * Validate a decap action.
  *
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
  * @param[in] action_flags
  *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the action structure.
+ * @param[in] item_flags
+ *   Holds the items detected.
  * @param[in] attr
  *   Pointer to flow attributes
  * @param[out] error
@@ -2081,19 +2267,22 @@ flow_dv_validate_action_l2_encap(uint64_t action_flags,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_dv_validate_action_l2_decap(uint64_t action_flags,
-				 const struct rte_flow_attr *attr,
-				 struct rte_flow_error *error)
+flow_dv_validate_action_decap(struct rte_eth_dev *dev,
+			      uint64_t action_flags,
+			      const struct rte_flow_action *action,
+			      const uint64_t item_flags,
+			      const struct rte_flow_attr *attr,
+			      struct rte_flow_error *error)
 {
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and decap in same flow");
-	if (action_flags & (MLX5_FLOW_ENCAP_ACTIONS | MLX5_FLOW_DECAP_ACTIONS))
-		return rte_flow_error_set(error, EINVAL,
+	const struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (action_flags & MLX5_FLOW_XCAP_ACTIONS)
+		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single encap or"
-					  " decap action in a flow");
+					  action_flags &
+					  MLX5_FLOW_ACTION_DECAP ? "can only "
+					  "have a single decap action" : "decap "
+					  "after encap is not supported");
 	if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -2105,69 +2294,40 @@ flow_dv_validate_action_l2_decap(uint64_t action_flags,
 					  NULL,
 					  "decap action not supported for "
 					  "egress");
+	if (!attr->transfer && priv->representor)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "decap action for VF representor "
+					  "not supported on NIC table");
+	if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP &&
+	    !(item_flags & MLX5_FLOW_LAYER_VXLAN))
+		return rte_flow_error_set(error, ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				"VXLAN item should be present for VXLAN decap");
 	return 0;
 }
 
+const struct rte_flow_action_raw_decap empty_decap = {.data = NULL, .size = 0,};
+
 /**
- * Validate the raw encap action.
+ * Validate the raw encap and decap actions.
  *
- * @param[in] action_flags
- *   Holds the actions detected until now.
- * @param[in] action
+ * @param[in] dev
+ *   Pointer to the rte_eth_dev structure.
+ * @param[in] decap
+ *   Pointer to the decap action.
+ * @param[in] encap
  *   Pointer to the encap action.
  * @param[in] attr
  *   Pointer to flow attributes
- * @param[out] error
- *   Pointer to error structure.
- *
- * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
- */
-static int
-flow_dv_validate_action_raw_encap(uint64_t action_flags,
-				  const struct rte_flow_action *action,
-				  const struct rte_flow_attr *attr,
-				  struct rte_flow_error *error)
-{
-	const struct rte_flow_action_raw_encap *raw_encap =
-		(const struct rte_flow_action_raw_encap *)action->conf;
-	if (!(action->conf))
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "configuration cannot be null");
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and encap in same flow");
-	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single encap"
-					  " action in a flow");
-	/* encap without preceding decap is not supported for ingress */
-	if (!attr->transfer &&  attr->ingress &&
-	    !(action_flags & MLX5_FLOW_ACTION_RAW_DECAP))
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-					  NULL,
-					  "encap action not supported for "
-					  "ingress");
-	if (!raw_encap->size || !raw_encap->data)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, action,
-					  "raw encap data cannot be empty");
-	return 0;
-}
-
-/**
- * Validate the raw decap action.
- *
- * @param[in] action_flags
+ * @param[in/out] action_flags
  *   Holds the actions detected until now.
+ * @param[out] actions_n
+ *   pointer to the number of actions counter.
  * @param[in] action
- *   Pointer to the encap action.
- * @param[in] attr
- *   Pointer to flow attributes
+ *   Pointer to the action structure.
+ * @param[in] item_flags
+ *   Holds the items detected.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -2175,41 +2335,73 @@ flow_dv_validate_action_raw_encap(uint64_t action_flags,
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_dv_validate_action_raw_decap(uint64_t action_flags,
-				  const struct rte_flow_action *action,
-				  const struct rte_flow_attr *attr,
-				  struct rte_flow_error *error)
-{
-	const struct rte_flow_action_raw_decap *decap	= action->conf;
+flow_dv_validate_action_raw_encap_decap
+	(struct rte_eth_dev *dev,
+	 const struct rte_flow_action_raw_decap *decap,
+	 const struct rte_flow_action_raw_encap *encap,
+	 const struct rte_flow_attr *attr, uint64_t *action_flags,
+	 int *actions_n, const struct rte_flow_action *action,
+	 uint64_t item_flags, struct rte_flow_error *error)
+{
+	const struct mlx5_priv *priv = dev->data->dev_private;
+	int ret;
 
-	if (action_flags & MLX5_FLOW_ACTION_DROP)
+	if (encap && (!encap->size || !encap->data))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't drop and decap in same flow");
-	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can't have encap action before"
-					  " decap action");
-	if (action_flags & MLX5_FLOW_DECAP_ACTIONS)
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
-					  "can only have a single decap"
-					  " action in a flow");
-	/* decap action is valid on egress only if it is followed by encap */
-	if (attr->egress && decap &&
-	    decap->size > MLX5_ENCAPSULATION_DECISION_SIZE) {
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
-					  NULL, "decap action not supported"
-					  " for egress");
-	} else if (decap && decap->size > MLX5_ENCAPSULATION_DECISION_SIZE &&
-		   (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS)) {
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
-					  NULL,
-					  "can't have decap action "
-					  "after modify action");
+					  "raw encap data cannot be empty");
+	if (decap && encap) {
+		if (decap->size <= MLX5_ENCAPSULATION_DECISION_SIZE &&
+		    encap->size > MLX5_ENCAPSULATION_DECISION_SIZE)
+			/* L3 encap. */
+			decap = NULL;
+		else if (encap->size <=
+			   MLX5_ENCAPSULATION_DECISION_SIZE &&
+			   decap->size >
+			   MLX5_ENCAPSULATION_DECISION_SIZE)
+			/* L3 decap. */
+			encap = NULL;
+		else if (encap->size >
+			   MLX5_ENCAPSULATION_DECISION_SIZE &&
+			   decap->size >
+			   MLX5_ENCAPSULATION_DECISION_SIZE)
+			/* 2 L2 actions: encap and decap. */
+			;
+		else
+			return rte_flow_error_set(error,
+				ENOTSUP,
+				RTE_FLOW_ERROR_TYPE_ACTION,
+				NULL, "unsupported too small "
+				"raw decap and too small raw "
+				"encap combination");
+	}
+	if (decap) {
+		ret = flow_dv_validate_action_decap(dev, *action_flags, action,
+						    item_flags, attr, error);
+		if (ret < 0)
+			return ret;
+		*action_flags |= MLX5_FLOW_ACTION_DECAP;
+		++(*actions_n);
+	}
+	if (encap) {
+		if (encap->size <= MLX5_ENCAPSULATION_DECISION_SIZE)
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  NULL,
+						  "small raw encap size");
+		if (*action_flags & MLX5_FLOW_ACTION_ENCAP)
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  NULL,
+						  "more than one encap action");
+		if (!attr->transfer && priv->representor)
+			return rte_flow_error_set
+					(error, ENOTSUP,
+					 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					 "encap action for VF representor "
+					 "not supported on NIC table");
+		*action_flags |= MLX5_FLOW_ACTION_ENCAP;
+		++(*actions_n);
 	}
 	return 0;
 }
@@ -2248,7 +2440,6 @@ flow_dv_encap_decap_resource_register
 		domain = sh->rx_domain;
 	else
 		domain = sh->tx_domain;
-
 	/* Lookup a matching resource from cache. */
 	LIST_FOREACH(cache_resource, &sh->encaps_decaps, next) {
 		if (resource->reformat_type == cache_resource->reformat_type &&
@@ -2334,6 +2525,8 @@ flow_dv_jump_tbl_resource_register
 		DRV_LOG(DEBUG, "new jump table resource %p: refcnt %d++",
 			(void *)&tbl_data->jump, cnt);
 	} else {
+		/* old jump should not make the table ref++. */
+		flow_dv_tbl_resource_release(dev, &tbl_data->tbl);
 		assert(tbl_data->jump.action);
 		DRV_LOG(DEBUG, "existed jump table resource %p: refcnt %d++",
 			(void *)&tbl_data->jump, cnt);
@@ -2484,7 +2677,7 @@ flow_dv_push_vlan_action_resource_register
 	return 0;
 }
 /**
- * Get the size of specific rte_flow_item_type
+ * Get the size of specific rte_flow_item_type hdr size
  *
  * @param[in] item_type
  *   Tested rte_flow_item_type.
@@ -2493,43 +2686,39 @@ flow_dv_push_vlan_action_resource_register
  *   sizeof struct item_type, 0 if void or irrelevant.
  */
 static size_t
-flow_dv_get_item_len(const enum rte_flow_item_type item_type)
+flow_dv_get_item_hdr_len(const enum rte_flow_item_type item_type)
 {
 	size_t retval;
 
 	switch (item_type) {
 	case RTE_FLOW_ITEM_TYPE_ETH:
-		retval = sizeof(struct rte_flow_item_eth);
+		retval = sizeof(struct rte_ether_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_VLAN:
-		retval = sizeof(struct rte_flow_item_vlan);
+		retval = sizeof(struct rte_vlan_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_IPV4:
-		retval = sizeof(struct rte_flow_item_ipv4);
+		retval = sizeof(struct rte_ipv4_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_IPV6:
-		retval = sizeof(struct rte_flow_item_ipv6);
+		retval = sizeof(struct rte_ipv6_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_UDP:
-		retval = sizeof(struct rte_flow_item_udp);
+		retval = sizeof(struct rte_udp_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_TCP:
-		retval = sizeof(struct rte_flow_item_tcp);
+		retval = sizeof(struct rte_tcp_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
-		retval = sizeof(struct rte_flow_item_vxlan);
+	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+		retval = sizeof(struct rte_vxlan_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_GRE:
-		retval = sizeof(struct rte_flow_item_gre);
-		break;
 	case RTE_FLOW_ITEM_TYPE_NVGRE:
-		retval = sizeof(struct rte_flow_item_nvgre);
-		break;
-	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
-		retval = sizeof(struct rte_flow_item_vxlan_gpe);
+		retval = sizeof(struct rte_gre_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_MPLS:
-		retval = sizeof(struct rte_flow_item_mpls);
+		retval = sizeof(struct rte_mpls_hdr);
 		break;
 	case RTE_FLOW_ITEM_TYPE_VOID: /* Fall through. */
 	default:
@@ -2582,7 +2771,7 @@ flow_dv_convert_encap_data(const struct rte_flow_item *items, uint8_t *buf,
 					  RTE_FLOW_ERROR_TYPE_ACTION,
 					  NULL, "invalid empty data");
 	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
-		len = flow_dv_get_item_len(items->type);
+		len = flow_dv_get_item_hdr_len(items->type);
 		if (len + temp_size > MLX5_ENCAP_MAX_LEN)
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -2799,8 +2988,6 @@ flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
 			(const struct rte_flow_action_raw_encap *)action->conf;
 		res.size = raw_encap_data->size;
 		memcpy(res.buf, raw_encap_data->data, res.size);
-		if (flow_dv_zero_encap_udp_csum(res.buf, error))
-			return -rte_errno;
 	} else {
 		if (action->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP)
 			encap_data =
@@ -2814,6 +3001,8 @@ flow_dv_create_action_l2_encap(struct rte_eth_dev *dev,
 					       &res.size, error))
 			return -rte_errno;
 	}
+	if (flow_dv_zero_encap_udp_csum(res.buf, error))
+		return -rte_errno;
 	if (flow_dv_encap_decap_resource_register(dev, &res, dev_flow, error))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION,
@@ -2907,12 +3096,12 @@ flow_dv_create_action_raw_encap(struct rte_eth_dev *dev,
  *
  * @param[in] dev
  *   Pointer to rte_eth_dev structure.
- * @param[in] vlan_tag
- *   the vlan tag to push to the Ethernet header.
- * @param[in, out] dev_flow
- *   Pointer to the mlx5_flow.
  * @param[in] attr
  *   Pointer to the flow attributes.
+ * @param[in] vlan
+ *   Pointer to the vlan to push to the Ethernet header.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -2962,7 +3151,7 @@ flow_dv_validate_action_modify_hdr(const uint64_t action_flags,
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION_CONF,
 					  NULL, "action configuration not set");
-	if (action_flags & MLX5_FLOW_ENCAP_ACTIONS)
+	if (action_flags & MLX5_FLOW_ACTION_ENCAP)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "can't have encap action before"
@@ -3026,10 +3215,14 @@ flow_dv_validate_action_modify_ipv4(const uint64_t action_flags,
 				    struct rte_flow_error *error)
 {
 	int ret = 0;
+	uint64_t layer;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
 	if (!ret) {
-		if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV4))
+		layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
+				 MLX5_FLOW_LAYER_INNER_L3_IPV4 :
+				 MLX5_FLOW_LAYER_OUTER_L3_IPV4;
+		if (!(item_flags & layer))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL,
@@ -3060,10 +3253,14 @@ flow_dv_validate_action_modify_ipv6(const uint64_t action_flags,
 				    struct rte_flow_error *error)
 {
 	int ret = 0;
+	uint64_t layer;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
 	if (!ret) {
-		if (!(item_flags & MLX5_FLOW_LAYER_L3_IPV6))
+		layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
+				 MLX5_FLOW_LAYER_INNER_L3_IPV6 :
+				 MLX5_FLOW_LAYER_OUTER_L3_IPV6;
+		if (!(item_flags & layer))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL,
@@ -3094,10 +3291,14 @@ flow_dv_validate_action_modify_tp(const uint64_t action_flags,
 				  struct rte_flow_error *error)
 {
 	int ret = 0;
+	uint64_t layer;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
 	if (!ret) {
-		if (!(item_flags & MLX5_FLOW_LAYER_L4))
+		layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
+				 MLX5_FLOW_LAYER_INNER_L4 :
+				 MLX5_FLOW_LAYER_OUTER_L4;
+		if (!(item_flags & layer))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL, "no transport layer "
@@ -3129,10 +3330,14 @@ flow_dv_validate_action_modify_tcp_seq(const uint64_t action_flags,
 				       struct rte_flow_error *error)
 {
 	int ret = 0;
+	uint64_t layer;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
 	if (!ret) {
-		if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP))
+		layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
+				 MLX5_FLOW_LAYER_INNER_L4_TCP :
+				 MLX5_FLOW_LAYER_OUTER_L4_TCP;
+		if (!(item_flags & layer))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL, "no TCP item in"
@@ -3174,10 +3379,14 @@ flow_dv_validate_action_modify_tcp_ack(const uint64_t action_flags,
 				       struct rte_flow_error *error)
 {
 	int ret = 0;
+	uint64_t layer;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
 	if (!ret) {
-		if (!(item_flags & MLX5_FLOW_LAYER_OUTER_L4_TCP))
+		layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
+				 MLX5_FLOW_LAYER_INNER_L4_TCP :
+				 MLX5_FLOW_LAYER_OUTER_L4_TCP;
+		if (!(item_flags & layer))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL, "no TCP item in"
@@ -3218,10 +3427,14 @@ flow_dv_validate_action_modify_ttl(const uint64_t action_flags,
 				   struct rte_flow_error *error)
 {
 	int ret = 0;
+	uint64_t layer;
 
 	ret = flow_dv_validate_action_modify_hdr(action_flags, action, error);
 	if (!ret) {
-		if (!(item_flags & MLX5_FLOW_LAYER_L3))
+		layer = (action_flags & MLX5_FLOW_ACTION_DECAP) ?
+				 MLX5_FLOW_LAYER_INNER_L3 :
+				 MLX5_FLOW_LAYER_OUTER_L3;
+		if (!(item_flags & layer))
 			return rte_flow_error_set(error, EINVAL,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL,
@@ -3273,7 +3486,7 @@ flow_dv_validate_action_jump(const struct rte_flow_action *action,
 	target_group =
 		((const struct rte_flow_action_jump *)action->conf)->group;
 	ret = mlx5_flow_group_to_table(attributes, external, target_group,
-				       &table, error);
+				       true, &table, error);
 	if (ret)
 		return ret;
 	if (attributes->group == target_group)
@@ -3359,21 +3572,24 @@ flow_dv_validate_action_port_id(struct rte_eth_dev *dev,
  *
  * @param dev
  *   Pointer to rte_eth_dev structure.
+ * @param flags
+ *   Flags bits to check if root level.
  *
  * @return
  *   Max number of modify header actions device can support.
  */
-static unsigned int
-flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev)
+static inline unsigned int
+flow_dv_modify_hdr_action_max(struct rte_eth_dev *dev __rte_unused,
+			      uint64_t flags)
 {
 	/*
-	 * There's no way to directly query the max cap. Although it has to be
-	 * acquried by iterative trial, it is a safe assumption that more
-	 * actions are supported by FW if extensive metadata register is
-	 * supported.
+	 * There's no way to directly query the max capacity from FW.
+	 * The maximal value on root table should be assumed to be supported.
 	 */
-	return mlx5_flow_ext_mreg_supported(dev) ? MLX5_MODIFY_NUM :
-						   MLX5_MODIFY_NUM_NO_MREG;
+	if (!(flags & MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL))
+		return MLX5_MAX_MODIFY_NUM;
+	else
+		return MLX5_ROOT_TBL_MODIFY_NUM;
 }
 
 /**
@@ -3402,7 +3618,12 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	const struct rte_flow_action_meter *am = action->conf;
-	struct mlx5_flow_meter *fm = mlx5_flow_meter_find(priv, am->mtr_id);
+	struct mlx5_flow_meter *fm;
+
+	if (!am)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "meter action conf is NULL");
 
 	if (action_flags & MLX5_FLOW_ACTION_METER)
 		return rte_flow_error_set(error, ENOTSUP,
@@ -3417,6 +3638,7 @@ mlx5_flow_validate_action_meter(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 					  NULL,
 					  "meter action not supported");
+	fm = mlx5_flow_meter_find(priv, am->mtr_id);
 	if (!fm)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@@ -3458,8 +3680,12 @@ flow_dv_modify_hdr_resource_register
 	struct mlx5_ibv_shared *sh = priv->sh;
 	struct mlx5_flow_dv_modify_hdr_resource *cache_resource;
 	struct mlx5dv_dr_domain *ns;
+	uint32_t actions_len;
 
-	if (resource->actions_num > flow_dv_modify_hdr_action_max(dev))
+	resource->flags =
+		dev_flow->group ? 0 : MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
+	if (resource->actions_num > flow_dv_modify_hdr_action_max(dev,
+				    resource->flags))
 		return rte_flow_error_set(error, EOVERFLOW,
 					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
 					  "too many modify header items");
@@ -3469,17 +3695,15 @@ flow_dv_modify_hdr_resource_register
 		ns = sh->tx_domain;
 	else
 		ns = sh->rx_domain;
-	resource->flags =
-		dev_flow->group ? 0 : MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
 	/* Lookup a matching resource from cache. */
+	actions_len = resource->actions_num * sizeof(resource->actions[0]);
 	LIST_FOREACH(cache_resource, &sh->modify_cmds, next) {
 		if (resource->ft_type == cache_resource->ft_type &&
 		    resource->actions_num == cache_resource->actions_num &&
 		    resource->flags == cache_resource->flags &&
 		    !memcmp((const void *)resource->actions,
 			    (const void *)cache_resource->actions,
-			    (resource->actions_num *
-					    sizeof(resource->actions[0])))) {
+			    actions_len)) {
 			DRV_LOG(DEBUG, "modify-header resource %p: refcnt %d++",
 				(void *)cache_resource,
 				rte_atomic32_read(&cache_resource->refcnt));
@@ -3489,18 +3713,18 @@ flow_dv_modify_hdr_resource_register
 		}
 	}
 	/* Register new modify-header resource. */
-	cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource), 0);
+	cache_resource = rte_calloc(__func__, 1,
+				    sizeof(*cache_resource) + actions_len, 0);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 					  "cannot allocate resource memory");
 	*cache_resource = *resource;
+	rte_memcpy(cache_resource->actions, resource->actions, actions_len);
 	cache_resource->verbs_action =
 		mlx5_glue->dv_create_flow_action_modify_header
-					(sh->ctx, cache_resource->ft_type,
-					 ns, cache_resource->flags,
-					 cache_resource->actions_num *
-					 sizeof(cache_resource->actions[0]),
+					(sh->ctx, cache_resource->ft_type, ns,
+					 cache_resource->flags, actions_len,
 					 (uint64_t *)cache_resource->actions);
 	if (!cache_resource->verbs_action) {
 		rte_free(cache_resource);
@@ -3846,11 +4070,13 @@ _flow_dv_query_count(struct rte_eth_dev *dev,
  *   The devX counter handle.
  * @param[in] batch
  *   Whether the pool is for counter that was allocated by batch command.
+ * @param[in/out] cont_cur
+ *   Pointer to the container pointer, it will be update in pool resize.
  *
  * @return
- *   A new pool pointer on success, NULL otherwise and rte_errno is set.
+ *   The pool container pointer on success, NULL otherwise and rte_errno is set.
  */
-static struct mlx5_flow_counter_pool *
+static struct mlx5_pools_container *
 flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,
 		    uint32_t batch)
 {
@@ -3884,12 +4110,69 @@ flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,
 	 */
 	rte_atomic64_set(&pool->query_gen, 0x2);
 	TAILQ_INIT(&pool->counters);
-	TAILQ_INSERT_TAIL(&cont->pool_list, pool, next);
+	TAILQ_INSERT_HEAD(&cont->pool_list, pool, next);
 	cont->pools[n_valid] = pool;
 	/* Pool initialization must be updated before host thread access. */
 	rte_cio_wmb();
 	rte_atomic16_add(&cont->n_valid, 1);
-	return pool;
+	return cont;
+}
+/**
+ * Restore skipped counters in the pool.
+ *
+ * As counter pool query requires the first counter dcs
+ * ID start with 4 alinged, if the pool counters with
+ * min_dcs ID are not aligned with 4, the counters will
+ * be skipped.
+ * Once other min_dcs ID less than these skipped counter
+ * dcs ID appears, the skipped counters will be safe to
+ * use.
+ * Should be called when min_dcs is updated.
+ *
+ * @param[in] pool
+ *   Current counter pool.
+ * @param[in] last_min_dcs
+ *   Last min_dcs.
+ */
+static void
+flow_dv_counter_restore(struct mlx5_flow_counter_pool *pool,
+			struct mlx5_devx_obj *last_min_dcs)
+{
+	struct mlx5_flow_counter *cnt;
+	uint32_t offset, new_offset;
+	uint32_t skip_cnt = 0;
+	uint32_t i;
+
+	if (!pool->skip_cnt)
+		return;
+	/*
+	 * If last min_dcs is not valid. The skipped counter may even after
+	 * last min_dcs, set the offset to the whole pool.
+	 */
+	if (last_min_dcs->id & (MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT - 1))
+		offset = MLX5_COUNTERS_PER_POOL;
+	else
+		offset = last_min_dcs->id % MLX5_COUNTERS_PER_POOL;
+	new_offset = pool->min_dcs->id % MLX5_COUNTERS_PER_POOL;
+	/*
+	 * Check the counters from 1 to the last_min_dcs range. Counters
+	 * before new min_dcs indicates pool still has skipped counters.
+	 * Counters be skipped after new min_dcs will be ready to use.
+	 * Offset 0 counter must be empty or min_dcs, start from 1.
+	 */
+	for (i = 1; i < offset; i++) {
+		cnt = &pool->counters_raw[i];
+		if (cnt->skipped) {
+			if (i > new_offset) {
+				cnt->skipped = 0;
+				TAILQ_INSERT_TAIL(&pool->counters, cnt, next);
+			} else {
+				skip_cnt++;
+			}
+		}
+	}
+	if (!skip_cnt)
+		pool->skip_cnt = 0;
 }
 
 /**
@@ -3903,42 +4186,77 @@ flow_dv_pool_create(struct rte_eth_dev *dev, struct mlx5_devx_obj *dcs,
  *   Whether the pool is for counter that was allocated by batch command.
  *
  * @return
- *   The free counter pool pointer and @p cnt_free is set on success,
+ *   The counter container pointer and @p cnt_free is set on success,
  *   NULL otherwise and rte_errno is set.
  */
-static struct mlx5_flow_counter_pool *
+static struct mlx5_pools_container *
 flow_dv_counter_pool_prepare(struct rte_eth_dev *dev,
 			     struct mlx5_flow_counter **cnt_free,
 			     uint32_t batch)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_pools_container *cont;
 	struct mlx5_flow_counter_pool *pool;
 	struct mlx5_devx_obj *dcs = NULL;
+	struct mlx5_devx_obj *last_min_dcs;
 	struct mlx5_flow_counter *cnt;
 	uint32_t i;
 
+	cont = MLX5_CNT_CONTAINER(priv->sh, batch, 0);
 	if (!batch) {
+retry:
 		/* bulk_bitmap must be 0 for single counter allocation. */
 		dcs = mlx5_devx_cmd_flow_counter_alloc(priv->sh->ctx, 0);
 		if (!dcs)
 			return NULL;
-		pool = flow_dv_find_pool_by_id
-			(MLX5_CNT_CONTAINER(priv->sh, batch, 0), dcs->id);
+		pool = flow_dv_find_pool_by_id(cont, dcs->id);
 		if (!pool) {
-			pool = flow_dv_pool_create(dev, dcs, batch);
-			if (!pool) {
+			cont = flow_dv_pool_create(dev, dcs, batch);
+			if (!cont) {
 				mlx5_devx_cmd_destroy(dcs);
 				return NULL;
 			}
-		} else if (dcs->id < pool->min_dcs->id) {
+			pool = TAILQ_FIRST(&cont->pool_list);
+		} else if (((dcs->id < pool->min_dcs->id) ||
+			   pool->min_dcs->id &
+			   (MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT - 1)) &&
+			   !(dcs->id &
+			   (MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT - 1))) {
+			/*
+			 * Update the pool min_dcs only if current dcs is
+			 * valid and exist min_dcs is not valid or greater
+			 * than new dcs.
+			 */
+			last_min_dcs = pool->min_dcs;
 			rte_atomic64_set(&pool->a64_dcs,
 					 (int64_t)(uintptr_t)dcs);
+			/*
+			 * Restore any skipped counters if the new min_dcs
+			 * ID is smaller or min_dcs is not valid.
+			 */
+			if (dcs->id < last_min_dcs->id ||
+			    last_min_dcs->id &
+			    (MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT - 1))
+				flow_dv_counter_restore(pool, last_min_dcs);
 		}
 		cnt = &pool->counters_raw[dcs->id % MLX5_COUNTERS_PER_POOL];
-		TAILQ_INSERT_HEAD(&pool->counters, cnt, next);
 		cnt->dcs = dcs;
+		/*
+		 * If min_dcs is not valid, it means the new allocated dcs
+		 * also fail to become the valid min_dcs, just skip it.
+		 * Or if min_dcs is valid, and new dcs ID is smaller than
+		 * min_dcs, but not become the min_dcs, also skip it.
+		 */
+		if (pool->min_dcs->id &
+		    (MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT - 1) ||
+		    dcs->id < pool->min_dcs->id) {
+			cnt->skipped = 1;
+			pool->skip_cnt = 1;
+			goto retry;
+		}
+		TAILQ_INSERT_HEAD(&pool->counters, cnt, next);
 		*cnt_free = cnt;
-		return pool;
+		return cont;
 	}
 	/* bulk_bitmap is in 128 counters units. */
 	if (priv->config.hca_attr.flow_counter_bulk_alloc_bitmap & 0x4)
@@ -3947,18 +4265,19 @@ flow_dv_counter_pool_prepare(struct rte_eth_dev *dev,
 		rte_errno = ENODATA;
 		return NULL;
 	}
-	pool = flow_dv_pool_create(dev, dcs, batch);
-	if (!pool) {
+	cont = flow_dv_pool_create(dev, dcs, batch);
+	if (!cont) {
 		mlx5_devx_cmd_destroy(dcs);
 		return NULL;
 	}
+	pool = TAILQ_FIRST(&cont->pool_list);
 	for (i = 0; i < MLX5_COUNTERS_PER_POOL; ++i) {
 		cnt = &pool->counters_raw[i];
 		cnt->pool = pool;
 		TAILQ_INSERT_HEAD(&pool->counters, cnt, next);
 	}
 	*cnt_free = &pool->counters_raw[0];
-	return pool;
+	return cont;
 }
 
 /**
@@ -4059,9 +4378,10 @@ flow_dv_counter_alloc(struct rte_eth_dev *dev, uint32_t shared, uint32_t id,
 		cnt_free = NULL;
 	}
 	if (!cnt_free) {
-		pool = flow_dv_counter_pool_prepare(dev, &cnt_free, batch);
-		if (!pool)
+		cont = flow_dv_counter_pool_prepare(dev, &cnt_free, batch);
+		if (!cont)
 			return NULL;
+		pool = TAILQ_FIRST(&cont->pool_list);
 	}
 	cnt_free->batch = batch;
 	/* Create a DV counter action only in the first time usage. */
@@ -4146,7 +4466,9 @@ flow_dv_counter_release(struct rte_eth_dev *dev,
  *   Pointer to error structure.
  *
  * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
+ *   - 0 on success and non root table.
+ *   - 1 on success and root table.
+ *   - a negative errno value otherwise and rte_errno is set.
  */
 static int
 flow_dv_validate_attributes(struct rte_eth_dev *dev,
@@ -4156,6 +4478,7 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	uint32_t priority_max = priv->config.flow_prio - 1;
+	int ret = 0;
 
 #ifndef HAVE_MLX5DV_DR
 	if (attributes->group)
@@ -4164,14 +4487,15 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
 					  NULL,
 					  "groups are not supported");
 #else
-	uint32_t table;
-	int ret;
+	uint32_t table = 0;
 
 	ret = mlx5_flow_group_to_table(attributes, external,
-				       attributes->group,
+				       attributes->group, !!priv->fdb_def_rule,
 				       &table, error);
 	if (ret)
 		return ret;
+	if (!table)
+		ret = MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL;
 #endif
 	if (attributes->priority != MLX5_FLOW_PRIO_RSVD &&
 	    attributes->priority >= priority_max)
@@ -4201,7 +4525,7 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ATTR, NULL,
 					  "must specify exactly one of "
 					  "ingress or egress");
-	return 0;
+	return ret;
 }
 
 /**
@@ -4217,6 +4541,8 @@ flow_dv_validate_attributes(struct rte_eth_dev *dev,
  *   Pointer to the list of actions.
  * @param[in] external
  *   This flow rule is created by request external to PMD.
+ * @param[in] hairpin
+ *   Number of hairpin TX actions, 0 means classic flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -4227,7 +4553,7 @@ static int
 flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		 const struct rte_flow_item items[],
 		 const struct rte_flow_action actions[],
-		 bool external, struct rte_flow_error *error)
+		 bool external, int hairpin, struct rte_flow_error *error)
 {
 	int ret;
 	uint64_t action_flags = 0;
@@ -4236,7 +4562,11 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 	uint8_t next_protocol = 0xff;
 	uint16_t ether_type = 0;
 	int actions_n = 0;
+	uint8_t item_ipv6_proto = 0;
 	const struct rte_flow_item *gre_item = NULL;
+	const struct rte_flow_action_raw_decap *decap;
+	const struct rte_flow_action_raw_encap *encap;
+	const struct rte_flow_action_rss *rss;
 	struct rte_flow_item_tcp nic_tcp_mask = {
 		.hdr = {
 			.tcp_flags = 0xFF,
@@ -4246,12 +4576,17 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 	};
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_dev_config *dev_conf = &priv->config;
+	uint16_t queue_index = 0xFFFF;
+	const struct rte_flow_item_vlan *vlan_m = NULL;
+	int16_t rw_act_num = 0;
+	uint64_t is_root;
 
 	if (items == NULL)
 		return -1;
 	ret = flow_dv_validate_attributes(dev, attr, external, error);
 	if (ret < 0)
 		return ret;
+	is_root = (uint64_t)ret;
 	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
 		int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
 		int type = items->type;
@@ -4286,8 +4621,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_VLAN:
-			ret = mlx5_flow_validate_item_vlan(items, item_flags,
-							   dev, error);
+			ret = flow_dv_validate_item_vlan(items, item_flags,
+							 dev, error);
 			if (ret < 0)
 				return ret;
 			last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN :
@@ -4303,6 +4638,9 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			} else {
 				ether_type = 0;
 			}
+			/* Store outer VLAN mask for of_push_vlan action. */
+			if (!tunnel)
+				vlan_m = items->mask;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
 			mlx5_flow_tunnel_ip_check(items, next_protocol,
@@ -4343,6 +4681,9 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			if (items->mask != NULL &&
 			    ((const struct rte_flow_item_ipv6 *)
 			     items->mask)->hdr.proto) {
+				item_ipv6_proto =
+					((const struct rte_flow_item_ipv6 *)
+					 items->spec)->hdr.proto;
 				next_protocol =
 					((const struct rte_flow_item_ipv6 *)
 					 items->spec)->hdr.proto;
@@ -4418,7 +4759,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 							     error);
 			if (ret < 0)
 				return ret;
-			last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
+			last_item = MLX5_FLOW_LAYER_GENEVE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_MPLS:
 			ret = mlx5_flow_validate_item_mpls(dev, items,
@@ -4457,6 +4798,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 							    error);
 			if (ret < 0)
 				return ret;
+			item_ipv6_proto = IPPROTO_ICMPV6;
 			last_item = MLX5_FLOW_LAYER_ICMP6;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TAG:
@@ -4512,6 +4854,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 				action_flags |= MLX5_FLOW_ACTION_FLAG;
 				++actions_n;
 			}
+			rw_act_num += MLX5_ACT_NUM_SET_MARK;
 			break;
 		case RTE_FLOW_ACTION_TYPE_MARK:
 			ret = flow_dv_validate_action_mark(dev, actions,
@@ -4530,6 +4873,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 				action_flags |= MLX5_FLOW_ACTION_MARK;
 				++actions_n;
 			}
+			rw_act_num += MLX5_ACT_NUM_SET_MARK;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_META:
 			ret = flow_dv_validate_action_set_meta(dev, actions,
@@ -4541,6 +4885,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
 				++actions_n;
 			action_flags |= MLX5_FLOW_ACTION_SET_META;
+			rw_act_num += MLX5_ACT_NUM_SET_META;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_TAG:
 			ret = flow_dv_validate_action_set_tag(dev, actions,
@@ -4552,6 +4897,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
 				++actions_n;
 			action_flags |= MLX5_FLOW_ACTION_SET_TAG;
+			rw_act_num += MLX5_ACT_NUM_SET_TAG;
 			break;
 		case RTE_FLOW_ACTION_TYPE_DROP:
 			ret = mlx5_flow_validate_action_drop(action_flags,
@@ -4567,16 +4913,21 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 							      attr, error);
 			if (ret < 0)
 				return ret;
+			queue_index = ((const struct rte_flow_action_queue *)
+							(actions->conf))->index;
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
+			rss = actions->conf;
 			ret = mlx5_flow_validate_action_rss(actions,
 							    action_flags, dev,
 							    attr, item_flags,
 							    error);
 			if (ret < 0)
 				return ret;
+			if (rss != NULL && rss->queue_num)
+				queue_index = rss->queue[0];
 			action_flags |= MLX5_FLOW_ACTION_RSS;
 			++actions_n;
 			break;
@@ -4598,8 +4949,9 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
-			ret = flow_dv_validate_action_push_vlan(action_flags,
-								item_flags,
+			ret = flow_dv_validate_action_push_vlan(dev,
+								action_flags,
+								vlan_m,
 								actions, attr,
 								error);
 			if (ret < 0)
@@ -4623,49 +4975,53 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 				return ret;
 			/* Count VID with push_vlan command. */
 			action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
+			rw_act_num += MLX5_ACT_NUM_MDF_VID;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
-			ret = flow_dv_validate_action_l2_encap(action_flags,
+			ret = flow_dv_validate_action_l2_encap(dev,
+							       action_flags,
 							       actions, attr,
 							       error);
 			if (ret < 0)
 				return ret;
-			action_flags |= actions->type ==
-					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
-					MLX5_FLOW_ACTION_VXLAN_ENCAP :
-					MLX5_FLOW_ACTION_NVGRE_ENCAP;
+			action_flags |= MLX5_FLOW_ACTION_ENCAP;
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
-			ret = flow_dv_validate_action_l2_decap(action_flags,
-							       attr, error);
+			ret = flow_dv_validate_action_decap(dev, action_flags,
+							    actions, item_flags,
+							    attr, error);
 			if (ret < 0)
 				return ret;
-			action_flags |= actions->type ==
-					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
-					MLX5_FLOW_ACTION_VXLAN_DECAP :
-					MLX5_FLOW_ACTION_NVGRE_DECAP;
+			action_flags |= MLX5_FLOW_ACTION_DECAP;
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
-			ret = flow_dv_validate_action_raw_encap(action_flags,
-								actions, attr,
-								error);
+			ret = flow_dv_validate_action_raw_encap_decap
+				(dev, NULL, actions->conf, attr, &action_flags,
+				 &actions_n, actions, item_flags, error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
-			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
-			ret = flow_dv_validate_action_raw_decap(action_flags,
-								actions, attr,
-								error);
+			decap = actions->conf;
+			while ((++actions)->type == RTE_FLOW_ACTION_TYPE_VOID)
+				;
+			if (actions->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
+				encap = NULL;
+				actions--;
+			} else {
+				encap = actions->conf;
+			}
+			ret = flow_dv_validate_action_raw_encap_decap
+					   (dev,
+					    decap ? decap : &empty_decap, encap,
+					    attr, &action_flags, &actions_n,
+					    actions, item_flags, error);
 			if (ret < 0)
 				return ret;
-			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
-			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
@@ -4682,8 +5038,15 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
 						MLX5_FLOW_ACTION_SET_MAC_SRC :
 						MLX5_FLOW_ACTION_SET_MAC_DST;
+			/*
+			 * Even if the source and destination MAC addresses have
+			 * overlap in the header with 4B alignment, the convert
+			 * function will handle them separately and 4 SW actions
+			 * will be created. And 2 actions will be added each
+			 * time no matter how many bytes of address will be set.
+			 */
+			rw_act_num += MLX5_ACT_NUM_MDF_MAC;
 			break;
-
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
 			ret = flow_dv_validate_action_modify_ipv4(action_flags,
@@ -4699,6 +5062,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
 						MLX5_FLOW_ACTION_SET_IPV4_SRC :
 						MLX5_FLOW_ACTION_SET_IPV4_DST;
+			rw_act_num += MLX5_ACT_NUM_MDF_IPV4;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
@@ -4708,6 +5072,12 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 								  error);
 			if (ret < 0)
 				return ret;
+			if (item_ipv6_proto == IPPROTO_ICMPV6)
+				return rte_flow_error_set(error, ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION,
+					actions,
+					"Can't change header "
+					"with ICMPv6 proto");
 			/* Count all modify-header actions as one action. */
 			if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
 				++actions_n;
@@ -4715,6 +5085,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
 						MLX5_FLOW_ACTION_SET_IPV6_SRC :
 						MLX5_FLOW_ACTION_SET_IPV6_DST;
+			rw_act_num += MLX5_ACT_NUM_MDF_IPV6;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
@@ -4731,6 +5102,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
 						MLX5_FLOW_ACTION_SET_TP_SRC :
 						MLX5_FLOW_ACTION_SET_TP_DST;
+			rw_act_num += MLX5_ACT_NUM_MDF_PORT;
 			break;
 		case RTE_FLOW_ACTION_TYPE_DEC_TTL:
 		case RTE_FLOW_ACTION_TYPE_SET_TTL:
@@ -4747,6 +5119,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_SET_TTL ?
 						MLX5_FLOW_ACTION_SET_TTL :
 						MLX5_FLOW_ACTION_DEC_TTL;
+			rw_act_num += MLX5_ACT_NUM_MDF_TTL;
 			break;
 		case RTE_FLOW_ACTION_TYPE_JUMP:
 			ret = flow_dv_validate_action_jump(actions,
@@ -4774,6 +5147,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
 						MLX5_FLOW_ACTION_INC_TCP_SEQ :
 						MLX5_FLOW_ACTION_DEC_TCP_SEQ;
+			rw_act_num += MLX5_ACT_NUM_MDF_TCPSEQ;
 			break;
 		case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
 		case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
@@ -4791,10 +5165,13 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 					RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
 						MLX5_FLOW_ACTION_INC_TCP_ACK :
 						MLX5_FLOW_ACTION_DEC_TCP_ACK;
+			rw_act_num += MLX5_ACT_NUM_MDF_TCPACK;
 			break;
-		case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
 		case MLX5_RTE_FLOW_ACTION_TYPE_MARK:
+			break;
+		case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
 		case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
+			rw_act_num += MLX5_ACT_NUM_SET_TAG;
 			break;
 		case RTE_FLOW_ACTION_TYPE_METER:
 			ret = mlx5_flow_validate_action_meter(dev,
@@ -4805,6 +5182,8 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_METER;
 			++actions_n;
+			/* Meter action will add one more TAG action. */
+			rw_act_num += MLX5_ACT_NUM_SET_TAG;
 			break;
 		default:
 			return rte_flow_error_set(error, ENOTSUP,
@@ -4813,13 +5192,18 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 						  "action not supported");
 		}
 	}
-	if ((action_flags & MLX5_FLOW_LAYER_TUNNEL) &&
-	    (action_flags & MLX5_FLOW_VLAN_ACTIONS))
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
-					  actions,
-					  "can't have vxlan and vlan"
-					  " actions in the same rule");
+	/*
+	 * Validate the drop action mutual exclusion with other actions.
+	 * Drop action is mutually-exclusive with any other action, except for
+	 * Count action.
+	 */
+	if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
+	    (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT)))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "Drop action is mutually-exclusive "
+					  "with any other action, except for "
+					  "Count action");
 	/* Eswitch has few restrictions on using items and actions */
 	if (attr->transfer) {
 		if (!mlx5_flow_ext_mreg_supported(dev) &&
@@ -4856,6 +5240,54 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 						  actions,
 						  "no fate action is found");
 	}
+	/* Continue validation for Xcap and VLAN actions.*/
+	if ((action_flags & (MLX5_FLOW_XCAP_ACTIONS |
+			     MLX5_FLOW_VLAN_ACTIONS)) &&
+	    (queue_index == 0xFFFF ||
+	     mlx5_rxq_get_type(dev, queue_index) != MLX5_RXQ_TYPE_HAIRPIN)) {
+		if ((action_flags & MLX5_FLOW_XCAP_ACTIONS) ==
+		    MLX5_FLOW_XCAP_ACTIONS)
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  NULL, "encap and decap "
+						  "combination aren't supported");
+		if (!attr->transfer && attr->ingress) {
+			if (action_flags & MLX5_FLOW_ACTION_ENCAP)
+				return rte_flow_error_set
+						(error, ENOTSUP,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 NULL, "encap is not supported"
+						 " for ingress traffic");
+			else if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN)
+				return rte_flow_error_set
+						(error, ENOTSUP,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 NULL, "push VLAN action not "
+						 "supported for ingress");
+			else if ((action_flags & MLX5_FLOW_VLAN_ACTIONS) ==
+					MLX5_FLOW_VLAN_ACTIONS)
+				return rte_flow_error_set
+						(error, ENOTSUP,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 NULL, "no support for "
+						 "multiple VLAN actions");
+		}
+	}
+	/* Hairpin flow will add one more TAG action. */
+	if (hairpin > 0)
+		rw_act_num += MLX5_ACT_NUM_SET_TAG;
+	/* extra metadata enabled: one more TAG action will be add. */
+	if (dev_conf->dv_flow_en &&
+	    dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
+	    mlx5_flow_ext_mreg_supported(dev))
+		rw_act_num += MLX5_ACT_NUM_SET_TAG;
+	if ((uint32_t)rw_act_num >
+			flow_dv_modify_hdr_action_max(dev, is_root)) {
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_ACTION,
+					  NULL, "too many header modify"
+					  " actions to support");
+	}
 	return 0;
 }
 
@@ -4984,6 +5416,23 @@ flow_dv_translate_item_eth(void *matcher, void *key,
 	/* The value must be in the range of the mask. */
 	for (i = 0; i < sizeof(eth_m->dst); ++i)
 		l24_v[i] = eth_m->src.addr_bytes[i] & eth_v->src.addr_bytes[i];
+	if (eth_v->type) {
+		/* When ethertype is present set mask for tagged VLAN. */
+		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
+		/* Set value for tagged VLAN if ethertype is 802.1Q. */
+		if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+		    eth_v->type == RTE_BE16(RTE_ETHER_TYPE_QINQ)) {
+			MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag,
+				 1);
+			/* Return here to avoid setting match on ethertype. */
+			return;
+		}
+	}
+	/*
+	 * HW supports match on one Ethertype, the Ethertype following the last
+	 * VLAN tag of the packet (see PRM).
+	 * Set match on ethertype only if ETH header is not followed by VLAN.
+	 */
 	MLX5_SET(fte_match_set_lyr_2_4, headers_m, ethertype,
 		 rte_be_to_cpu_16(eth_m->type));
 	l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, ethertype);
@@ -5017,10 +5466,6 @@ flow_dv_translate_item_vlan(struct mlx5_flow *dev_flow,
 	uint16_t tci_m;
 	uint16_t tci_v;
 
-	if (!vlan_v)
-		return;
-	if (!vlan_m)
-		vlan_m = &rte_flow_item_vlan_mask;
 	if (inner) {
 		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
 					 inner_headers);
@@ -5033,13 +5478,22 @@ flow_dv_translate_item_vlan(struct mlx5_flow *dev_flow,
 		 * This is workaround, masks are not supported,
 		 * and pre-validated.
 		 */
-		dev_flow->dv.vf_vlan.tag =
-			rte_be_to_cpu_16(vlan_v->tci) & 0x0fff;
+		if (vlan_v)
+			dev_flow->dv.vf_vlan.tag =
+					rte_be_to_cpu_16(vlan_v->tci) & 0x0fff;
 	}
-	tci_m = rte_be_to_cpu_16(vlan_m->tci);
-	tci_v = rte_be_to_cpu_16(vlan_m->tci & vlan_v->tci);
+	/*
+	 * When VLAN item exists in flow, mark packet as tagged,
+	 * even if TCI is not specified.
+	 */
 	MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1);
+	if (!vlan_v)
+		return;
+	if (!vlan_m)
+		vlan_m = &rte_flow_item_vlan_mask;
+	tci_m = rte_be_to_cpu_16(vlan_m->tci);
+	tci_v = rte_be_to_cpu_16(vlan_m->tci & vlan_v->tci);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_vid, tci_m);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, tci_v);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_m, first_cfi, tci_m >> 12);
@@ -5061,6 +5515,8 @@ flow_dv_translate_item_vlan(struct mlx5_flow *dev_flow,
  *   Flow matcher value.
  * @param[in] item
  *   Flow pattern to translate.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
  * @param[in] inner
  *   Item is inner pattern.
  * @param[in] group
@@ -5069,6 +5525,7 @@ flow_dv_translate_item_vlan(struct mlx5_flow *dev_flow,
 static void
 flow_dv_translate_item_ipv4(void *matcher, void *key,
 			    const struct rte_flow_item *item,
+			    const uint64_t item_flags,
 			    int inner, uint32_t group)
 {
 	const struct rte_flow_item_ipv4 *ipv4_m = item->mask;
@@ -5101,6 +5558,13 @@ flow_dv_translate_item_ipv4(void *matcher, void *key,
 	else
 		MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_version, 0x4);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 4);
+	/*
+	 * On outer header (which must contains L2), or inner header with L2,
+	 * set cvlan_tag mask bit to mark this packet as untagged.
+	 * This should be done even if item->spec is empty.
+	 */
+	if (!inner || item_flags & MLX5_FLOW_LAYER_INNER_L2)
+		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 	if (!ipv4_v)
 		return;
 	if (!ipv4_m)
@@ -5139,6 +5603,8 @@ flow_dv_translate_item_ipv4(void *matcher, void *key,
  *   Flow matcher value.
  * @param[in] item
  *   Flow pattern to translate.
+ * @param[in] item_flags
+ *   Bit-fields that holds the items detected until now.
  * @param[in] inner
  *   Item is inner pattern.
  * @param[in] group
@@ -5147,6 +5613,7 @@ flow_dv_translate_item_ipv4(void *matcher, void *key,
 static void
 flow_dv_translate_item_ipv6(void *matcher, void *key,
 			    const struct rte_flow_item *item,
+			    const uint64_t item_flags,
 			    int inner, uint32_t group)
 {
 	const struct rte_flow_item_ipv6 *ipv6_m = item->mask;
@@ -5189,6 +5656,13 @@ flow_dv_translate_item_ipv6(void *matcher, void *key,
 	else
 		MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_version, 0x6);
 	MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_version, 6);
+	/*
+	 * On outer header (which must contains L2), or inner header with L2,
+	 * set cvlan_tag mask bit to mark this packet as untagged.
+	 * This should be done even if item->spec is empty.
+	 */
+	if (!inner || item_flags & MLX5_FLOW_LAYER_INNER_L2)
+		MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 	if (!ipv6_v)
 		return;
 	if (!ipv6_m)
@@ -5354,13 +5828,13 @@ flow_dv_translate_item_gre_key(void *matcher, void *key,
 	void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
 	rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
 
+	/* GRE K bit must be on and should already be validated */
+	MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 1);
+	MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
 	if (!key_v)
 		return;
 	if (!key_m)
 		key_m = &gre_key_default_mask;
-	/* GRE K bit must be on and should already be validated */
-	MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 1);
-	MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
 	MLX5_SET(fte_match_set_misc, misc_m, gre_key_h,
 		 rte_be_to_cpu_32(*key_m) >> 8);
 	MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
@@ -5468,8 +5942,8 @@ flow_dv_translate_item_nvgre(void *matcher, void *key,
 	const struct rte_flow_item_nvgre *nvgre_v = item->spec;
 	void *misc_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
 	void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
-	const char *tni_flow_id_m = (const char *)nvgre_m->tni;
-	const char *tni_flow_id_v = (const char *)nvgre_v->tni;
+	const char *tni_flow_id_m;
+	const char *tni_flow_id_v;
 	char *gre_key_m;
 	char *gre_key_v;
 	int size;
@@ -5494,6 +5968,8 @@ flow_dv_translate_item_nvgre(void *matcher, void *key,
 		return;
 	if (!nvgre_m)
 		nvgre_m = &rte_flow_item_nvgre_mask;
+	tni_flow_id_m = (const char *)nvgre_m->tni;
+	tni_flow_id_v = (const char *)nvgre_v->tni;
 	size = sizeof(nvgre_m->tni) + sizeof(nvgre_m->flow_id);
 	gre_key_m = MLX5_ADDR_OF(fte_match_set_misc, misc_m, gre_key_h);
 	gre_key_v = MLX5_ADDR_OF(fte_match_set_misc, misc_v, gre_key_h);
@@ -5558,6 +6034,76 @@ flow_dv_translate_item_vxlan(void *matcher, void *key,
 		vni_v[i] = vni_m[i] & vxlan_v->vni[i];
 }
 
+/**
+ * Add VXLAN-GPE item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+
+static void
+flow_dv_translate_item_vxlan_gpe(void *matcher, void *key,
+				 const struct rte_flow_item *item, int inner)
+{
+	const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask;
+	const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec;
+	void *headers_m;
+	void *headers_v;
+	void *misc_m =
+		MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_3);
+	void *misc_v =
+		MLX5_ADDR_OF(fte_match_param, key, misc_parameters_3);
+	char *vni_m;
+	char *vni_v;
+	uint16_t dport;
+	int size;
+	int i;
+	uint8_t flags_m = 0xff;
+	uint8_t flags_v = 0xc;
+
+	if (inner) {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 inner_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+	} else {
+		headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+					 outer_headers);
+		headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+	}
+	dport = item->type == RTE_FLOW_ITEM_TYPE_VXLAN ?
+		MLX5_UDP_PORT_VXLAN : MLX5_UDP_PORT_VXLAN_GPE;
+	if (!MLX5_GET16(fte_match_set_lyr_2_4, headers_v, udp_dport)) {
+		MLX5_SET(fte_match_set_lyr_2_4, headers_m, udp_dport, 0xFFFF);
+		MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport, dport);
+	}
+	if (!vxlan_v)
+		return;
+	if (!vxlan_m)
+		vxlan_m = &rte_flow_item_vxlan_gpe_mask;
+	size = sizeof(vxlan_m->vni);
+	vni_m = MLX5_ADDR_OF(fte_match_set_misc3, misc_m, outer_vxlan_gpe_vni);
+	vni_v = MLX5_ADDR_OF(fte_match_set_misc3, misc_v, outer_vxlan_gpe_vni);
+	memcpy(vni_m, vxlan_m->vni, size);
+	for (i = 0; i < size; ++i)
+		vni_v[i] = vni_m[i] & vxlan_v->vni[i];
+	if (vxlan_m->flags) {
+		flags_m = vxlan_m->flags;
+		flags_v = vxlan_v->flags;
+	}
+	MLX5_SET(fte_match_set_misc3, misc_m, outer_vxlan_gpe_flags, flags_m);
+	MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_flags, flags_v);
+	MLX5_SET(fte_match_set_misc3, misc_m, outer_vxlan_gpe_next_protocol,
+		 vxlan_m->protocol);
+	MLX5_SET(fte_match_set_misc3, misc_v, outer_vxlan_gpe_next_protocol,
+		 vxlan_v->protocol);
+}
+
 /**
  * Add Geneve item to matcher and to the value.
  *
@@ -5742,6 +6288,7 @@ flow_dv_match_meta_reg(void *matcher, void *key,
 		MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_2);
 	void *misc2_v =
 		MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
+	uint32_t temp;
 
 	data &= mask;
 	switch (reg_type) {
@@ -5754,8 +6301,18 @@ flow_dv_match_meta_reg(void *matcher, void *key,
 		MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b, data);
 		break;
 	case REG_C_0:
-		MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_0, mask);
-		MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, data);
+		/*
+		 * The metadata register C0 field might be divided into
+		 * source vport index and META item value, we should set
+		 * this field according to specified mask, not as whole one.
+		 */
+		temp = MLX5_GET(fte_match_set_misc2, misc2_m, metadata_reg_c_0);
+		temp |= mask;
+		MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_0, temp);
+		temp = MLX5_GET(fte_match_set_misc2, misc2_v, metadata_reg_c_0);
+		temp &= ~mask;
+		temp |= data;
+		MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, temp);
 		break;
 	case REG_C_1:
 		MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_1, mask);
@@ -5825,6 +6382,15 @@ flow_dv_translate_item_mark(struct rte_eth_dev *dev,
 		/* Get the metadata register index for the mark. */
 		reg = mlx5_flow_get_reg_id(dev, MLX5_FLOW_MARK, 0, NULL);
 		assert(reg > 0);
+		if (reg == REG_C_0) {
+			struct mlx5_priv *priv = dev->data->dev_private;
+			uint32_t msk_c0 = priv->sh->dv_regc0_mask;
+			uint32_t shl_c0 = rte_bsf32(msk_c0);
+
+			mask &= msk_c0;
+			mask <<= shl_c0;
+			value <<= shl_c0;
+		}
 		flow_dv_match_meta_reg(matcher, key, reg, value, mask);
 	}
 }
@@ -5857,7 +6423,7 @@ flow_dv_translate_item_meta(struct rte_eth_dev *dev,
 		meta_m = &rte_flow_item_meta_mask;
 	meta_v = (const void *)item->spec;
 	if (meta_v) {
-		enum modify_reg reg;
+		int reg;
 		uint32_t value = meta_v->data;
 		uint32_t mask = meta_m->data;
 
@@ -5875,8 +6441,12 @@ flow_dv_translate_item_meta(struct rte_eth_dev *dev,
 			struct mlx5_priv *priv = dev->data->dev_private;
 			uint32_t msk_c0 = priv->sh->dv_regc0_mask;
 			uint32_t shl_c0 = rte_bsf32(msk_c0);
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+			uint32_t shr_c0 = __builtin_clz(priv->sh->dv_meta_mask);
 
-			msk_c0 = rte_cpu_to_be_32(msk_c0);
+			value >>= shr_c0;
+			mask >>= shr_c0;
+#endif
 			value <<= shl_c0;
 			mask <<= shl_c0;
 			assert(msk_c0);
@@ -5906,6 +6476,8 @@ flow_dv_translate_item_meta_vport(void *matcher, void *key,
 /**
  * Add tag item to matcher
  *
+ * @param[in] dev
+ *   The devich to configure through.
  * @param[in, out] matcher
  *   Flow matcher.
  * @param[in, out] key
@@ -5914,15 +6486,27 @@ flow_dv_translate_item_meta_vport(void *matcher, void *key,
  *   Flow pattern to translate.
  */
 static void
-flow_dv_translate_mlx5_item_tag(void *matcher, void *key,
+flow_dv_translate_mlx5_item_tag(struct rte_eth_dev *dev,
+				void *matcher, void *key,
 				const struct rte_flow_item *item)
 {
 	const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
 	const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
+	uint32_t mask, value;
 
 	assert(tag_v);
-	flow_dv_match_meta_reg(matcher, key, tag_v->id, tag_v->data,
-			       tag_m ? tag_m->data : UINT32_MAX);
+	value = tag_v->data;
+	mask = tag_m ? tag_m->data : UINT32_MAX;
+	if (tag_v->id == REG_C_0) {
+		struct mlx5_priv *priv = dev->data->dev_private;
+		uint32_t msk_c0 = priv->sh->dv_regc0_mask;
+		uint32_t shl_c0 = rte_bsf32(msk_c0);
+
+		mask &= msk_c0;
+		mask <<= shl_c0;
+		value <<= shl_c0;
+	}
+	flow_dv_match_meta_reg(matcher, key, tag_v->id, value, mask);
 }
 
 /**
@@ -6056,6 +6640,12 @@ flow_dv_translate_item_icmp6(void *matcher, void *key,
 		return;
 	if (!icmp6_m)
 		icmp6_m = &rte_flow_item_icmp6_mask;
+	/*
+	 * Force flow only to match the non-fragmented IPv6 ICMPv6 packets.
+	 * If only the protocol is specified, no need to match the frag.
+	 */
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 1);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
 	MLX5_SET(fte_match_set_misc3, misc3_m, icmpv6_type, icmp6_m->type);
 	MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type,
 		 icmp6_v->type & icmp6_m->type);
@@ -6103,6 +6693,12 @@ flow_dv_translate_item_icmp(void *matcher, void *key,
 		return;
 	if (!icmp_m)
 		icmp_m = &rte_flow_item_icmp_mask;
+	/*
+	 * Force flow only to match the non-fragmented IPv4 ICMP packets.
+	 * If only the protocol is specified, no need to match the frag.
+	 */
+	MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 1);
+	MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
 	MLX5_SET(fte_match_set_misc3, misc3_m, icmp_type,
 		 icmp_m->hdr.icmp_type);
 	MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type,
@@ -6618,10 +7214,13 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 	};
 	int actions_n = 0;
 	bool actions_end = false;
-	struct mlx5_flow_dv_modify_hdr_resource mhdr_res = {
-		.ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
-					  MLX5DV_FLOW_TABLE_TYPE_NIC_RX
-	};
+	union {
+		struct mlx5_flow_dv_modify_hdr_resource res;
+		uint8_t len[sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
+			    sizeof(struct mlx5_modification_cmd) *
+			    (MLX5_MAX_MODIFY_NUM + 1)];
+	} mhdr_dummy;
+	struct mlx5_flow_dv_modify_hdr_resource *mhdr_res = &mhdr_dummy.res;
 	union flow_dv_attr flow_attr = { .attr = 0 };
 	uint32_t tag_be;
 	union mlx5_flow_tbl_key tbl_key;
@@ -6633,15 +7232,19 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 	uint32_t table;
 	int ret = 0;
 
+	mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
+					   MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
 	ret = mlx5_flow_group_to_table(attr, dev_flow->external, attr->group,
-				       &table, error);
+				       !!priv->fdb_def_rule, &table, error);
 	if (ret)
 		return ret;
 	dev_flow->group = table;
 	if (attr->transfer)
-		mhdr_res.ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
+		mhdr_res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
 	if (priority == MLX5_FLOW_PRIO_RSVD)
 		priority = dev_conf->flow_prio - 1;
+	/* number of actions must be set to 0 in case of dirty stack. */
+	mhdr_res->actions_num = 0;
 	for (; !actions_end ; actions++) {
 		const struct rte_flow_action_queue *queue;
 		const struct rte_flow_action_rss *rss;
@@ -6679,7 +7282,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 				};
 
 				if (flow_dv_convert_action_mark(dev, &mark,
-								&mhdr_res,
+								mhdr_res,
 								error))
 					return -rte_errno;
 				action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
@@ -6701,7 +7304,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 						actions->conf;
 
 				if (flow_dv_convert_action_mark(dev, mark,
-								&mhdr_res,
+								mhdr_res,
 								error))
 					return -rte_errno;
 				action_flags |= MLX5_FLOW_ACTION_MARK_EXT;
@@ -6722,7 +7325,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_META:
 			if (flow_dv_convert_action_set_meta
-				(dev, &mhdr_res, attr,
+				(dev, mhdr_res, attr,
 				 (const struct rte_flow_action_set_meta *)
 				  actions->conf, error))
 				return -rte_errno;
@@ -6730,7 +7333,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_TAG:
 			if (flow_dv_convert_action_set_tag
-				(dev, &mhdr_res,
+				(dev, mhdr_res,
 				 (const struct rte_flow_action_set_tag *)
 				  actions->conf, error))
 				return -rte_errno;
@@ -6798,7 +7401,9 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
 			break;
 		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
-			flow_dev_get_vlan_info_from_items(items, &vlan);
+			if (!(action_flags &
+			      MLX5_FLOW_ACTION_OF_SET_VLAN_VID))
+				flow_dev_get_vlan_info_from_items(items, &vlan);
 			vlan.eth_proto = rte_be_to_cpu_16
 			     ((((const struct rte_flow_action_of_push_vlan *)
 						   actions->conf)->ethertype));
@@ -6830,7 +7435,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			mlx5_update_vlan_vid_pcp(actions, &vlan);
 			/* If no VLAN push - this is a modify header action */
 			if (flow_dv_convert_action_modify_vlan_vid
-						(&mhdr_res, actions, error))
+						(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
 			break;
@@ -6843,10 +7448,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 				return -rte_errno;
 			dev_flow->dv.actions[actions_n++] =
 				dev_flow->dv.encap_decap->verbs_action;
-			action_flags |= actions->type ==
-					RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP ?
-					MLX5_FLOW_ACTION_VXLAN_ENCAP :
-					MLX5_FLOW_ACTION_NVGRE_ENCAP;
+			action_flags |= MLX5_FLOW_ACTION_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
@@ -6856,14 +7458,11 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 				return -rte_errno;
 			dev_flow->dv.actions[actions_n++] =
 				dev_flow->dv.encap_decap->verbs_action;
-			action_flags |= actions->type ==
-					RTE_FLOW_ACTION_TYPE_VXLAN_DECAP ?
-					MLX5_FLOW_ACTION_VXLAN_DECAP :
-					MLX5_FLOW_ACTION_NVGRE_DECAP;
+			action_flags |= MLX5_FLOW_ACTION_DECAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
 			/* Handle encap with preceding decap. */
-			if (action_flags & MLX5_FLOW_ACTION_RAW_DECAP) {
+			if (action_flags & MLX5_FLOW_ACTION_DECAP) {
 				if (flow_dv_create_action_raw_encap
 					(dev, actions, dev_flow, attr, error))
 					return -rte_errno;
@@ -6878,15 +7477,11 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 				dev_flow->dv.actions[actions_n++] =
 					dev_flow->dv.encap_decap->verbs_action;
 			}
-			action_flags |= MLX5_FLOW_ACTION_RAW_ENCAP;
+			action_flags |= MLX5_FLOW_ACTION_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
-			/* Check if this decap is followed by encap. */
-			for (; action->type != RTE_FLOW_ACTION_TYPE_END &&
-			       action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP;
-			       action++) {
-			}
-			/* Handle decap only if it isn't followed by encap. */
+			while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)
+				;
 			if (action->type != RTE_FLOW_ACTION_TYPE_RAW_ENCAP) {
 				if (flow_dv_create_action_l2_decap
 				    (dev, dev_flow, attr->transfer, error))
@@ -6895,13 +7490,14 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 					dev_flow->dv.encap_decap->verbs_action;
 			}
 			/* If decap is followed by encap, handle it at encap. */
-			action_flags |= MLX5_FLOW_ACTION_RAW_DECAP;
+			action_flags |= MLX5_FLOW_ACTION_DECAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_JUMP:
 			jump_data = action->conf;
 			ret = mlx5_flow_group_to_table(attr, dev_flow->external,
-						       jump_data->group, &table,
-						       error);
+						       jump_data->group,
+						       !!priv->fdb_def_rule,
+						       &table, error);
 			if (ret)
 				return ret;
 			tbl = flow_dv_tbl_resource_get(dev, table,
@@ -6929,7 +7525,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
 			if (flow_dv_convert_action_modify_mac
-					(&mhdr_res, actions, error))
+					(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= actions->type ==
 					RTE_FLOW_ACTION_TYPE_SET_MAC_SRC ?
@@ -6939,7 +7535,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
 			if (flow_dv_convert_action_modify_ipv4
-					(&mhdr_res, actions, error))
+					(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= actions->type ==
 					RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC ?
@@ -6949,7 +7545,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_IPV6_DST:
 			if (flow_dv_convert_action_modify_ipv6
-					(&mhdr_res, actions, error))
+					(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= actions->type ==
 					RTE_FLOW_ACTION_TYPE_SET_IPV6_SRC ?
@@ -6959,8 +7555,9 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ACTION_TYPE_SET_TP_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_TP_DST:
 			if (flow_dv_convert_action_modify_tp
-					(&mhdr_res, actions, items,
-					 &flow_attr, error))
+					(mhdr_res, actions, items,
+					 &flow_attr, dev_flow, !!(action_flags &
+					 MLX5_FLOW_ACTION_DECAP), error))
 				return -rte_errno;
 			action_flags |= actions->type ==
 					RTE_FLOW_ACTION_TYPE_SET_TP_SRC ?
@@ -6969,21 +7566,24 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			break;
 		case RTE_FLOW_ACTION_TYPE_DEC_TTL:
 			if (flow_dv_convert_action_modify_dec_ttl
-					(&mhdr_res, items, &flow_attr, error))
+					(mhdr_res, items, &flow_attr, dev_flow,
+					 !!(action_flags &
+					 MLX5_FLOW_ACTION_DECAP), error))
 				return -rte_errno;
 			action_flags |= MLX5_FLOW_ACTION_DEC_TTL;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_TTL:
 			if (flow_dv_convert_action_modify_ttl
-					(&mhdr_res, actions, items,
-					 &flow_attr, error))
+					(mhdr_res, actions, items, &flow_attr,
+					 dev_flow, !!(action_flags &
+					 MLX5_FLOW_ACTION_DECAP), error))
 				return -rte_errno;
 			action_flags |= MLX5_FLOW_ACTION_SET_TTL;
 			break;
 		case RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ:
 		case RTE_FLOW_ACTION_TYPE_DEC_TCP_SEQ:
 			if (flow_dv_convert_action_modify_tcp_seq
-					(&mhdr_res, actions, error))
+					(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= actions->type ==
 					RTE_FLOW_ACTION_TYPE_INC_TCP_SEQ ?
@@ -6994,7 +7594,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ACTION_TYPE_INC_TCP_ACK:
 		case RTE_FLOW_ACTION_TYPE_DEC_TCP_ACK:
 			if (flow_dv_convert_action_modify_tcp_ack
-					(&mhdr_res, actions, error))
+					(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= actions->type ==
 					RTE_FLOW_ACTION_TYPE_INC_TCP_ACK ?
@@ -7003,13 +7603,13 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			break;
 		case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
 			if (flow_dv_convert_action_set_reg
-					(&mhdr_res, actions, error))
+					(mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= MLX5_FLOW_ACTION_SET_TAG;
 			break;
 		case MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG:
 			if (flow_dv_convert_action_copy_mreg
-					(dev, &mhdr_res, actions, error))
+					(dev, mhdr_res, actions, error))
 				return -rte_errno;
 			action_flags |= MLX5_FLOW_ACTION_SET_TAG;
 			break;
@@ -7034,10 +7634,10 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			break;
 		case RTE_FLOW_ACTION_TYPE_END:
 			actions_end = true;
-			if (mhdr_res.actions_num) {
+			if (mhdr_res->actions_num) {
 				/* create modify action if needed. */
 				if (flow_dv_modify_hdr_resource_register
-					(dev, &mhdr_res, dev_flow, error))
+					(dev, mhdr_res, dev_flow, error))
 					return -rte_errno;
 				dev_flow->dv.actions[modify_action_position] =
 					dev_flow->dv.modify_hdr->verbs_action;
@@ -7046,7 +7646,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		default:
 			break;
 		}
-		if (mhdr_res.actions_num &&
+		if (mhdr_res->actions_num &&
 		    modify_action_position == UINT32_MAX)
 			modify_action_position = actions_n++;
 	}
@@ -7083,7 +7683,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			mlx5_flow_tunnel_ip_check(items, next_protocol,
 						  &item_flags, &tunnel);
 			flow_dv_translate_item_ipv4(match_mask, match_value,
-						    items, tunnel,
+						    items, item_flags, tunnel,
 						    dev_flow->group);
 			matcher.priority = MLX5_PRIORITY_MAP_L3;
 			dev_flow->hash_fields |=
@@ -7111,7 +7711,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			mlx5_flow_tunnel_ip_check(items, next_protocol,
 						  &item_flags, &tunnel);
 			flow_dv_translate_item_ipv6(match_mask, match_value,
-						    items, tunnel,
+						    items, item_flags, tunnel,
 						    dev_flow->group);
 			matcher.priority = MLX5_PRIORITY_MAP_L3;
 			dev_flow->hash_fields |=
@@ -7162,6 +7762,8 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ITEM_TYPE_GRE:
 			flow_dv_translate_item_gre(match_mask, match_value,
 						   items, tunnel);
+			matcher.priority = flow->rss.level >= 2 ?
+				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GRE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
@@ -7172,26 +7774,37 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ITEM_TYPE_NVGRE:
 			flow_dv_translate_item_nvgre(match_mask, match_value,
 						     items, tunnel);
+			matcher.priority = flow->rss.level >= 2 ?
+				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GRE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 			flow_dv_translate_item_vxlan(match_mask, match_value,
 						     items, tunnel);
+			matcher.priority = flow->rss.level >= 2 ?
+				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_VXLAN;
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
-			flow_dv_translate_item_vxlan(match_mask, match_value,
-						     items, tunnel);
+			flow_dv_translate_item_vxlan_gpe(match_mask,
+							 match_value, items,
+							 tunnel);
+			matcher.priority = flow->rss.level >= 2 ?
+				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_GENEVE:
 			flow_dv_translate_item_geneve(match_mask, match_value,
 						      items, tunnel);
+			matcher.priority = flow->rss.level >= 2 ?
+				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GENEVE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_MPLS:
 			flow_dv_translate_item_mpls(match_mask, match_value,
 						    items, last_item, tunnel);
+			matcher.priority = flow->rss.level >= 2 ?
+				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_MPLS;
 			break;
 		case RTE_FLOW_ITEM_TYPE_MARK:
@@ -7220,7 +7833,7 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 			last_item = MLX5_FLOW_ITEM_TAG;
 			break;
 		case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
-			flow_dv_translate_mlx5_item_tag(match_mask,
+			flow_dv_translate_mlx5_item_tag(dev, match_mask,
 							match_value, items);
 			last_item = MLX5_FLOW_ITEM_TAG;
 			break;
@@ -7236,13 +7849,13 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 		item_flags |= last_item;
 	}
 	/*
-	 * In case of ingress traffic when E-Switch mode is enabled,
-	 * we have two cases where we need to set the source port manually.
+	 * When E-Switch mode is enabled, we have two cases where we need to
+	 * set the source port manually.
 	 * The first one, is in case of Nic steering rule, and the second is
 	 * E-Switch rule where no port_id item was found. In both cases
 	 * the source port is set according the current port in use.
 	 */
-	if ((attr->ingress && !(item_flags & MLX5_FLOW_ITEM_PORT_ID)) &&
+	if (!(item_flags & MLX5_FLOW_ITEM_PORT_ID) &&
 	    (priv->representor || priv->master)) {
 		if (flow_dv_translate_item_port_id(dev, match_mask,
 						   match_value, NULL))
@@ -7250,7 +7863,11 @@ __flow_dv_translate(struct rte_eth_dev *dev,
 	}
 	assert(!flow_dv_check_valid_spec(matcher.mask.buf,
 					 dev_flow->dv.value.buf));
-	dev_flow->layers = item_flags;
+	/*
+	 * Layers may be already initialized from prefix flow if this dev_flow
+	 * is the suffix flow.
+	 */
+	dev_flow->layers |= item_flags;
 	/* Register matcher. */
 	matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
 				    matcher.mask.size);
@@ -7779,8 +8396,9 @@ flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev,
 		claim_zero(mlx5_glue->dv_destroy_flow_matcher
 			  (mtd->egress.any_matcher));
 	if (mtd->egress.tbl)
-		claim_zero(flow_dv_tbl_resource_release(dev,
-							mtd->egress.tbl));
+		flow_dv_tbl_resource_release(dev, mtd->egress.tbl);
+	if (mtd->egress.sfx_tbl)
+		flow_dv_tbl_resource_release(dev, mtd->egress.sfx_tbl);
 	if (mtd->ingress.color_matcher)
 		claim_zero(mlx5_glue->dv_destroy_flow_matcher
 			  (mtd->ingress.color_matcher));
@@ -7788,8 +8406,9 @@ flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev,
 		claim_zero(mlx5_glue->dv_destroy_flow_matcher
 			  (mtd->ingress.any_matcher));
 	if (mtd->ingress.tbl)
-		claim_zero(flow_dv_tbl_resource_release(dev,
-							mtd->ingress.tbl));
+		flow_dv_tbl_resource_release(dev, mtd->ingress.tbl);
+	if (mtd->ingress.sfx_tbl)
+		flow_dv_tbl_resource_release(dev, mtd->ingress.sfx_tbl);
 	if (mtd->transfer.color_matcher)
 		claim_zero(mlx5_glue->dv_destroy_flow_matcher
 			  (mtd->transfer.color_matcher));
@@ -7797,8 +8416,9 @@ flow_dv_destroy_mtr_tbl(struct rte_eth_dev *dev,
 		claim_zero(mlx5_glue->dv_destroy_flow_matcher
 			  (mtd->transfer.any_matcher));
 	if (mtd->transfer.tbl)
-		claim_zero(flow_dv_tbl_resource_release(dev,
-							mtd->transfer.tbl));
+		flow_dv_tbl_resource_release(dev, mtd->transfer.tbl);
+	if (mtd->transfer.sfx_tbl)
+		flow_dv_tbl_resource_release(dev, mtd->transfer.sfx_tbl);
 	if (mtd->drop_actn)
 		claim_zero(mlx5_glue->destroy_flow_action(mtd->drop_actn));
 	rte_free(mtd);
@@ -7846,31 +8466,16 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,
 		.match_mask = (void *)&mask,
 	};
 	void *actions[METER_ACTIONS];
-	struct mlx5_flow_tbl_resource **sfx_tbl;
 	struct mlx5_meter_domain_info *dtb;
 	struct rte_flow_error error;
 	int i = 0;
 
-	if (transfer) {
-		sfx_tbl = &sh->fdb_mtr_sfx_tbl;
+	if (transfer)
 		dtb = &mtb->transfer;
-	} else if (egress) {
-		sfx_tbl = &sh->tx_mtr_sfx_tbl;
+	else if (egress)
 		dtb = &mtb->egress;
-	} else {
-		sfx_tbl = &sh->rx_mtr_sfx_tbl;
+	else
 		dtb = &mtb->ingress;
-	}
-	/* If the suffix table in missing, create it. */
-	if (!(*sfx_tbl)) {
-		*sfx_tbl = flow_dv_tbl_resource_get(dev,
-						MLX5_FLOW_TABLE_LEVEL_SUFFIX,
-						egress, transfer, &error);
-		if (!(*sfx_tbl)) {
-			DRV_LOG(ERR, "Failed to create meter suffix table.");
-			return -1;
-		}
-	}
 	/* Create the meter table with METER level. */
 	dtb->tbl = flow_dv_tbl_resource_get(dev, MLX5_FLOW_TABLE_LEVEL_METER,
 					    egress, transfer, &error);
@@ -7878,6 +8483,14 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,
 		DRV_LOG(ERR, "Failed to create meter policer table.");
 		return -1;
 	}
+	/* Create the meter suffix table with SUFFIX level. */
+	dtb->sfx_tbl = flow_dv_tbl_resource_get(dev,
+					    MLX5_FLOW_TABLE_LEVEL_SUFFIX,
+					    egress, transfer, &error);
+	if (!dtb->sfx_tbl) {
+		DRV_LOG(ERR, "Failed to create meter suffix table.");
+		return -1;
+	}
 	/* Create matchers, Any and Color. */
 	dv_attr.priority = 3;
 	dv_attr.match_criteria_enable = 0;
@@ -7893,7 +8506,7 @@ flow_dv_prepare_mtr_tables(struct rte_eth_dev *dev,
 	dv_attr.match_criteria_enable =
 				1 << MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT;
 	flow_dv_match_meta_reg(mask.buf, value.buf, color_reg_c_idx,
-			       rte_col_2_mlx5_col(RTE_COLORS), UINT32_MAX);
+			       rte_col_2_mlx5_col(RTE_COLORS), UINT8_MAX);
 	dtb->color_matcher = mlx5_glue->dv_create_flow_matcher(sh->ctx,
 							       &dv_attr,
 							       dtb->tbl->obj);
@@ -8048,8 +8661,6 @@ flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused,
  *   Pointer to flow meter structure.
  * @param[in] mtb
  *   Pointer to DV meter table set.
- * @param[in] sfx_tb
- *   Pointer to suffix table.
  * @param[in] mtr_reg_c
  *   Color match REG_C.
  *
@@ -8059,7 +8670,6 @@ flow_dv_destroy_policer_rules(struct rte_eth_dev *dev __rte_unused,
 static int
 flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,
 				    struct mlx5_meter_domain_info *dtb,
-				    struct mlx5_flow_tbl_resource *sfx_tb,
 				    uint8_t mtr_reg_c)
 {
 	struct mlx5_flow_dv_match_params matcher = {
@@ -8073,12 +8683,10 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,
 	int i;
 
 	/* Create jump action. */
-	if (!sfx_tb)
-		return -1;
 	if (!dtb->jump_actn)
 		dtb->jump_actn =
 			mlx5_glue->dr_create_flow_action_dest_flow_tbl
-							(sfx_tb->obj);
+							(dtb->sfx_tbl->obj);
 	if (!dtb->jump_actn) {
 		DRV_LOG(ERR, "Failed to create policer jump action.");
 		goto error;
@@ -8087,7 +8695,7 @@ flow_dv_create_policer_forward_rule(struct mlx5_flow_meter *fm,
 		int j = 0;
 
 		flow_dv_match_meta_reg(matcher.buf, value.buf, mtr_reg_c,
-				       rte_col_2_mlx5_col(i), UINT32_MAX);
+				       rte_col_2_mlx5_col(i), UINT8_MAX);
 		if (mtb->count_actns[i])
 			actions[j++] = mtb->count_actns[i];
 		if (fm->params.action[i] == MTR_POLICER_ACTION_DROP)
@@ -8133,7 +8741,6 @@ flow_dv_create_policer_rules(struct rte_eth_dev *dev,
 
 	if (attr->egress) {
 		ret = flow_dv_create_policer_forward_rule(fm, &mtb->egress,
-						priv->sh->tx_mtr_sfx_tbl,
 						priv->mtr_color_reg);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create egress policer.");
@@ -8142,7 +8749,6 @@ flow_dv_create_policer_rules(struct rte_eth_dev *dev,
 	}
 	if (attr->ingress) {
 		ret = flow_dv_create_policer_forward_rule(fm, &mtb->ingress,
-						priv->sh->rx_mtr_sfx_tbl,
 						priv->mtr_color_reg);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create ingress policer.");
@@ -8151,7 +8757,6 @@ flow_dv_create_policer_rules(struct rte_eth_dev *dev,
 	}
 	if (attr->transfer) {
 		ret = flow_dv_create_policer_forward_rule(fm, &mtb->transfer,
-						priv->sh->fdb_mtr_sfx_tbl,
 						priv->mtr_color_reg);
 		if (ret) {
 			DRV_LOG(ERR, "Failed to create transfer policer.");
diff --git a/dpdk/drivers/net/mlx5/mlx5_flow_meter.c b/dpdk/drivers/net/mlx5/mlx5_flow_meter.c
index c4d28b282e..62e3a35902 100644
--- a/dpdk/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/dpdk/drivers/net/mlx5/mlx5_flow_meter.c
@@ -301,7 +301,7 @@ mlx5_flow_mtr_cap_get(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	memset(cap, 0, sizeof(*cap));
 	cap->n_max = 1 << qattr->log_max_flow_meter;
 	cap->n_shared_max = cap->n_max;
@@ -347,7 +347,7 @@ mlx5_flow_meter_profile_add(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Check input params. */
 	ret = mlx5_flow_meter_profile_validate(dev, meter_profile_id,
 					       profile, error);
@@ -400,19 +400,19 @@ mlx5_flow_meter_profile_delete(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter profile must exist. */
 	fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
 	if (fmp == NULL)
 		return -rte_mtr_error_set(error, ENOENT,
 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 					  &meter_profile_id,
-					  "Meter profile id invalid.");
+					  "Meter profile id is invalid.");
 	/* Check profile is unused. */
 	if (fmp->ref_cnt)
 		return -rte_mtr_error_set(error, EBUSY,
 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-					  NULL, "Meter profile in use.");
+					  NULL, "Meter profile is in use.");
 	/* Remove from list. */
 	TAILQ_REMOVE(&priv->flow_meter_profiles, fmp, next);
 	rte_free(fmp);
@@ -633,7 +633,7 @@ mlx5_flow_meter_create(struct rte_eth_dev *dev, uint32_t meter_id,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Validate the parameters. */
 	ret = mlx5_flow_meter_validate(priv, meter_id, params, error);
 	if (ret)
@@ -718,7 +718,7 @@ mlx5_flow_meter_destroy(struct rte_eth_dev *dev, uint32_t meter_id,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter object must exist. */
 	fm = mlx5_flow_meter_find(priv, meter_id);
 	if (fm == NULL)
@@ -823,7 +823,7 @@ mlx5_flow_meter_enable(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter object must exist. */
 	fm = mlx5_flow_meter_find(priv, meter_id);
 	if (fm == NULL)
@@ -864,7 +864,7 @@ mlx5_flow_meter_disable(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter object must exist. */
 	fm = mlx5_flow_meter_find(priv, meter_id);
 	if (fm == NULL)
@@ -912,7 +912,7 @@ mlx5_flow_meter_profile_update(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter profile must exist. */
 	fmp = mlx5_flow_meter_profile_find(priv, meter_profile_id);
 	if (fmp == NULL)
@@ -975,7 +975,7 @@ mlx5_flow_meter_stats_update(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter object must exist. */
 	fm = mlx5_flow_meter_find(priv, meter_id);
 	if (fm == NULL)
@@ -1032,7 +1032,7 @@ mlx5_flow_meter_stats_read(struct rte_eth_dev *dev,
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
-					  "Meter is not support");
+					  "Meter is not supported");
 	/* Meter object must exist. */
 	fm = mlx5_flow_meter_find(priv, meter_id);
 	if (fm == NULL)
diff --git a/dpdk/drivers/net/mlx5/mlx5_flow_verbs.c b/dpdk/drivers/net/mlx5/mlx5_flow_verbs.c
index c787c9838d..a670c5f3c5 100644
--- a/dpdk/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/dpdk/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -493,14 +493,12 @@ flow_verbs_translate_item_ipv6(struct mlx5_flow *dev_flow,
 		ipv6.val.traffic_class = (vtc_flow_val & RTE_IPV6_HDR_TC_MASK) >>
 					 RTE_IPV6_HDR_TC_SHIFT;
 		ipv6.val.next_hdr = spec->hdr.proto;
-		ipv6.val.hop_limit = spec->hdr.hop_limits;
 		ipv6.mask.flow_label =
 			rte_cpu_to_be_32((vtc_flow_mask & RTE_IPV6_HDR_FL_MASK) >>
 					 RTE_IPV6_HDR_FL_SHIFT);
 		ipv6.mask.traffic_class = (vtc_flow_mask & RTE_IPV6_HDR_TC_MASK) >>
 					  RTE_IPV6_HDR_TC_SHIFT;
 		ipv6.mask.next_hdr = mask->hdr.proto;
-		ipv6.mask.hop_limit = mask->hdr.hop_limits;
 		/* Remove unwanted bits from values. */
 		for (i = 0; i < RTE_DIM(ipv6.val.src_ip); ++i) {
 			ipv6.val.src_ip[i] &= ipv6.mask.src_ip[i];
@@ -509,7 +507,6 @@ flow_verbs_translate_item_ipv6(struct mlx5_flow *dev_flow,
 		ipv6.val.flow_label &= ipv6.mask.flow_label;
 		ipv6.val.traffic_class &= ipv6.mask.traffic_class;
 		ipv6.val.next_hdr &= ipv6.mask.next_hdr;
-		ipv6.val.hop_limit &= ipv6.mask.hop_limit;
 	}
 	flow_verbs_spec_add(&dev_flow->verbs, &ipv6, size);
 }
@@ -589,6 +586,28 @@ flow_verbs_translate_item_udp(struct mlx5_flow *dev_flow,
 		udp.val.src_port &= udp.mask.src_port;
 		udp.val.dst_port &= udp.mask.dst_port;
 	}
+	item++;
+	while (item->type == RTE_FLOW_ITEM_TYPE_VOID)
+		item++;
+	if (!(udp.val.dst_port & udp.mask.dst_port)) {
+		switch ((item)->type) {
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			udp.val.dst_port = htons(MLX5_UDP_PORT_VXLAN);
+			udp.mask.dst_port = 0xffff;
+			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+			udp.val.dst_port = htons(MLX5_UDP_PORT_VXLAN_GPE);
+			udp.mask.dst_port = 0xffff;
+			break;
+		case RTE_FLOW_ITEM_TYPE_MPLS:
+			udp.val.dst_port = htons(MLX5_UDP_PORT_MPLS);
+			udp.mask.dst_port = 0xffff;
+			break;
+		default:
+			break;
+		}
+	}
+
 	flow_verbs_spec_add(&dev_flow->verbs, &udp, size);
 }
 
@@ -1019,6 +1038,8 @@ flow_verbs_translate_action_count(struct mlx5_flow *dev_flow,
  *   Pointer to the list of actions.
  * @param[in] external
  *   This flow rule is created by request external to PMD.
+ * @param[in] hairpin
+ *   Number of hairpin TX actions, 0 means classic flow.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -1031,6 +1052,7 @@ flow_verbs_validate(struct rte_eth_dev *dev,
 		    const struct rte_flow_item items[],
 		    const struct rte_flow_action actions[],
 		    bool external __rte_unused,
+		    int hairpin __rte_unused,
 		    struct rte_flow_error *error)
 {
 	int ret;
@@ -1039,6 +1061,7 @@ flow_verbs_validate(struct rte_eth_dev *dev,
 	uint64_t last_item = 0;
 	uint8_t next_protocol = 0xff;
 	uint16_t ether_type = 0;
+	bool is_empty_vlan = false;
 
 	if (items == NULL)
 		return -1;
@@ -1066,6 +1089,8 @@ flow_verbs_validate(struct rte_eth_dev *dev,
 				ether_type &=
 					((const struct rte_flow_item_eth *)
 					 items->mask)->type;
+				if (ether_type == RTE_BE16(RTE_ETHER_TYPE_VLAN))
+					is_empty_vlan = true;
 				ether_type = rte_be_to_cpu_16(ether_type);
 			} else {
 				ether_type = 0;
@@ -1091,6 +1116,7 @@ flow_verbs_validate(struct rte_eth_dev *dev,
 			} else {
 				ether_type = 0;
 			}
+			is_empty_vlan = false;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV4:
 			ret = mlx5_flow_validate_item_ipv4(items, item_flags,
@@ -1195,6 +1221,10 @@ flow_verbs_validate(struct rte_eth_dev *dev,
 		}
 		item_flags |= last_item;
 	}
+	if (is_empty_vlan)
+		return rte_flow_error_set(error, ENOTSUP,
+						 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+		    "VLAN matching without vid specification is not supported");
 	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
 		switch (actions->type) {
 		case RTE_FLOW_ACTION_TYPE_VOID:
@@ -1255,6 +1285,18 @@ flow_verbs_validate(struct rte_eth_dev *dev,
 						  "action not supported");
 		}
 	}
+	/*
+	 * Validate the drop action mutual exclusion with other actions.
+	 * Drop action is mutually-exclusive with any other action, except for
+	 * Count action.
+	 */
+	if ((action_flags & MLX5_FLOW_ACTION_DROP) &&
+	    (action_flags & ~(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_COUNT)))
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "Drop action is mutually-exclusive "
+					  "with any other action, except for "
+					  "Count action");
 	if (!(action_flags & MLX5_FLOW_FATE_ACTIONS))
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, actions,
@@ -1444,6 +1486,7 @@ flow_verbs_translate(struct rte_eth_dev *dev,
 	uint64_t priority = attr->priority;
 	uint32_t subpriority = 0;
 	struct mlx5_priv *priv = dev->data->dev_private;
+	struct rte_flow *flow = dev_flow->flow;
 
 	if (priority == MLX5_FLOW_PRIO_RSVD)
 		priority = priv->config.flow_prio - 1;
@@ -1562,25 +1605,33 @@ flow_verbs_translate(struct rte_eth_dev *dev,
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 			flow_verbs_translate_item_vxlan(dev_flow, items,
 							item_flags);
-			subpriority = MLX5_PRIORITY_MAP_L2;
+			subpriority = flow->rss.level >= 2 ?
+					MLX5_PRIORITY_MAP_L2 :
+					MLX5_PRIORITY_MAP_L4;
 			item_flags |= MLX5_FLOW_LAYER_VXLAN;
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
 			flow_verbs_translate_item_vxlan_gpe(dev_flow, items,
 							    item_flags);
-			subpriority = MLX5_PRIORITY_MAP_L2;
+			subpriority = flow->rss.level >= 2 ?
+					MLX5_PRIORITY_MAP_L2 :
+					MLX5_PRIORITY_MAP_L4;
 			item_flags |= MLX5_FLOW_LAYER_VXLAN_GPE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE:
 			flow_verbs_translate_item_gre(dev_flow, items,
 						      item_flags);
-			subpriority = MLX5_PRIORITY_MAP_L2;
+			subpriority = flow->rss.level >= 2 ?
+					MLX5_PRIORITY_MAP_L2 :
+					MLX5_PRIORITY_MAP_L4;
 			item_flags |= MLX5_FLOW_LAYER_GRE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_MPLS:
 			flow_verbs_translate_item_mpls(dev_flow, items,
 						       item_flags);
-			subpriority = MLX5_PRIORITY_MAP_L2;
+			subpriority = flow->rss.level >= 2 ?
+					MLX5_PRIORITY_MAP_L2 :
+					MLX5_PRIORITY_MAP_L4;
 			item_flags |= MLX5_FLOW_LAYER_MPLS;
 			break;
 		default:
diff --git a/dpdk/drivers/net/mlx5/mlx5_glue.c b/dpdk/drivers/net/mlx5/mlx5_glue.c
index 0917bf28d6..65b63bd607 100644
--- a/dpdk/drivers/net/mlx5/mlx5_glue.c
+++ b/dpdk/drivers/net/mlx5/mlx5_glue.c
@@ -754,7 +754,7 @@ mlx5_glue_dv_create_flow_action_tag(uint32_t tag)
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 #ifdef HAVE_MLX5DV_DR
 	return mlx5dv_dr_action_create_tag(tag);
-#else
+#else /* HAVE_MLX5DV_DR */
 	struct mlx5dv_flow_action_attr *action;
 	action = malloc(sizeof(*action));
 	if (!action)
@@ -762,11 +762,12 @@ mlx5_glue_dv_create_flow_action_tag(uint32_t tag)
 	action->type = MLX5DV_FLOW_ACTION_TAG;
 	action->tag_value = tag;
 	return action;
-#endif
-#endif
+#endif /* HAVE_MLX5DV_DR */
+#else /* HAVE_IBV_FLOW_DV_SUPPORT */
 	(void)tag;
 	errno = ENOTSUP;
 	return NULL;
+#endif /* HAVE_IBV_FLOW_DV_SUPPORT */
 }
 
 static void *
@@ -1008,7 +1009,7 @@ mlx5_glue_devx_qp_query(struct ibv_qp *qp,
 			const void *in, size_t inlen,
 			void *out, size_t outlen)
 {
-#ifdef HAVE_IBV_DEVX_OBJ
+#ifdef HAVE_IBV_DEVX_QP
 	return mlx5dv_devx_qp_query(qp, in, inlen, out, outlen);
 #else
 	(void)qp;
diff --git a/dpdk/drivers/net/mlx5/mlx5_glue.h b/dpdk/drivers/net/mlx5/mlx5_glue.h
index 6442f1eba8..9895e55974 100644
--- a/dpdk/drivers/net/mlx5/mlx5_glue.h
+++ b/dpdk/drivers/net/mlx5/mlx5_glue.h
@@ -167,11 +167,11 @@ struct mlx5_glue {
 	void *(*dr_create_flow_action_dest_flow_tbl)(void *tbl);
 	void *(*dr_create_flow_action_dest_port)(void *domain,
 						 uint32_t port);
-	void *(*dr_create_flow_action_drop)();
+	void *(*dr_create_flow_action_drop)(void);
 	void *(*dr_create_flow_action_push_vlan)
 					(struct mlx5dv_dr_domain *domain,
 					 rte_be32_t vlan_tag);
-	void *(*dr_create_flow_action_pop_vlan)();
+	void *(*dr_create_flow_action_pop_vlan)(void);
 	void *(*dr_create_flow_tbl)(void *domain, uint32_t level);
 	int (*dr_destroy_flow_tbl)(void *tbl);
 	void *(*dr_create_domain)(struct ibv_context *ctx,
@@ -258,6 +258,6 @@ struct mlx5_glue {
 			       struct mlx5dv_devx_port *mlx5_devx_port);
 };
 
-const struct mlx5_glue *mlx5_glue;
+extern const struct mlx5_glue *mlx5_glue;
 
 #endif /* MLX5_GLUE_H_ */
diff --git a/dpdk/drivers/net/mlx5/mlx5_mac.c b/dpdk/drivers/net/mlx5/mlx5_mac.c
index 7bdaa2a392..177871b211 100644
--- a/dpdk/drivers/net/mlx5/mlx5_mac.c
+++ b/dpdk/drivers/net/mlx5/mlx5_mac.c
@@ -11,7 +11,6 @@
 #include <errno.h>
 #include <netinet/in.h>
 #include <sys/ioctl.h>
-#include <arpa/inet.h>
 
 /* Verbs header. */
 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
@@ -200,8 +199,11 @@ mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
 	uint16_t port_id;
 	struct mlx5_priv *priv = dev->data->dev_private;
 
-	/* Configuring the VF instead of its representor. */
-	if (priv->representor) {
+	/*
+	 * Configuring the VF instead of its representor,
+	 * need to skip the special case of HPF on Bluefield.
+	 */
+	if (priv->representor && priv->representor_id >= 0) {
 		DRV_LOG(DEBUG, "VF represented by port %u setting primary MAC address",
 			dev->data->port_id);
 		RTE_ETH_FOREACH_DEV_SIBLING(port_id, dev->data->port_id) {
diff --git a/dpdk/drivers/net/mlx5/mlx5_mp.c b/dpdk/drivers/net/mlx5/mlx5_mp.c
index 2a031e2610..e889247871 100644
--- a/dpdk/drivers/net/mlx5/mlx5_mp.c
+++ b/dpdk/drivers/net/mlx5/mlx5_mp.c
@@ -119,6 +119,8 @@ mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
 	const struct mlx5_mp_param *param =
 		(const struct mlx5_mp_param *)mp_msg->param;
 	struct rte_eth_dev *dev;
+	struct mlx5_proc_priv *ppriv;
+	struct mlx5_priv *priv;
 	int ret;
 
 	assert(rte_eal_process_type() == RTE_PROC_SECONDARY);
@@ -128,12 +130,27 @@ mp_secondary_handle(const struct rte_mp_msg *mp_msg, const void *peer)
 		return -rte_errno;
 	}
 	dev = &rte_eth_devices[param->port_id];
+	priv = dev->data->dev_private;
 	switch (param->type) {
 	case MLX5_MP_REQ_START_RXTX:
 		DRV_LOG(INFO, "port %u starting datapath", dev->data->port_id);
 		rte_mb();
 		dev->rx_pkt_burst = mlx5_select_rx_function(dev);
 		dev->tx_pkt_burst = mlx5_select_tx_function(dev);
+		ppriv = (struct mlx5_proc_priv *)dev->process_private;
+		/* If Tx queue number changes, re-initialize UAR. */
+		if (ppriv->uar_table_sz != priv->txqs_n) {
+			mlx5_tx_uar_uninit_secondary(dev);
+			mlx5_proc_priv_uninit(dev);
+			ret = mlx5_proc_priv_init(dev);
+			if (ret)
+				return -rte_errno;
+			ret = mlx5_tx_uar_init_secondary(dev, mp_msg->fds[0]);
+			if (ret) {
+				mlx5_proc_priv_uninit(dev);
+				return -rte_errno;
+			}
+		}
 		mp_init_msg(dev, &mp_res, param->type);
 		res->result = 0;
 		ret = rte_mp_reply(&mp_res, peer);
@@ -172,6 +189,7 @@ mp_req_on_rxtx(struct rte_eth_dev *dev, enum mlx5_mp_req_type type)
 	struct rte_mp_reply mp_rep;
 	struct mlx5_mp_param *res;
 	struct timespec ts = {.tv_sec = MLX5_MP_REQ_TIMEOUT_SEC, .tv_nsec = 0};
+	struct mlx5_priv *priv = dev->data->dev_private;
 	int ret;
 	int i;
 
@@ -184,6 +202,10 @@ mp_req_on_rxtx(struct rte_eth_dev *dev, enum mlx5_mp_req_type type)
 		return;
 	}
 	mp_init_msg(dev, &mp_req, type);
+	if (type == MLX5_MP_REQ_START_RXTX) {
+		mp_req.num_fds = 1;
+		mp_req.fds[0] = ((struct ibv_context *)priv->sh->ctx)->cmd_fd;
+	}
 	ret = rte_mp_request_sync(&mp_req, &mp_rep, &ts);
 	if (ret) {
 		if (rte_errno != ENOTSUP)
diff --git a/dpdk/drivers/net/mlx5/mlx5_mr.c b/dpdk/drivers/net/mlx5/mlx5_mr.c
index 0d549b68e6..54a11bd5d1 100644
--- a/dpdk/drivers/net/mlx5/mlx5_mr.c
+++ b/dpdk/drivers/net/mlx5/mlx5_mr.c
@@ -1408,7 +1408,7 @@ mlx5_dma_unmap(struct rte_pci_device *pdev, void *addr,
 		return -1;
 	}
 	LIST_REMOVE(mr, mr);
-	LIST_INSERT_HEAD(&sh->mr.mr_free_list, mr, mr);
+	mr_free(mr);
 	DEBUG("port %u remove MR(%p) from list", dev->data->port_id,
 	      (void *)mr);
 	mr_rebuild_dev_cache(sh);
diff --git a/dpdk/drivers/net/mlx5/mlx5_nl.c b/dpdk/drivers/net/mlx5/mlx5_nl.c
index e7ba03471d..64580b9e6a 100644
--- a/dpdk/drivers/net/mlx5/mlx5_nl.c
+++ b/dpdk/drivers/net/mlx5/mlx5_nl.c
@@ -269,10 +269,10 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
 	     void *arg)
 {
 	struct sockaddr_nl sa;
-	char buf[MLX5_RECV_BUF_SIZE];
+	void *buf = malloc(MLX5_RECV_BUF_SIZE);
 	struct iovec iov = {
 		.iov_base = buf,
-		.iov_len = sizeof(buf),
+		.iov_len = MLX5_RECV_BUF_SIZE,
 	};
 	struct msghdr msg = {
 		.msg_name = &sa,
@@ -284,6 +284,10 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
 	int multipart = 0;
 	int ret = 0;
 
+	if (!buf) {
+		rte_errno = ENOMEM;
+		return -rte_errno;
+	}
 	do {
 		struct nlmsghdr *nh;
 		int recv_bytes = 0;
@@ -292,7 +296,8 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
 			recv_bytes = recvmsg(nlsk_fd, &msg, 0);
 			if (recv_bytes == -1) {
 				rte_errno = errno;
-				return -rte_errno;
+				ret = -rte_errno;
+				goto exit;
 			}
 			nh = (struct nlmsghdr *)buf;
 		} while (nh->nlmsg_seq != sn);
@@ -304,24 +309,30 @@ mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),
 
 				if (err_data->error < 0) {
 					rte_errno = -err_data->error;
-					return -rte_errno;
+					ret = -rte_errno;
+					goto exit;
 				}
 				/* Ack message. */
-				return 0;
+				ret = 0;
+				goto exit;
 			}
 			/* Multi-part msgs and their trailing DONE message. */
 			if (nh->nlmsg_flags & NLM_F_MULTI) {
-				if (nh->nlmsg_type == NLMSG_DONE)
-					return 0;
+				if (nh->nlmsg_type == NLMSG_DONE) {
+					ret =  0;
+					goto exit;
+				}
 				multipart = 1;
 			}
 			if (cb) {
 				ret = cb(nh, arg);
 				if (ret < 0)
-					return ret;
+					goto exit;
 			}
 		}
 	} while (multipart);
+exit:
+	free(buf);
 	return ret;
 }
 
diff --git a/dpdk/drivers/net/mlx5/mlx5_prm.h b/dpdk/drivers/net/mlx5/mlx5_prm.h
index a805363757..1d13bbb009 100644
--- a/dpdk/drivers/net/mlx5/mlx5_prm.h
+++ b/dpdk/drivers/net/mlx5/mlx5_prm.h
@@ -18,6 +18,8 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include <unistd.h>
+
 #include <rte_vect.h>
 #include "mlx5_autoconf.h"
 
@@ -100,7 +102,7 @@
  */
 #define MLX5_EMPW_MAX_PACKETS MLX5_TX_COMP_THRESH
 #define MLX5_MPW_MAX_PACKETS 6
-#define MLX5_MPW_INLINE_MAX_PACKETS 2
+#define MLX5_MPW_INLINE_MAX_PACKETS 6
 
 /*
  * Default packet length threshold to be inlined with
@@ -251,7 +253,7 @@
 #define MLX5_MAX_LOG_RQ_SEGS 5u
 
 /* The alignment needed for WQ buffer. */
-#define MLX5_WQE_BUF_ALIGNMENT 512
+#define MLX5_WQE_BUF_ALIGNMENT sysconf(_SC_PAGESIZE)
 
 /* Completion mode. */
 enum mlx5_completion_mode {
@@ -513,7 +515,7 @@ typedef uint8_t u8;
 
 #define __mlx5_nullp(typ) ((struct mlx5_ifc_##typ##_bits *)0)
 #define __mlx5_bit_sz(typ, fld) sizeof(__mlx5_nullp(typ)->fld)
-#define __mlx5_bit_off(typ, fld) ((unsigned int)(unsigned long) \
+#define __mlx5_bit_off(typ, fld) ((unsigned int)(uintptr_t) \
 				  (&(__mlx5_nullp(typ)->fld)))
 #define __mlx5_dw_bit_off(typ, fld) (32 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0x1f))
@@ -723,6 +725,9 @@ enum {
 	MLX5_MKC_ACCESS_MODE_MTT   = 0x1,
 };
 
+/* The counter batch query requires ID align with 4. */
+#define MLX5_CNT_BATCH_QUERY_ID_ALIGNMENT 4
+
 /* Flow counters. */
 struct mlx5_ifc_alloc_flow_counter_out_bits {
 	u8         status[0x8];
@@ -1196,7 +1201,9 @@ struct mlx5_ifc_qos_cap_bits {
 	u8 reserved_at_8[0x8];
 	u8 log_max_flow_meter[0x8];
 	u8 flow_meter_reg_id[0x8];
-	u8 reserved_at_25[0x20];
+	u8 reserved_at_25[0x8];
+	u8 flow_meter_reg_share[0x1];
+	u8 reserved_at_2e[0x17];
 	u8 packet_pacing_max_rate[0x20];
 	u8 packet_pacing_min_rate[0x20];
 	u8 reserved_at_80[0x10];
@@ -1816,6 +1823,9 @@ enum {
 #define MLX5_SRTCM_CIR_MAX (8 * (1ULL << 30) * 0xFF)
 #define MLX5_SRTCM_EBS_MAX 0
 
+/* The bits meter color use. */
+#define MLX5_MTR_COLOR_BITS 8
+
 /**
  * Convert a user mark to flow mark.
  *
diff --git a/dpdk/drivers/net/mlx5/mlx5_rss.c b/dpdk/drivers/net/mlx5/mlx5_rss.c
index 102826452d..170005a7af 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rss.c
+++ b/dpdk/drivers/net/mlx5/mlx5_rss.c
@@ -221,9 +221,11 @@ mlx5_dev_rss_reta_update(struct rte_eth_dev *dev,
 		assert(reta_conf[idx].reta[pos] < priv->rxqs_n);
 		(*priv->reta_idx)[i] = reta_conf[idx].reta[pos];
 	}
+
+	priv->skip_default_rss_reta = 1;
+
 	if (dev->data->dev_started) {
 		mlx5_dev_stop(dev);
-		priv->skip_default_rss_reta = 1;
 		return mlx5_dev_start(dev);
 	}
 	return 0;
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxq.c b/dpdk/drivers/net/mlx5/mlx5_rxq.c
index 986ec016df..e3f41d121d 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxq.c
+++ b/dpdk/drivers/net/mlx5/mlx5_rxq.c
@@ -36,6 +36,7 @@
 #include "mlx5_autoconf.h"
 #include "mlx5_defs.h"
 #include "mlx5_glue.h"
+#include "mlx5_flow.h"
 
 /* Default RSS hash key also used for ConnectX-3. */
 uint8_t rss_hash_default_key[] = {
@@ -104,7 +105,7 @@ inline int
 mlx5_mprq_enabled(struct rte_eth_dev *dev)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint16_t i;
+	uint32_t i;
 	uint16_t n = 0;
 	uint16_t n_ibv = 0;
 
@@ -445,19 +446,19 @@ mlx5_rxq_releasable(struct rte_eth_dev *dev, uint16_t idx)
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_rx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc)
+mlx5_rx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t *desc)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 
-	if (!rte_is_power_of_2(desc)) {
-		desc = 1 << log2above(desc);
+	if (!rte_is_power_of_2(*desc)) {
+		*desc = 1 << log2above(*desc);
 		DRV_LOG(WARNING,
 			"port %u increased number of descriptors in Rx queue %u"
 			" to the next power of two (%d)",
-			dev->data->port_id, idx, desc);
+			dev->data->port_id, idx, *desc);
 	}
 	DRV_LOG(DEBUG, "port %u configuring Rx queue %u for %u descriptors",
-		dev->data->port_id, idx, desc);
+		dev->data->port_id, idx, *desc);
 	if (idx >= priv->rxqs_n) {
 		DRV_LOG(ERR, "port %u Rx queue index out of range (%u >= %u)",
 			dev->data->port_id, idx, priv->rxqs_n);
@@ -503,7 +504,7 @@ mlx5_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		container_of(rxq, struct mlx5_rxq_ctrl, rxq);
 	int res;
 
-	res = mlx5_rx_queue_pre_setup(dev, idx, desc);
+	res = mlx5_rx_queue_pre_setup(dev, idx, &desc);
 	if (res)
 		return res;
 	rxq_ctrl = mlx5_rxq_new(dev, idx, desc, socket, conf, mp);
@@ -544,7 +545,7 @@ mlx5_rx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
 		container_of(rxq, struct mlx5_rxq_ctrl, rxq);
 	int res;
 
-	res = mlx5_rx_queue_pre_setup(dev, idx, desc);
+	res = mlx5_rx_queue_pre_setup(dev, idx, &desc);
 	if (res)
 		return res;
 	if (hairpin_conf->peer_count != 1 ||
@@ -722,6 +723,9 @@ mlx5_rx_intr_vec_enable(struct rte_eth_dev *dev)
 	unsigned int count = 0;
 	struct rte_intr_handle *intr_handle = dev->intr_handle;
 
+	/* Representor shares dev->intr_handle with PF. */
+	if (priv->representor)
+		return 0;
 	if (!dev->data->dev_conf.intr_conf.rxq)
 		return 0;
 	mlx5_rx_intr_vec_disable(dev);
@@ -799,6 +803,9 @@ mlx5_rx_intr_vec_disable(struct rte_eth_dev *dev)
 	unsigned int rxqs_n = priv->rxqs_n;
 	unsigned int n = RTE_MIN(rxqs_n, (uint32_t)RTE_MAX_RXTX_INTR_VEC_ID);
 
+	/* Representor shares dev->intr_handle with PF. */
+	if (priv->representor)
+		return;
 	if (!dev->data->dev_conf.intr_conf.rxq)
 		return;
 	if (!intr_handle->intr_vec)
@@ -1152,7 +1159,7 @@ static void
 mlx5_devx_wq_attr_fill(struct mlx5_priv *priv, struct mlx5_rxq_ctrl *rxq_ctrl,
 		       struct mlx5_devx_wq_attr *wq_attr)
 {
-	wq_attr->end_padding_mode = priv->config.cqe_pad ?
+	wq_attr->end_padding_mode = priv->config.hw_padding ?
 					MLX5_WQ_END_PAD_MODE_ALIGN :
 					MLX5_WQ_END_PAD_MODE_NONE;
 	wq_attr->pd = priv->sh->pdn;
@@ -1259,7 +1266,7 @@ mlx5_rxq_obj_hairpin_new(struct rte_eth_dev *dev, uint16_t idx)
 		container_of(rxq_data, struct mlx5_rxq_ctrl, rxq);
 	struct mlx5_devx_create_rq_attr attr = { 0 };
 	struct mlx5_rxq_obj *tmpl = NULL;
-	int ret = 0;
+	uint32_t max_wq_data;
 
 	assert(rxq_data);
 	assert(!rxq_ctrl->obj);
@@ -1270,24 +1277,29 @@ mlx5_rxq_obj_hairpin_new(struct rte_eth_dev *dev, uint16_t idx)
 			"port %u Rx queue %u cannot allocate verbs resources",
 			dev->data->port_id, rxq_data->idx);
 		rte_errno = ENOMEM;
-		goto error;
+		return NULL;
 	}
 	tmpl->type = MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN;
 	tmpl->rxq_ctrl = rxq_ctrl;
 	attr.hairpin = 1;
-	/* Workaround for hairpin startup */
-	attr.wq_attr.log_hairpin_num_packets = log2above(32);
-	/* Workaround for packets larger than 1KB */
+	max_wq_data = priv->config.hca_attr.log_max_hairpin_wq_data_sz;
+	/* Jumbo frames > 9KB should be supported, and more packets. */
 	attr.wq_attr.log_hairpin_data_sz =
-			priv->config.hca_attr.log_max_hairpin_wq_data_sz;
+			(max_wq_data < MLX5_HAIRPIN_JUMBO_LOG_SIZE) ?
+			max_wq_data : MLX5_HAIRPIN_JUMBO_LOG_SIZE;
+	/* Set the packets number to the maximum value for performance. */
+	attr.wq_attr.log_hairpin_num_packets =
+			attr.wq_attr.log_hairpin_data_sz -
+			MLX5_HAIRPIN_QUEUE_STRIDE;
 	tmpl->rq = mlx5_devx_cmd_create_rq(priv->sh->ctx, &attr,
 					   rxq_ctrl->socket);
 	if (!tmpl->rq) {
 		DRV_LOG(ERR,
 			"port %u Rx hairpin queue %u can't create rq object",
 			dev->data->port_id, idx);
+		rte_free(tmpl);
 		rte_errno = errno;
-		goto error;
+		return NULL;
 	}
 	DRV_LOG(DEBUG, "port %u rxq %u updated with %p", dev->data->port_id,
 		idx, (void *)&tmpl);
@@ -1295,12 +1307,6 @@ mlx5_rxq_obj_hairpin_new(struct rte_eth_dev *dev, uint16_t idx)
 	LIST_INSERT_HEAD(&priv->rxqsobj, tmpl, next);
 	priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;
 	return tmpl;
-error:
-	ret = rte_errno; /* Save rte_errno before cleanup. */
-	if (tmpl->rq)
-		mlx5_devx_cmd_destroy(tmpl->rq);
-	rte_errno = ret; /* Restore rte_errno. */
-	return NULL;
 }
 
 /**
@@ -1762,9 +1768,10 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_ctrl *tmpl;
 	unsigned int mb_len = rte_pktmbuf_data_room_size(mp);
+	unsigned int mprq_stride_nums;
 	unsigned int mprq_stride_size;
+	unsigned int mprq_stride_cap;
 	struct mlx5_dev_config *config = &priv->config;
-	unsigned int strd_headroom_en;
 	/*
 	 * Always allocate extra slots, even if eventually
 	 * the vector Rx will not be used.
@@ -1810,42 +1817,42 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	tmpl->socket = socket;
 	if (dev->data->dev_conf.intr_conf.rxq)
 		tmpl->irq = 1;
-	/*
-	 * LRO packet may consume all the stride memory, hence we cannot
-	 * guaranty head-room near the packet memory in the stride.
-	 * In this case scatter is, for sure, enabled and an empty mbuf may be
-	 * added in the start for the head-room.
-	 */
-	if (lro_on_queue && RTE_PKTMBUF_HEADROOM > 0 &&
-	    non_scatter_min_mbuf_size > mb_len) {
-		strd_headroom_en = 0;
-		mprq_stride_size = RTE_MIN(max_rx_pkt_len,
-					1u << config->mprq.max_stride_size_n);
-	} else {
-		strd_headroom_en = 1;
-		mprq_stride_size = non_scatter_min_mbuf_size;
-	}
+	mprq_stride_nums = config->mprq.stride_num_n ?
+		config->mprq.stride_num_n : MLX5_MPRQ_STRIDE_NUM_N;
+	mprq_stride_size = non_scatter_min_mbuf_size <=
+		(1U << config->mprq.max_stride_size_n) ?
+		log2above(non_scatter_min_mbuf_size) : MLX5_MPRQ_STRIDE_SIZE_N;
+	mprq_stride_cap = (config->mprq.stride_num_n ?
+		(1U << config->mprq.stride_num_n) : (1U << mprq_stride_nums)) *
+			(config->mprq.stride_size_n ?
+		(1U << config->mprq.stride_size_n) : (1U << mprq_stride_size));
 	/*
 	 * This Rx queue can be configured as a Multi-Packet RQ if all of the
 	 * following conditions are met:
 	 *  - MPRQ is enabled.
 	 *  - The number of descs is more than the number of strides.
-	 *  - max_rx_pkt_len plus overhead is less than the max size of a
-	 *    stride.
+	 *  - max_rx_pkt_len plus overhead is less than the max size
+	 *    of a stride or mprq_stride_size is specified by a user.
+	 *    Need to nake sure that there are enough stides to encap
+	 *    the maximum packet size in case mprq_stride_size is set.
 	 *  Otherwise, enable Rx scatter if necessary.
 	 */
-	if (mprq_en &&
-	    desc > (1U << config->mprq.stride_num_n) &&
-	    mprq_stride_size <= (1U << config->mprq.max_stride_size_n)) {
+	if (mprq_en && desc > (1U << mprq_stride_nums) &&
+	    (non_scatter_min_mbuf_size <=
+	     (1U << config->mprq.max_stride_size_n) ||
+	     (config->mprq.stride_size_n &&
+	      non_scatter_min_mbuf_size <= mprq_stride_cap))) {
 		/* TODO: Rx scatter isn't supported yet. */
 		tmpl->rxq.sges_n = 0;
 		/* Trim the number of descs needed. */
-		desc >>= config->mprq.stride_num_n;
-		tmpl->rxq.strd_num_n = config->mprq.stride_num_n;
-		tmpl->rxq.strd_sz_n = RTE_MAX(log2above(mprq_stride_size),
-					      config->mprq.min_stride_size_n);
+		desc >>= mprq_stride_nums;
+		tmpl->rxq.strd_num_n = config->mprq.stride_num_n ?
+			config->mprq.stride_num_n : mprq_stride_nums;
+		tmpl->rxq.strd_sz_n = config->mprq.stride_size_n ?
+			config->mprq.stride_size_n : mprq_stride_size;
 		tmpl->rxq.strd_shift_en = MLX5_MPRQ_TWO_BYTE_SHIFT;
-		tmpl->rxq.strd_headroom_en = strd_headroom_en;
+		tmpl->rxq.strd_scatter_en =
+				!!(offloads & DEV_RX_OFFLOAD_SCATTER);
 		tmpl->rxq.mprq_max_memcpy_len = RTE_MIN(first_mb_free_size,
 				config->mprq.max_memcpy_len);
 		max_lro_size = RTE_MIN(max_rx_pkt_len,
@@ -1889,14 +1896,24 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		tmpl->rxq.sges_n = sges_n;
 		max_lro_size = max_rx_pkt_len;
 	}
-	if (mprq_en && !mlx5_rxq_mprq_enabled(&tmpl->rxq))
+	if (config->mprq.enabled && !mlx5_rxq_mprq_enabled(&tmpl->rxq))
 		DRV_LOG(WARNING,
-			"port %u MPRQ is requested but cannot be enabled"
-			" (requested: desc = %u, stride_sz = %u,"
-			" supported: min_stride_num = %u, max_stride_sz = %u).",
-			dev->data->port_id, desc, mprq_stride_size,
-			(1 << config->mprq.stride_num_n),
-			(1 << config->mprq.max_stride_size_n));
+			"port %u MPRQ is requested but cannot be enabled\n"
+			" (requested: pkt_sz = %u, desc_num = %u,"
+			" rxq_num = %u, stride_sz = %u, stride_num = %u\n"
+			"  supported: min_rxqs_num = %u,"
+			" min_stride_sz = %u, max_stride_sz = %u).",
+			dev->data->port_id, non_scatter_min_mbuf_size,
+			desc, priv->rxqs_n,
+			config->mprq.stride_size_n ?
+				(1U << config->mprq.stride_size_n) :
+				(1U << mprq_stride_size),
+			config->mprq.stride_num_n ?
+				(1U << config->mprq.stride_num_n) :
+				(1U << mprq_stride_nums),
+			config->mprq.min_rxqs_num,
+			(1U << config->mprq.min_stride_size_n),
+			(1U << config->mprq.max_stride_size_n));
 	DRV_LOG(DEBUG, "port %u maximum number of segments per packet: %u",
 		dev->data->port_id, 1 << tmpl->rxq.sges_n);
 	if (desc % (1 << tmpl->rxq.sges_n)) {
@@ -1958,13 +1975,14 @@ mlx5_rxq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	tmpl->rxq.elts =
 		(struct rte_mbuf *(*)[1 << tmpl->rxq.elts_n])(tmpl + 1);
 #ifndef RTE_ARCH_64
-	tmpl->rxq.uar_lock_cq = &priv->uar_lock_cq;
+	tmpl->rxq.uar_lock_cq = &priv->sh->uar_lock_cq;
 #endif
 	tmpl->rxq.idx = idx;
 	rte_atomic32_inc(&tmpl->refcnt);
 	LIST_INSERT_HEAD(&priv->rxqsctrl, tmpl, next);
 	return tmpl;
 error:
+	mlx5_mr_btree_free(&tmpl->rxq.mr_ctrl.cache_bh);
 	rte_free(tmpl);
 	return NULL;
 }
@@ -2465,13 +2483,42 @@ mlx5_hrxq_new(struct rte_eth_dev *dev,
 		memset(&tir_attr, 0, sizeof(tir_attr));
 		tir_attr.disp_type = MLX5_TIRC_DISP_TYPE_INDIRECT;
 		tir_attr.rx_hash_fn = MLX5_RX_HASH_FN_TOEPLITZ;
-		memcpy(&tir_attr.rx_hash_field_selector_outer, &hash_fields,
-		       sizeof(uint64_t));
+		tir_attr.tunneled_offload_en = !!tunnel;
+		/* If needed, translate hash_fields bitmap to PRM format. */
+		if (hash_fields) {
+#ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
+			struct mlx5_rx_hash_field_select *rx_hash_field_select =
+					hash_fields & IBV_RX_HASH_INNER ?
+					&tir_attr.rx_hash_field_selector_inner :
+					&tir_attr.rx_hash_field_selector_outer;
+#else
+			struct mlx5_rx_hash_field_select *rx_hash_field_select =
+					&tir_attr.rx_hash_field_selector_outer;
+#endif
+
+			/* 1 bit: 0: IPv4, 1: IPv6. */
+			rx_hash_field_select->l3_prot_type =
+				!!(hash_fields & MLX5_IPV6_IBV_RX_HASH);
+			/* 1 bit: 0: TCP, 1: UDP. */
+			rx_hash_field_select->l4_prot_type =
+				!!(hash_fields & MLX5_UDP_IBV_RX_HASH);
+			/* Bitmask which sets which fields to use in RX Hash. */
+			rx_hash_field_select->selected_fields =
+			((!!(hash_fields & MLX5_L3_SRC_IBV_RX_HASH)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_SRC_IP) |
+			(!!(hash_fields & MLX5_L3_DST_IBV_RX_HASH)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_DST_IP |
+			(!!(hash_fields & MLX5_L4_SRC_IBV_RX_HASH)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_SPORT |
+			(!!(hash_fields & MLX5_L4_DST_IBV_RX_HASH)) <<
+			 MLX5_RX_HASH_FIELD_SELECT_SELECTED_FIELDS_L4_DPORT;
+		}
 		if (rxq_ctrl->obj->type == MLX5_RXQ_OBJ_TYPE_DEVX_HAIRPIN)
 			tir_attr.transport_domain = priv->sh->td->id;
 		else
 			tir_attr.transport_domain = priv->sh->tdn;
-		memcpy(tir_attr.rx_hash_toeplitz_key, rss_key, rss_key_len);
+		memcpy(tir_attr.rx_hash_toeplitz_key, rss_key,
+		       MLX5_RSS_HASH_KEY_LEN);
 		tir_attr.indirect_table = ind_tbl->rqt->id;
 		if (dev->data->dev_conf.lpbk_mode)
 			tir_attr.self_lb_block =
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxtx.c b/dpdk/drivers/net/mlx5/mlx5_rxtx.c
index acf0fd794b..ac5c1868a0 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxtx.c
+++ b/dpdk/drivers/net/mlx5/mlx5_rxtx.c
@@ -469,13 +469,15 @@ rx_queue_count(struct mlx5_rxq_data *rxq)
 	struct rxq_zip *zip = &rxq->zip;
 	volatile struct mlx5_cqe *cqe;
 	const unsigned int cqe_n = (1 << rxq->cqe_n);
+	const unsigned int sges_n = (1 << rxq->sges_n);
+	const unsigned int elts_n = (1 << rxq->elts_n);
+	const unsigned int strd_n = (1 << rxq->strd_num_n);
 	const unsigned int cqe_cnt = cqe_n - 1;
-	unsigned int cq_ci;
-	unsigned int used;
+	unsigned int cq_ci, used;
 
 	/* if we are processing a compressed cqe */
 	if (zip->ai) {
-		used = zip->cqe_cnt - zip->ca;
+		used = zip->cqe_cnt - zip->ai;
 		cq_ci = zip->cq_ci;
 	} else {
 		used = 0;
@@ -495,7 +497,7 @@ rx_queue_count(struct mlx5_rxq_data *rxq)
 		used += n;
 		cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
 	}
-	used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
+	used = RTE_MIN(used * sges_n, elts_n * strd_n);
 	return used;
 }
 
@@ -518,11 +520,12 @@ mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
 			container_of(rxq, struct mlx5_rxq_ctrl, rxq);
 	struct rte_eth_dev *dev = ETH_DEV(rxq_ctrl->priv);
 
-	if (dev->rx_pkt_burst != mlx5_rx_burst) {
+	if (dev->rx_pkt_burst == NULL ||
+	    dev->rx_pkt_burst == removed_rx_burst) {
 		rte_errno = ENOTSUP;
 		return -rte_errno;
 	}
-	if (offset >= (1 << rxq->elts_n)) {
+	if (offset >= (1 << rxq->cqe_n)) {
 		rte_errno = EINVAL;
 		return -rte_errno;
 	}
@@ -550,7 +553,8 @@ mlx5_rx_queue_count(struct rte_eth_dev *dev, uint16_t rx_queue_id)
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_rxq_data *rxq;
 
-	if (dev->rx_pkt_burst != mlx5_rx_burst) {
+	if (dev->rx_pkt_burst == NULL ||
+	    dev->rx_pkt_burst == removed_rx_burst) {
 		rte_errno = ENOTSUP;
 		return -rte_errno;
 	}
@@ -654,10 +658,10 @@ check_err_cqe_seen(volatile struct mlx5_err_cqe *err_cqe)
  *   Pointer to the error CQE.
  *
  * @return
- *   Negative value if queue recovery failed,
- *   the last Tx buffer element to free otherwise.
+ *   Negative value if queue recovery failed, otherwise
+ *   the error completion entry is handled successfully.
  */
-int
+static int
 mlx5_tx_error_cqe_handle(struct mlx5_txq_data *restrict txq,
 			 volatile struct mlx5_err_cqe *err_cqe)
 {
@@ -701,18 +705,14 @@ mlx5_tx_error_cqe_handle(struct mlx5_txq_data *restrict txq,
 			 */
 			txq->stats.oerrors += ((txq->wqe_ci & wqe_m) -
 						new_wqe_pi) & wqe_m;
-		if (tx_recover_qp(txq_ctrl) == 0) {
-			txq->cq_ci++;
-			/* Release all the remaining buffers. */
-			return txq->elts_head;
+		if (tx_recover_qp(txq_ctrl)) {
+			/* Recovering failed - retry later on the same WQE. */
+			return -1;
 		}
-		/* Recovering failed - try again later on the same WQE. */
-		return -1;
-	} else {
-		txq->cq_ci++;
+		/* Release all the remaining buffers. */
+		txq_free_elts(txq_ctrl);
 	}
-	/* Do not release buffers. */
-	return txq->elts_tail;
+	return 0;
 }
 
 /**
@@ -1132,6 +1132,7 @@ mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
 		} else {
 			int ret;
 			int8_t op_own;
+			uint32_t cq_ci;
 
 			ret = check_cqe(cqe, cqe_n, rxq->cq_ci);
 			if (unlikely(ret != MLX5_CQE_STATUS_SW_OWN)) {
@@ -1145,14 +1146,19 @@ mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
 					return 0;
 				}
 			}
-			++rxq->cq_ci;
+			/*
+			 * Introduce the local variable to have queue cq_ci
+			 * index in queue structure always consistent with
+			 * actual CQE boundary (not pointing to the middle
+			 * of compressed CQE session).
+			 */
+			cq_ci = rxq->cq_ci + 1;
 			op_own = cqe->op_own;
 			if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED) {
 				volatile struct mlx5_mini_cqe8 (*mc)[8] =
 					(volatile struct mlx5_mini_cqe8 (*)[8])
 					(uintptr_t)(&(*rxq->cqes)
-						[rxq->cq_ci &
-						 cqe_cnt].pkt_info);
+						[cq_ci & cqe_cnt].pkt_info);
 
 				/* Fix endianness. */
 				zip->cqe_cnt = rte_be_to_cpu_32(cqe->byte_cnt);
@@ -1165,10 +1171,9 @@ mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
 				 * 7 CQEs after the initial CQE instead of 8
 				 * for subsequent ones.
 				 */
-				zip->ca = rxq->cq_ci;
+				zip->ca = cq_ci;
 				zip->na = zip->ca + 7;
 				/* Compute the next non compressed CQE. */
-				--rxq->cq_ci;
 				zip->cq_ci = rxq->cq_ci + zip->cqe_cnt;
 				/* Get packet size to return. */
 				len = rte_be_to_cpu_32((*mc)[0].byte_cnt);
@@ -1183,6 +1188,7 @@ mlx5_rx_poll_len(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cqe,
 					++idx;
 				}
 			} else {
+				rxq->cq_ci = cq_ci;
 				len = rte_be_to_cpu_32(cqe->byte_cnt);
 			}
 		}
@@ -1253,9 +1259,10 @@ rxq_cq_to_mbuf(struct mlx5_rxq_data *rxq, struct rte_mbuf *pkt,
 			pkt->hash.fdir.hi = mlx5_flow_mark_get(mark);
 		}
 	}
-	if (rte_flow_dynf_metadata_avail() && cqe->flow_table_metadata) {
-		pkt->ol_flags |= PKT_RX_DYNF_METADATA;
-		*RTE_FLOW_DYNF_METADATA(pkt) = cqe->flow_table_metadata;
+	if (rxq->dynf_meta && cqe->flow_table_metadata) {
+		pkt->ol_flags |= rxq->flow_meta_mask;
+		*RTE_MBUF_DYNFIELD(pkt, rxq->flow_meta_offset, uint32_t *) =
+			cqe->flow_table_metadata;
 	}
 	if (rxq->csum)
 		pkt->ol_flags |= rxq_cq_to_ol_flags(cqe);
@@ -1442,7 +1449,7 @@ mlx5_lro_update_tcp_hdr(struct rte_tcp_hdr *restrict tcp,
 	if (cqe->lro_tcppsh_abort_dupack & MLX5_CQE_LRO_PUSH_MASK)
 		tcp->tcp_flags |= RTE_TCP_PSH_FLAG;
 	tcp->cksum = 0;
-	csum += rte_raw_cksum(tcp, (tcp->data_off & 0xF) * 4);
+	csum += rte_raw_cksum(tcp, (tcp->data_off >> 4) * 4);
 	csum = ((csum & 0xffff0000) >> 16) + (csum & 0xffff);
 	csum = (~csum) & 0xffff;
 	if (csum == 0)
@@ -1574,21 +1581,20 @@ mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 	unsigned int i = 0;
 	uint32_t rq_ci = rxq->rq_ci;
 	uint16_t consumed_strd = rxq->consumed_strd;
-	uint16_t headroom_sz = rxq->strd_headroom_en * RTE_PKTMBUF_HEADROOM;
 	struct mlx5_mprq_buf *buf = (*rxq->mprq_bufs)[rq_ci & wq_mask];
 
 	while (i < pkts_n) {
 		struct rte_mbuf *pkt;
 		void *addr;
 		int ret;
-		unsigned int len;
+		uint32_t len;
 		uint16_t strd_cnt;
 		uint16_t strd_idx;
 		uint32_t offset;
 		uint32_t byte_cnt;
+		int32_t hdrm_overlap;
 		volatile struct mlx5_mini_cqe8 *mcqe = NULL;
 		uint32_t rss_hash_res = 0;
-		uint8_t lro_num_seg;
 
 		if (consumed_strd == strd_n) {
 			/* Replace WQE only if the buffer is still in use. */
@@ -1634,18 +1640,6 @@ mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		}
 		assert(strd_idx < strd_n);
 		assert(!((rte_be_to_cpu_16(cqe->wqe_id) ^ rq_ci) & wq_mask));
-		lro_num_seg = cqe->lro_num_seg;
-		/*
-		 * Currently configured to receive a packet per a stride. But if
-		 * MTU is adjusted through kernel interface, device could
-		 * consume multiple strides without raising an error. In this
-		 * case, the packet should be dropped because it is bigger than
-		 * the max_rx_pkt_len.
-		 */
-		if (unlikely(!lro_num_seg && strd_cnt > 1)) {
-			++rxq->stats.idropped;
-			continue;
-		}
 		pkt = rte_pktmbuf_alloc(rxq->mp);
 		if (unlikely(pkt == NULL)) {
 			++rxq->stats.rx_nombuf;
@@ -1657,23 +1651,57 @@ mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			len -= RTE_ETHER_CRC_LEN;
 		offset = strd_idx * strd_sz + strd_shift;
 		addr = RTE_PTR_ADD(mlx5_mprq_buf_addr(buf, strd_n), offset);
+		hdrm_overlap = len + RTE_PKTMBUF_HEADROOM - strd_cnt * strd_sz;
 		/*
 		 * Memcpy packets to the target mbuf if:
 		 * - The size of packet is smaller than mprq_max_memcpy_len.
 		 * - Out of buffer in the Mempool for Multi-Packet RQ.
+		 * - The packet's stride overlaps a headroom and scatter is off.
 		 */
-		if (len <= rxq->mprq_max_memcpy_len || rxq->mprq_repl == NULL) {
-			/*
-			 * When memcpy'ing packet due to out-of-buffer, the
-			 * packet must be smaller than the target mbuf.
-			 */
-			if (unlikely(rte_pktmbuf_tailroom(pkt) < len)) {
+		if (len <= rxq->mprq_max_memcpy_len ||
+		    rxq->mprq_repl == NULL ||
+		    (hdrm_overlap > 0 && !rxq->strd_scatter_en)) {
+			if (likely(rte_pktmbuf_tailroom(pkt) >= len)) {
+				rte_memcpy(rte_pktmbuf_mtod(pkt, void *),
+					   addr, len);
+				DATA_LEN(pkt) = len;
+			} else if (rxq->strd_scatter_en) {
+				struct rte_mbuf *prev = pkt;
+				uint32_t seg_len =
+					RTE_MIN(rte_pktmbuf_tailroom(pkt), len);
+				uint32_t rem_len = len - seg_len;
+
+				rte_memcpy(rte_pktmbuf_mtod(pkt, void *),
+					   addr, seg_len);
+				DATA_LEN(pkt) = seg_len;
+				while (rem_len) {
+					struct rte_mbuf *next =
+						rte_pktmbuf_alloc(rxq->mp);
+
+					if (unlikely(next == NULL)) {
+						rte_pktmbuf_free(pkt);
+						++rxq->stats.rx_nombuf;
+						goto out;
+					}
+					NEXT(prev) = next;
+					SET_DATA_OFF(next, 0);
+					addr = RTE_PTR_ADD(addr, seg_len);
+					seg_len = RTE_MIN
+						(rte_pktmbuf_tailroom(next),
+						 rem_len);
+					rte_memcpy
+						(rte_pktmbuf_mtod(next, void *),
+						 addr, seg_len);
+					DATA_LEN(next) = seg_len;
+					rem_len -= seg_len;
+					prev = next;
+					++NB_SEGS(pkt);
+				}
+			} else {
 				rte_pktmbuf_free_seg(pkt);
 				++rxq->stats.idropped;
 				continue;
 			}
-			rte_memcpy(rte_pktmbuf_mtod(pkt, void *), addr, len);
-			DATA_LEN(pkt) = len;
 		} else {
 			rte_iova_t buf_iova;
 			struct rte_mbuf_ext_shared_info *shinfo;
@@ -1684,7 +1712,7 @@ mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			rte_atomic16_add_return(&buf->refcnt, 1);
 			assert((uint16_t)rte_atomic16_read(&buf->refcnt) <=
 			       strd_n + 1);
-			buf_addr = RTE_PTR_SUB(addr, headroom_sz);
+			buf_addr = RTE_PTR_SUB(addr, RTE_PKTMBUF_HEADROOM);
 			/*
 			 * MLX5 device doesn't use iova but it is necessary in a
 			 * case where the Rx packet is transmitted via a
@@ -1703,43 +1731,42 @@ mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			rte_pktmbuf_attach_extbuf(pkt, buf_addr, buf_iova,
 						  buf_len, shinfo);
 			/* Set mbuf head-room. */
-			pkt->data_off = headroom_sz;
+			SET_DATA_OFF(pkt, RTE_PKTMBUF_HEADROOM);
 			assert(pkt->ol_flags == EXT_ATTACHED_MBUF);
-			/*
-			 * Prevent potential overflow due to MTU change through
-			 * kernel interface.
-			 */
-			if (unlikely(rte_pktmbuf_tailroom(pkt) < len)) {
-				rte_pktmbuf_free_seg(pkt);
-				++rxq->stats.idropped;
-				continue;
-			}
+			assert(rte_pktmbuf_tailroom(pkt) >=
+				len - (hdrm_overlap > 0 ? hdrm_overlap : 0));
 			DATA_LEN(pkt) = len;
 			/*
-			 * LRO packet may consume all the stride memory, in this
-			 * case packet head-room space is not guaranteed so must
-			 * to add an empty mbuf for the head-room.
+			 * Copy the last fragment of a packet (up to headroom
+			 * size bytes) in case there is a stride overlap with
+			 * a next packet's headroom. Allocate a separate mbuf
+			 * to store this fragment and link it. Scatter is on.
 			 */
-			if (!rxq->strd_headroom_en) {
-				struct rte_mbuf *headroom_mbuf =
-						rte_pktmbuf_alloc(rxq->mp);
+			if (hdrm_overlap > 0) {
+				assert(rxq->strd_scatter_en);
+				struct rte_mbuf *seg =
+					rte_pktmbuf_alloc(rxq->mp);
 
-				if (unlikely(headroom_mbuf == NULL)) {
+				if (unlikely(seg == NULL)) {
 					rte_pktmbuf_free_seg(pkt);
 					++rxq->stats.rx_nombuf;
 					break;
 				}
-				PORT(pkt) = rxq->port_id;
-				NEXT(headroom_mbuf) = pkt;
-				pkt = headroom_mbuf;
+				SET_DATA_OFF(seg, 0);
+				rte_memcpy(rte_pktmbuf_mtod(seg, void *),
+					RTE_PTR_ADD(addr, len - hdrm_overlap),
+					hdrm_overlap);
+				DATA_LEN(seg) = hdrm_overlap;
+				DATA_LEN(pkt) = len - hdrm_overlap;
+				NEXT(pkt) = seg;
 				NB_SEGS(pkt) = 2;
 			}
 		}
 		rxq_cq_to_mbuf(rxq, pkt, cqe, rss_hash_res);
-		if (lro_num_seg > 1) {
+		if (cqe->lro_num_seg > 1) {
 			mlx5_lro_update_hdr(addr, cqe, len);
 			pkt->ol_flags |= PKT_RX_LRO;
-			pkt->tso_segsz = strd_sz;
+			pkt->tso_segsz = len / cqe->lro_num_seg;
 		}
 		PKT_LEN(pkt) = len;
 		PORT(pkt) = rxq->port_id;
@@ -1751,6 +1778,7 @@ mlx5_rx_burst_mprq(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		*(pkts++) = pkt;
 		++i;
 	}
+out:
 	/* Update the consumer indexes. */
 	rxq->consumed_strd = consumed_strd;
 	rte_cio_wmb();
@@ -2034,8 +2062,6 @@ mlx5_tx_copy_elts(struct mlx5_txq_data *restrict txq,
  *   Pointer to TX queue structure.
  * @param valid CQE pointer
  *   if not NULL update txq->wqe_pi and flush the buffers
- * @param itail
- *   if not negative - flush the buffers till this index.
  * @param olx
  *   Configured Tx offloads mask. It is fully defined at
  *   compile time and may be used for optimization.
@@ -2043,25 +2069,17 @@ mlx5_tx_copy_elts(struct mlx5_txq_data *restrict txq,
 static __rte_always_inline void
 mlx5_tx_comp_flush(struct mlx5_txq_data *restrict txq,
 		   volatile struct mlx5_cqe *last_cqe,
-		   int itail,
 		   unsigned int olx __rte_unused)
 {
-	uint16_t tail;
-
 	if (likely(last_cqe != NULL)) {
+		uint16_t tail;
+
 		txq->wqe_pi = rte_be_to_cpu_16(last_cqe->wqe_counter);
-		tail = ((volatile struct mlx5_wqe_cseg *)
-			(txq->wqes + (txq->wqe_pi & txq->wqe_m)))->misc;
-	} else if (itail >= 0) {
-		tail = (uint16_t)itail;
-	} else {
-		return;
-	}
-	rte_compiler_barrier();
-	*txq->cq_db = rte_cpu_to_be_32(txq->cq_ci);
-	if (likely(tail != txq->elts_tail)) {
-		mlx5_tx_free_elts(txq, tail, olx);
-		assert(tail == txq->elts_tail);
+		tail = txq->fcqs[(txq->cq_ci - 1) & txq->cqe_m];
+		if (likely(tail != txq->elts_tail)) {
+			mlx5_tx_free_elts(txq, tail, olx);
+			assert(tail == txq->elts_tail);
+		}
 	}
 }
 
@@ -2085,6 +2103,7 @@ mlx5_tx_handle_completion(struct mlx5_txq_data *restrict txq,
 {
 	unsigned int count = MLX5_TX_COMP_MAX_CQE;
 	volatile struct mlx5_cqe *last_cqe = NULL;
+	bool ring_doorbell = false;
 	int ret;
 
 	static_assert(MLX5_CQE_STATUS_HW_OWN < 0, "Must be negative value");
@@ -2109,31 +2128,49 @@ mlx5_tx_handle_completion(struct mlx5_txq_data *restrict txq,
 			rte_wmb();
 			ret = mlx5_tx_error_cqe_handle
 				(txq, (volatile struct mlx5_err_cqe *)cqe);
+			if (unlikely(ret < 0)) {
+				/*
+				 * Some error occurred on queue error
+				 * handling, we do not advance the index
+				 * here, allowing to retry on next call.
+				 */
+				return;
+			}
 			/*
-			 * Flush buffers, update consuming index
-			 * if recovery succeeded. Otherwise
-			 * just try to recover later.
+			 * We are going to fetch all entries with
+			 * MLX5_CQE_SYNDROME_WR_FLUSH_ERR status.
+			 * The send queue is supposed to be empty.
 			 */
+			ring_doorbell = true;
+			++txq->cq_ci;
+			txq->cq_pi = txq->cq_ci;
 			last_cqe = NULL;
-			break;
+			continue;
 		}
 		/* Normal transmit completion. */
+		assert(txq->cq_ci != txq->cq_pi);
+		assert((txq->fcqs[txq->cq_ci & txq->cqe_m] >> 16) ==
+			    cqe->wqe_counter);
+		ring_doorbell = true;
 		++txq->cq_ci;
 		last_cqe = cqe;
-#ifndef NDEBUG
-		if (txq->cq_pi)
-			--txq->cq_pi;
-#endif
-	/*
-	 * We have to restrict the amount of processed CQEs
-	 * in one tx_burst routine call. The CQ may be large
-	 * and many CQEs may be updated by the NIC in one
-	 * transaction. Buffers freeing is time consuming,
-	 * multiple iterations may introduce significant
-	 * latency.
-	 */
-	} while (--count);
-	mlx5_tx_comp_flush(txq, last_cqe, ret, olx);
+		/*
+		 * We have to restrict the amount of processed CQEs
+		 * in one tx_burst routine call. The CQ may be large
+		 * and many CQEs may be updated by the NIC in one
+		 * transaction. Buffers freeing is time consuming,
+		 * multiple iterations may introduce significant
+		 * latency.
+		 */
+		if (likely(--count == 0))
+			break;
+	} while (true);
+	if (likely(ring_doorbell)) {
+		/* Ring doorbell to notify hardware. */
+		rte_compiler_barrier();
+		*txq->cq_db = rte_cpu_to_be_32(txq->cq_ci);
+		mlx5_tx_comp_flush(txq, last_cqe, olx);
+	}
 }
 
 /**
@@ -2145,9 +2182,6 @@ mlx5_tx_handle_completion(struct mlx5_txq_data *restrict txq,
  *   Pointer to TX queue structure.
  * @param loc
  *   Pointer to burst routine local context.
- * @param multi,
- *   Routine is called from multi-segment sending loop,
- *   do not correct the elts_head according to the pkts_copy.
  * @param olx
  *   Configured Tx offloads mask. It is fully defined at
  *   compile time and may be used for optimization.
@@ -2155,13 +2189,12 @@ mlx5_tx_handle_completion(struct mlx5_txq_data *restrict txq,
 static __rte_always_inline void
 mlx5_tx_request_completion(struct mlx5_txq_data *restrict txq,
 			   struct mlx5_txq_local *restrict loc,
-			   bool multi,
 			   unsigned int olx)
 {
 	uint16_t head = txq->elts_head;
 	unsigned int part;
 
-	part = (MLX5_TXOFF_CONFIG(INLINE) || multi) ?
+	part = MLX5_TXOFF_CONFIG(INLINE) ?
 	       0 : loc->pkts_sent - loc->pkts_copy;
 	head += part;
 	if ((uint16_t)(head - txq->elts_comp) >= MLX5_TX_COMP_THRESH ||
@@ -2175,15 +2208,15 @@ mlx5_tx_request_completion(struct mlx5_txq_data *restrict txq,
 		/* Request unconditional completion on last WQE. */
 		last->cseg.flags = RTE_BE32(MLX5_COMP_ALWAYS <<
 					    MLX5_COMP_MODE_OFFSET);
-		/* Save elts_head in unused "immediate" field of WQE. */
-		last->cseg.misc = head;
-		/*
-		 * A CQE slot must always be available. Count the
-		 * issued CEQ "always" request instead of production
-		 * index due to here can be CQE with errors and
-		 * difference with ci may become inconsistent.
-		 */
-		assert(txq->cqe_s > ++txq->cq_pi);
+		/* Save elts_head in dedicated free on completion queue. */
+#ifdef NDEBUG
+		txq->fcqs[txq->cq_pi++ & txq->cqe_m] = head;
+#else
+		txq->fcqs[txq->cq_pi++ & txq->cqe_m] = head |
+					(last->cseg.opcode >> 8) << 16;
+#endif
+		/* A CQE slot must always be available. */
+		assert((txq->cq_pi - txq->cq_ci) <= txq->cqe_s);
 	}
 }
 
@@ -2818,8 +2851,14 @@ mlx5_tx_dseg_empw(struct mlx5_txq_data *restrict txq,
 	unsigned int part;
 	uint8_t *pdst;
 
-	dseg->bcount = rte_cpu_to_be_32(len | MLX5_ETH_WQE_DATA_INLINE);
-	pdst = &dseg->inline_data[0];
+	if (!MLX5_TXOFF_CONFIG(MPW)) {
+		/* Store the descriptor byte counter for eMPW sessions. */
+		dseg->bcount = rte_cpu_to_be_32(len | MLX5_ETH_WQE_DATA_INLINE);
+		pdst = &dseg->inline_data[0];
+	} else {
+		/* The entire legacy MPW session counter is stored on close. */
+		pdst = (uint8_t *)dseg;
+	}
 	/*
 	 * The WQEBB space availability is checked by caller.
 	 * Here we should be aware of WQE ring buffer wraparound only.
@@ -2831,7 +2870,8 @@ mlx5_tx_dseg_empw(struct mlx5_txq_data *restrict txq,
 		len -= part;
 		if (likely(!len)) {
 			pdst += part;
-			pdst = RTE_PTR_ALIGN(pdst, MLX5_WSEG_SIZE);
+			if (!MLX5_TXOFF_CONFIG(MPW))
+				pdst = RTE_PTR_ALIGN(pdst, MLX5_WSEG_SIZE);
 			/* Note: no final wraparound check here. */
 			return (struct mlx5_wqe_dseg *)pdst;
 		}
@@ -2879,9 +2919,16 @@ mlx5_tx_dseg_vlan(struct mlx5_txq_data *restrict txq,
 	static_assert(MLX5_DSEG_MIN_INLINE_SIZE ==
 				 (2 * RTE_ETHER_ADDR_LEN),
 		      "invalid Data Segment data size");
-	dseg->bcount = rte_cpu_to_be_32((len + sizeof(struct rte_vlan_hdr)) |
-					MLX5_ETH_WQE_DATA_INLINE);
-	pdst = &dseg->inline_data[0];
+	if (!MLX5_TXOFF_CONFIG(MPW)) {
+		/* Store the descriptor byte counter for eMPW sessions. */
+		dseg->bcount = rte_cpu_to_be_32
+				((len + sizeof(struct rte_vlan_hdr)) |
+				 MLX5_ETH_WQE_DATA_INLINE);
+		pdst = &dseg->inline_data[0];
+	} else {
+		/* The entire legacy MPW session counter is stored on close. */
+		pdst = (uint8_t *)dseg;
+	}
 	memcpy(pdst, buf, MLX5_DSEG_MIN_INLINE_SIZE);
 	buf += MLX5_DSEG_MIN_INLINE_SIZE;
 	pdst += MLX5_DSEG_MIN_INLINE_SIZE;
@@ -2904,7 +2951,8 @@ mlx5_tx_dseg_vlan(struct mlx5_txq_data *restrict txq,
 		len -= part;
 		if (likely(!len)) {
 			pdst += part;
-			pdst = RTE_PTR_ALIGN(pdst, MLX5_WSEG_SIZE);
+			if (!MLX5_TXOFF_CONFIG(MPW))
+				pdst = RTE_PTR_ALIGN(pdst, MLX5_WSEG_SIZE);
 			/* Note: no final wraparound check here. */
 			return (struct mlx5_wqe_dseg *)pdst;
 		}
@@ -3120,8 +3168,6 @@ mlx5_tx_packet_multi_tso(struct mlx5_txq_data *restrict txq,
 	wqe->cseg.sq_ds = rte_cpu_to_be_32(txq->qp_num_8s | ds);
 	txq->wqe_ci += (ds + 3) / 4;
 	loc->wqe_free -= (ds + 3) / 4;
-	/* Request CQE generation if limits are reached. */
-	mlx5_tx_request_completion(txq, loc, true, olx);
 	return MLX5_TXCMP_CODE_MULTI;
 }
 
@@ -3230,8 +3276,6 @@ mlx5_tx_packet_multi_send(struct mlx5_txq_data *restrict txq,
 	} while (true);
 	txq->wqe_ci += (ds + 3) / 4;
 	loc->wqe_free -= (ds + 3) / 4;
-	/* Request CQE generation if limits are reached. */
-	mlx5_tx_request_completion(txq, loc, true, olx);
 	return MLX5_TXCMP_CODE_MULTI;
 }
 
@@ -3388,8 +3432,6 @@ mlx5_tx_packet_multi_inline(struct mlx5_txq_data *restrict txq,
 	wqe->cseg.sq_ds = rte_cpu_to_be_32(txq->qp_num_8s | ds);
 	txq->wqe_ci += (ds + 3) / 4;
 	loc->wqe_free -= (ds + 3) / 4;
-	/* Request CQE generation if limits are reached. */
-	mlx5_tx_request_completion(txq, loc, true, olx);
 	return MLX5_TXCMP_CODE_MULTI;
 }
 
@@ -3599,8 +3641,6 @@ mlx5_tx_burst_tso(struct mlx5_txq_data *restrict txq,
 		--loc->elts_free;
 		++loc->pkts_sent;
 		--pkts_n;
-		/* Request CQE generation if limits are reached. */
-		mlx5_tx_request_completion(txq, loc, false, olx);
 		if (unlikely(!pkts_n || !loc->elts_free || !loc->wqe_free))
 			return MLX5_TXCMP_CODE_EXIT;
 		loc->mbuf = *pkts++;
@@ -3750,7 +3790,7 @@ mlx5_tx_sdone_empw(struct mlx5_txq_data *restrict txq,
 		   struct mlx5_txq_local *restrict loc,
 		   unsigned int ds,
 		   unsigned int slen,
-		   unsigned int olx)
+		   unsigned int olx __rte_unused)
 {
 	assert(!MLX5_TXOFF_CONFIG(INLINE));
 #ifdef MLX5_PMD_SOFT_COUNTERS
@@ -3765,8 +3805,6 @@ mlx5_tx_sdone_empw(struct mlx5_txq_data *restrict txq,
 	loc->wqe_last->cseg.sq_ds = rte_cpu_to_be_32(txq->qp_num_8s | ds);
 	txq->wqe_ci += (ds + 3) / 4;
 	loc->wqe_free -= (ds + 3) / 4;
-	/* Request CQE generation if limits are reached. */
-	mlx5_tx_request_completion(txq, loc, false, olx);
 }
 
 /*
@@ -3797,20 +3835,36 @@ mlx5_tx_idone_empw(struct mlx5_txq_data *restrict txq,
 		   unsigned int slen,
 		   unsigned int olx __rte_unused)
 {
+	struct mlx5_wqe_dseg *dseg = &loc->wqe_last->dseg[0];
+
 	assert(MLX5_TXOFF_CONFIG(INLINE));
-	assert((len % MLX5_WSEG_SIZE) == 0);
 #ifdef MLX5_PMD_SOFT_COUNTERS
 	/* Update sent data bytes counter. */
 	 txq->stats.obytes += slen;
 #else
 	(void)slen;
 #endif
-	len = len / MLX5_WSEG_SIZE + 2;
+	if (MLX5_TXOFF_CONFIG(MPW) && dseg->bcount == RTE_BE32(0)) {
+		/*
+		 * If the legacy MPW session contains the inline packets
+		 * we should set the only inline data segment length
+		 * and align the total length to the segment size.
+		 */
+		assert(len > sizeof(dseg->bcount));
+		dseg->bcount = rte_cpu_to_be_32((len - sizeof(dseg->bcount)) |
+						MLX5_ETH_WQE_DATA_INLINE);
+		len = (len + MLX5_WSEG_SIZE - 1) / MLX5_WSEG_SIZE + 2;
+	} else {
+		/*
+		 * The session is not legacy MPW or contains the
+		 * data buffer pointer segments.
+		 */
+		assert((len % MLX5_WSEG_SIZE) == 0);
+		len = len / MLX5_WSEG_SIZE + 2;
+	}
 	loc->wqe_last->cseg.sq_ds = rte_cpu_to_be_32(txq->qp_num_8s | len);
 	txq->wqe_ci += (len + 3) / 4;
 	loc->wqe_free -= (len + 3) / 4;
-	/* Request CQE generation if limits are reached. */
-	mlx5_tx_request_completion(txq, loc, false, olx);
 }
 
 /**
@@ -4011,8 +4065,6 @@ mlx5_tx_burst_empw_simple(struct mlx5_txq_data *restrict txq,
 		txq->wqe_ci += (2 + part + 3) / 4;
 		loc->wqe_free -= (2 + part + 3) / 4;
 		pkts_n -= part;
-		/* Request CQE generation if limits are reached. */
-		mlx5_tx_request_completion(txq, loc, false, olx);
 		if (unlikely(!pkts_n || !loc->elts_free || !loc->wqe_free))
 			return MLX5_TXCMP_CODE_EXIT;
 		loc->mbuf = *pkts++;
@@ -4088,6 +4140,15 @@ mlx5_tx_burst_empw_inline(struct mlx5_txq_data *restrict txq,
 			       loc->wqe_free) * MLX5_WQE_SIZE -
 					MLX5_WQE_CSEG_SIZE -
 					MLX5_WQE_ESEG_SIZE;
+		/* Limit the room for legacy MPW sessions for performance. */
+		if (MLX5_TXOFF_CONFIG(MPW))
+			room = RTE_MIN(room,
+				       RTE_MAX(txq->inlen_empw +
+					       sizeof(dseg->bcount) +
+					       (MLX5_TXOFF_CONFIG(VLAN) ?
+					       sizeof(struct rte_vlan_hdr) : 0),
+					       MLX5_MPW_INLINE_MAX_PACKETS *
+					       MLX5_WQE_DSEG_SIZE));
 		/* Build WQE till we have space, packets and resources. */
 		part = room;
 		for (;;) {
@@ -4117,8 +4178,28 @@ mlx5_tx_burst_empw_inline(struct mlx5_txq_data *restrict txq,
 			/* Inline or not inline - that's the Question. */
 			if (dlen > txq->inlen_empw)
 				goto pointer_empw;
+			if (MLX5_TXOFF_CONFIG(MPW)) {
+				if (dlen > txq->inlen_send)
+					goto pointer_empw;
+				tlen = dlen;
+				if (part == room) {
+					/* Open new inline MPW session. */
+					tlen += sizeof(dseg->bcount);
+					dseg->bcount = RTE_BE32(0);
+					dseg = RTE_PTR_ADD
+						(dseg, sizeof(dseg->bcount));
+				} else {
+					/*
+					 * No pointer and inline descriptor
+					 * intermix for legacy MPW sessions.
+					 */
+					if (loc->wqe_last->dseg[0].bcount)
+						break;
+				}
+			} else {
+				tlen = sizeof(dseg->bcount) + dlen;
+			}
 			/* Inline entire packet, optional VLAN insertion. */
-			tlen = sizeof(dseg->bcount) + dlen;
 			if (MLX5_TXOFF_CONFIG(VLAN) &&
 			    loc->mbuf->ol_flags & PKT_TX_VLAN_PKT) {
 				/*
@@ -4143,7 +4224,8 @@ mlx5_tx_burst_empw_inline(struct mlx5_txq_data *restrict txq,
 				dseg = mlx5_tx_dseg_empw(txq, loc, dseg,
 							 dptr, dlen, olx);
 			}
-			tlen = RTE_ALIGN(tlen, MLX5_WSEG_SIZE);
+			if (!MLX5_TXOFF_CONFIG(MPW))
+				tlen = RTE_ALIGN(tlen, MLX5_WSEG_SIZE);
 			assert(room >= tlen);
 			room -= tlen;
 			/*
@@ -4153,6 +4235,14 @@ mlx5_tx_burst_empw_inline(struct mlx5_txq_data *restrict txq,
 			rte_pktmbuf_free_seg(loc->mbuf);
 			goto next_mbuf;
 pointer_empw:
+			/*
+			 * No pointer and inline descriptor
+			 * intermix for legacy MPW sessions.
+			 */
+			if (MLX5_TXOFF_CONFIG(MPW) &&
+			    part != room &&
+			    loc->wqe_last->dseg[0].bcount == RTE_BE32(0))
+				break;
 			/*
 			 * Not inlinable VLAN packets are
 			 * proceeded outside of this routine.
@@ -4496,8 +4586,6 @@ mlx5_tx_burst_single_send(struct mlx5_txq_data *restrict txq,
 		}
 		++loc->pkts_sent;
 		--pkts_n;
-		/* Request CQE generation if limits are reached. */
-		mlx5_tx_request_completion(txq, loc, false, olx);
 		if (unlikely(!pkts_n || !loc->elts_free || !loc->wqe_free))
 			return MLX5_TXCMP_CODE_EXIT;
 		loc->mbuf = *pkts++;
@@ -4596,7 +4684,7 @@ mlx5_tx_burst_tmpl(struct mlx5_txq_data *restrict txq,
 	/*
 	 * Calculate the number of available resources - elts and WQEs.
 	 * There are two possible different scenarios:
-	 * - no data inlining into WQEs, one WQEBB may contains upto
+	 * - no data inlining into WQEs, one WQEBB may contains up to
 	 *   four packets, in this case elts become scarce resource
 	 * - data inlining into WQEs, one packet may require multiple
 	 *   WQEBBs, the WQEs become the limiting factor.
@@ -4776,6 +4864,8 @@ mlx5_tx_burst_tmpl(struct mlx5_txq_data *restrict txq,
 	/* Take a shortcut if nothing is sent. */
 	if (unlikely(loc.pkts_sent == loc.pkts_loop))
 		goto burst_exit;
+	/* Request CQE generation if limits are reached. */
+	mlx5_tx_request_completion(txq, &loc, olx);
 	/*
 	 * Ring QP doorbell immediately after WQE building completion
 	 * to improve latencies. The pure software related data treatment
@@ -4977,7 +5067,7 @@ MLX5_TXOFF_DECL(iv,
 
 /*
  * Generate routines with Legacy Multi-Packet Write support.
- * This mode is supported by ConnectX-4LX only and imposes
+ * This mode is supported by ConnectX-4 Lx only and imposes
  * offload limitations, not supported:
  *   - ACL/Flows (metadata are becoming meaningless)
  *   - WQE Inline headers
@@ -4995,6 +5085,10 @@ MLX5_TXOFF_DECL(mci_mpw,
 		MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_EMPW |
 		MLX5_TXOFF_CONFIG_MPW)
 
+MLX5_TXOFF_DECL(mc_mpw,
+		MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_CSUM |
+		MLX5_TXOFF_CONFIG_EMPW | MLX5_TXOFF_CONFIG_MPW)
+
 MLX5_TXOFF_DECL(i_mpw,
 		MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_EMPW |
 		MLX5_TXOFF_CONFIG_MPW)
@@ -5151,6 +5245,10 @@ MLX5_TXOFF_INFO(mci_mpw,
 		MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_EMPW |
 		MLX5_TXOFF_CONFIG_MPW)
 
+MLX5_TXOFF_INFO(mc_mpw,
+		MLX5_TXOFF_CONFIG_MULTI | MLX5_TXOFF_CONFIG_CSUM |
+		MLX5_TXOFF_CONFIG_EMPW | MLX5_TXOFF_CONFIG_MPW)
+
 MLX5_TXOFF_INFO(i_mpw,
 		MLX5_TXOFF_CONFIG_INLINE | MLX5_TXOFF_CONFIG_EMPW |
 		MLX5_TXOFF_CONFIG_MPW)
@@ -5277,6 +5375,9 @@ mlx5_select_tx_function(struct rte_eth_dev *dev)
 			/* Does not meet requested offloads at all. */
 			continue;
 		}
+		if ((olx ^ tmp) & MLX5_TXOFF_CONFIG_MPW)
+			/* Do not enable legacy MPW if not configured. */
+			continue;
 		if ((olx ^ tmp) & MLX5_TXOFF_CONFIG_EMPW)
 			/* Do not enable eMPW if not configured. */
 			continue;
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxtx.h b/dpdk/drivers/net/mlx5/mlx5_rxtx.h
index e927343f7d..daa67e2f5c 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxtx.h
+++ b/dpdk/drivers/net/mlx5/mlx5_rxtx.h
@@ -114,9 +114,9 @@ struct mlx5_rxq_data {
 	unsigned int strd_sz_n:4; /* Log 2 of stride size. */
 	unsigned int strd_shift_en:1; /* Enable 2bytes shift on a stride. */
 	unsigned int err_state:2; /* enum mlx5_rxq_err_state. */
-	unsigned int strd_headroom_en:1; /* Enable mbuf headroom in MPRQ. */
+	unsigned int strd_scatter_en:1; /* Scattered packets from a stride. */
 	unsigned int lro:1; /* Enable LRO. */
-	unsigned int :1; /* Remaining bits. */
+	unsigned int dynf_meta:1; /* Dynamic metadata is configured. */
 	volatile uint32_t *rq_db;
 	volatile uint32_t *cq_db;
 	uint16_t port_id;
@@ -154,6 +154,8 @@ struct mlx5_rxq_data {
 	/* CQ (UAR) access lock required for 32bit implementations */
 #endif
 	uint32_t tunnel; /* Tunnel information. */
+	uint64_t flow_meta_mask;
+	int32_t flow_meta_offset;
 } __rte_cache_aligned;
 
 enum mlx5_rxq_obj_type {
@@ -273,9 +275,7 @@ struct mlx5_txq_data {
 	uint16_t wqe_thres; /* WQE threshold to request completion in CQ. */
 	/* WQ related fields. */
 	uint16_t cq_ci; /* Consumer index for completion queue. */
-#ifndef NDEBUG
-	uint16_t cq_pi; /* Counter of issued CQE "always" requests. */
-#endif
+	uint16_t cq_pi; /* Production index for completion queue. */
 	uint16_t cqe_s; /* Number of CQ elements. */
 	uint16_t cqe_m; /* Mask for CQ indices. */
 	/* CQ related fields. */
@@ -297,6 +297,11 @@ struct mlx5_txq_data {
 	struct mlx5_mr_ctrl mr_ctrl; /* MR control descriptor. */
 	struct mlx5_wqe *wqes; /* Work queue. */
 	struct mlx5_wqe *wqes_end; /* Work queue array limit. */
+#ifdef NDEBUG
+	uint16_t *fcqs; /* Free completion queue. */
+#else
+	uint32_t *fcqs; /* Free completion queue (debug extended). */
+#endif
 	volatile struct mlx5_cqe *cqes; /* Completion queue. */
 	volatile uint32_t *qp_db; /* Work queue doorbell. */
 	volatile uint32_t *cq_db; /* Completion queue doorbell. */
@@ -424,6 +429,7 @@ int mlx5_tx_hairpin_queue_setup
 	 const struct rte_eth_hairpin_conf *hairpin_conf);
 void mlx5_tx_queue_release(void *dpdk_txq);
 int mlx5_tx_uar_init_secondary(struct rte_eth_dev *dev, int fd);
+void mlx5_tx_uar_uninit_secondary(struct rte_eth_dev *dev);
 struct mlx5_txq_obj *mlx5_txq_obj_new(struct rte_eth_dev *dev, uint16_t idx,
 				      enum mlx5_txq_obj_type type);
 struct mlx5_txq_obj *mlx5_txq_obj_get(struct rte_eth_dev *dev, uint16_t idx);
@@ -440,6 +446,7 @@ int mlx5_txq_release(struct rte_eth_dev *dev, uint16_t idx);
 int mlx5_txq_releasable(struct rte_eth_dev *dev, uint16_t idx);
 int mlx5_txq_verify(struct rte_eth_dev *dev);
 void txq_alloc_elts(struct mlx5_txq_ctrl *txq_ctrl);
+void txq_free_elts(struct mlx5_txq_ctrl *txq_ctrl);
 uint64_t mlx5_get_tx_port_offloads(struct rte_eth_dev *dev);
 
 /* mlx5_rxtx.c */
@@ -451,9 +458,6 @@ extern uint8_t mlx5_swp_types_table[];
 void mlx5_set_ptype_table(void);
 void mlx5_set_cksum_table(void);
 void mlx5_set_swp_types_table(void);
-__rte_noinline int mlx5_tx_error_cqe_handle
-				(struct mlx5_txq_data *restrict txq,
-				 volatile struct mlx5_err_cqe *err_cqe);
 uint16_t mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n);
 void mlx5_rxq_initialize(struct mlx5_rxq_data *rxq);
 __rte_noinline int mlx5_rx_err_handle(struct mlx5_rxq_data *rxq, uint8_t vec);
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec.c b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec.c
index d85f90874d..0c705d1f7f 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec.c
+++ b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec.c
@@ -103,13 +103,20 @@ uint16_t
 mlx5_rx_burst_vec(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 {
 	struct mlx5_rxq_data *rxq = dpdk_rxq;
-	uint16_t nb_rx;
+	uint16_t nb_rx = 0;
+	uint16_t tn = 0;
 	uint64_t err = 0;
+	bool no_cq = false;
 
-	nb_rx = rxq_burst_v(rxq, pkts, pkts_n, &err);
-	if (unlikely(err | rxq->err_state))
-		nb_rx = rxq_handle_pending_error(rxq, pkts, nb_rx);
-	return nb_rx;
+	do {
+		nb_rx = rxq_burst_v(rxq, pkts + tn, pkts_n - tn, &err, &no_cq);
+		if (unlikely(err | rxq->err_state))
+			nb_rx = rxq_handle_pending_error(rxq, pkts + tn, nb_rx);
+		tn += nb_rx;
+		if (unlikely(no_cq))
+			break;
+	} while (tn != pkts_n);
+	return tn;
 }
 
 /**
@@ -149,7 +156,7 @@ int __attribute__((cold))
 mlx5_check_vec_rx_support(struct rte_eth_dev *dev)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint16_t i;
+	uint32_t i;
 
 	if (!priv->config.rx_vec_en)
 		return -ENOTSUP;
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_altivec.h b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_altivec.h
index 8e79883dfe..c167672f52 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_altivec.h
+++ b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_altivec.h
@@ -11,7 +11,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include <altivec.h>
+#include <rte_altivec.h>
 
 #include <rte_mbuf.h>
 #include <rte_mempool.h>
@@ -263,6 +263,25 @@ rxq_cq_decompress_v(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cq,
 			elts[pos + 2]->hash.fdir.hi = flow_tag;
 			elts[pos + 3]->hash.fdir.hi = flow_tag;
 		}
+		if (rxq->dynf_meta) {
+			int32_t offs = rxq->flow_meta_offset;
+			const uint32_t meta =
+				*RTE_MBUF_DYNFIELD(t_pkt, offs, uint32_t *);
+
+			/* Check if title packet has valid metadata. */
+			if (meta) {
+				assert(t_pkt->ol_flags &
+					    rxq->flow_meta_mask);
+				*RTE_MBUF_DYNFIELD(elts[pos], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 1], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 2], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 3], offs,
+							uint32_t *) = meta;
+			}
+		}
 
 		pos += MLX5_VPMD_DESCS_PER_LOOP;
 		/* Move to next CQE and invalidate consumed CQEs. */
@@ -545,13 +564,15 @@ rxq_cq_to_ptype_oflags_v(struct mlx5_rxq_data *rxq,
  * @param[out] err
  *   Pointer to a flag. Set non-zero value if pkts array has at least one error
  *   packet to handle.
+ * @param[out] no_cq
+ *  Pointer to a boolean. Set true if no new CQE seen.
  *
  * @return
  *   Number of packets received including errors (<= pkts_n).
  */
 static inline uint16_t
 rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
-	    uint64_t *err)
+	    uint64_t *err, bool *no_cq)
 {
 	const uint16_t q_n = 1 << rxq->cqe_n;
 	const uint16_t q_mask = q_n - 1;
@@ -644,8 +665,10 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 	/* Not to cross queue end. */
 	pkts_n = RTE_MIN(pkts_n, q_n - elts_idx);
 	pkts_n = RTE_MIN(pkts_n, q_n - cq_idx);
-	if (!pkts_n)
+	if (!pkts_n) {
+		*no_cq = !rcvd_pkt;
 		return rcvd_pkt;
+	}
 	/* At this point, there shouldn't be any remaining packets. */
 	assert(rxq->decompressed == 0);
 
@@ -1010,9 +1033,9 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 			pkts[pos + 3]->timestamp =
 				rte_be_to_cpu_64(cq[pos + p3].timestamp);
 		}
-		if (rte_flow_dynf_metadata_avail()) {
-			uint64_t flag = rte_flow_dynf_metadata_mask;
-			int offs = rte_flow_dynf_metadata_offs;
+		if (rxq->dynf_meta) {
+			uint64_t flag = rxq->flow_meta_mask;
+			int32_t offs = rxq->flow_meta_offset;
 			uint32_t metadata;
 
 			/* This code is subject for futher optimization. */
@@ -1060,8 +1083,10 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 			break;
 	}
 	/* If no new CQE seen, return without updating cq_db. */
-	if (unlikely(!nocmp_n && comp_idx == MLX5_VPMD_DESCS_PER_LOOP))
+	if (unlikely(!nocmp_n && comp_idx == MLX5_VPMD_DESCS_PER_LOOP)) {
+		*no_cq = true;
 		return rcvd_pkt;
+	}
 	/* Update the consumer indexes for non-compressed CQEs. */
 	assert(nocmp_n <= pkts_n);
 	rxq->cq_ci += nocmp_n;
@@ -1089,6 +1114,7 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 	}
 	rte_compiler_barrier();
 	*rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
+	*no_cq = !rcvd_pkt;
 	return rcvd_pkt;
 }
 
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_neon.h b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_neon.h
index 86785c7496..607659a629 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_neon.h
+++ b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_neon.h
@@ -205,6 +205,25 @@ rxq_cq_decompress_v(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cq,
 			elts[pos + 2]->hash.fdir.hi = flow_tag;
 			elts[pos + 3]->hash.fdir.hi = flow_tag;
 		}
+		if (rxq->dynf_meta) {
+			int32_t offs = rxq->flow_meta_offset;
+			const uint32_t meta =
+				*RTE_MBUF_DYNFIELD(t_pkt, offs, uint32_t *);
+
+			/* Check if title packet has valid metadata. */
+			if (meta) {
+				assert(t_pkt->ol_flags &
+					    rxq->flow_meta_mask);
+				*RTE_MBUF_DYNFIELD(elts[pos], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 1], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 2], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 3], offs,
+							uint32_t *) = meta;
+			}
+		}
 		pos += MLX5_VPMD_DESCS_PER_LOOP;
 		/* Move to next CQE and invalidate consumed CQEs. */
 		if (!(pos & 0x7) && pos < mcqe_n) {
@@ -358,13 +377,15 @@ rxq_cq_to_ptype_oflags_v(struct mlx5_rxq_data *rxq,
  * @param[out] err
  *   Pointer to a flag. Set non-zero value if pkts array has at least one error
  *   packet to handle.
+ * @param[out] no_cq
+ *   Pointer to a boolean. Set true if no new CQE seen.
  *
  * @return
  *   Number of packets received including errors (<= pkts_n).
  */
 static inline uint16_t
 rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
-	    uint64_t *err)
+	    uint64_t *err, bool *no_cq)
 {
 	const uint16_t q_n = 1 << rxq->cqe_n;
 	const uint16_t q_mask = q_n - 1;
@@ -465,8 +486,10 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 	/* Not to cross queue end. */
 	pkts_n = RTE_MIN(pkts_n, q_n - elts_idx);
 	pkts_n = RTE_MIN(pkts_n, q_n - cq_idx);
-	if (!pkts_n)
+	if (!pkts_n) {
+		*no_cq = !rcvd_pkt;
 		return rcvd_pkt;
+	}
 	/* At this point, there shouldn't be any remained packets. */
 	assert(rxq->decompressed == 0);
 	/*
@@ -687,28 +710,30 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 					container_of(p3, struct mlx5_cqe,
 						     pkt_info)->timestamp);
 		}
-		if (rte_flow_dynf_metadata_avail()) {
+		if (rxq->dynf_meta) {
 			/* This code is subject for futher optimization. */
-			*RTE_FLOW_DYNF_METADATA(elts[pos]) =
+			int32_t offs = rxq->flow_meta_offset;
+
+			*RTE_MBUF_DYNFIELD(pkts[pos], offs, uint32_t *) =
 				container_of(p0, struct mlx5_cqe,
 					     pkt_info)->flow_table_metadata;
-			*RTE_FLOW_DYNF_METADATA(elts[pos + 1]) =
+			*RTE_MBUF_DYNFIELD(pkts[pos + 1], offs, uint32_t *) =
 				container_of(p1, struct mlx5_cqe,
 					     pkt_info)->flow_table_metadata;
-			*RTE_FLOW_DYNF_METADATA(elts[pos + 2]) =
+			*RTE_MBUF_DYNFIELD(pkts[pos + 2], offs, uint32_t *) =
 				container_of(p2, struct mlx5_cqe,
 					     pkt_info)->flow_table_metadata;
-			*RTE_FLOW_DYNF_METADATA(elts[pos + 3]) =
+			*RTE_MBUF_DYNFIELD(pkts[pos + 3], offs, uint32_t *) =
 				container_of(p3, struct mlx5_cqe,
 					     pkt_info)->flow_table_metadata;
-			if (*RTE_FLOW_DYNF_METADATA(elts[pos]))
-				elts[pos]->ol_flags |= PKT_RX_DYNF_METADATA;
-			if (*RTE_FLOW_DYNF_METADATA(elts[pos + 1]))
-				elts[pos + 1]->ol_flags |= PKT_RX_DYNF_METADATA;
-			if (*RTE_FLOW_DYNF_METADATA(elts[pos + 2]))
-				elts[pos + 2]->ol_flags |= PKT_RX_DYNF_METADATA;
-			if (*RTE_FLOW_DYNF_METADATA(elts[pos + 3]))
-				elts[pos + 3]->ol_flags |= PKT_RX_DYNF_METADATA;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos], offs, uint32_t *))
+				elts[pos]->ol_flags |= rxq->flow_meta_mask;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos + 1], offs, uint32_t *))
+				elts[pos + 1]->ol_flags |= rxq->flow_meta_mask;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos + 2], offs, uint32_t *))
+				elts[pos + 2]->ol_flags |= rxq->flow_meta_mask;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos + 3], offs, uint32_t *))
+				elts[pos + 3]->ol_flags |= rxq->flow_meta_mask;
 		}
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		/* Add up received bytes count. */
@@ -723,8 +748,10 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 			break;
 	}
 	/* If no new CQE seen, return without updating cq_db. */
-	if (unlikely(!nocmp_n && comp_idx == MLX5_VPMD_DESCS_PER_LOOP))
+	if (unlikely(!nocmp_n && comp_idx == MLX5_VPMD_DESCS_PER_LOOP)) {
+		*no_cq = true;
 		return rcvd_pkt;
+	}
 	/* Update the consumer indexes for non-compressed CQEs. */
 	assert(nocmp_n <= pkts_n);
 	rxq->cq_ci += nocmp_n;
@@ -752,6 +779,7 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 	}
 	rte_cio_wmb();
 	*rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
+	*no_cq = !rcvd_pkt;
 	return rcvd_pkt;
 }
 
diff --git a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_sse.h b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_sse.h
index 35b7761007..9935299d59 100644
--- a/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_sse.h
+++ b/dpdk/drivers/net/mlx5/mlx5_rxtx_vec_sse.h
@@ -118,7 +118,6 @@ rxq_cq_decompress_v(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cq,
 			     14, 15,  6,  7,
 			     10, 11,  2,  3);
 #endif
-
 	/*
 	 * A. load mCQEs into a 128bit register.
 	 * B. store rearm data to mbuf.
@@ -191,6 +190,25 @@ rxq_cq_decompress_v(struct mlx5_rxq_data *rxq, volatile struct mlx5_cqe *cq,
 			elts[pos + 2]->hash.fdir.hi = flow_tag;
 			elts[pos + 3]->hash.fdir.hi = flow_tag;
 		}
+		if (rxq->dynf_meta) {
+			int32_t offs = rxq->flow_meta_offset;
+			const uint32_t meta =
+				*RTE_MBUF_DYNFIELD(t_pkt, offs, uint32_t *);
+
+			/* Check if title packet has valid metadata. */
+			if (meta) {
+				assert(t_pkt->ol_flags &
+					    rxq->flow_meta_mask);
+				*RTE_MBUF_DYNFIELD(elts[pos], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 1], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 2], offs,
+							uint32_t *) = meta;
+				*RTE_MBUF_DYNFIELD(elts[pos + 3], offs,
+							uint32_t *) = meta;
+			}
+		}
 		pos += MLX5_VPMD_DESCS_PER_LOOP;
 		/* Move to next CQE and invalidate consumed CQEs. */
 		if (!(pos & 0x7) && pos < mcqe_n) {
@@ -365,13 +383,15 @@ rxq_cq_to_ptype_oflags_v(struct mlx5_rxq_data *rxq, __m128i cqes[4],
  * @param[out] err
  *   Pointer to a flag. Set non-zero value if pkts array has at least one error
  *   packet to handle.
+ * @param[out] no_cq
+ *   Pointer to a boolean. Set true if no new CQE seen.
  *
  * @return
  *   Number of packets received including errors (<= pkts_n).
  */
 static inline uint16_t
 rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
-	    uint64_t *err)
+	    uint64_t *err, bool *no_cq)
 {
 	const uint16_t q_n = 1 << rxq->cqe_n;
 	const uint16_t q_mask = q_n - 1;
@@ -453,8 +473,10 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 	/* Not to cross queue end. */
 	pkts_n = RTE_MIN(pkts_n, q_n - elts_idx);
 	pkts_n = RTE_MIN(pkts_n, q_n - cq_idx);
-	if (!pkts_n)
+	if (!pkts_n) {
+		*no_cq = !rcvd_pkt;
 		return rcvd_pkt;
+	}
 	/* At this point, there shouldn't be any remained packets. */
 	assert(rxq->decompressed == 0);
 	/*
@@ -640,24 +662,26 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 			pkts[pos + 3]->timestamp =
 				rte_be_to_cpu_64(cq[pos + p3].timestamp);
 		}
-		if (rte_flow_dynf_metadata_avail()) {
+		if (rxq->dynf_meta) {
 			/* This code is subject for futher optimization. */
-			*RTE_FLOW_DYNF_METADATA(pkts[pos]) =
+			int32_t offs = rxq->flow_meta_offset;
+
+			*RTE_MBUF_DYNFIELD(pkts[pos], offs, uint32_t *) =
 				cq[pos].flow_table_metadata;
-			*RTE_FLOW_DYNF_METADATA(pkts[pos + 1]) =
+			*RTE_MBUF_DYNFIELD(pkts[pos + 1], offs, uint32_t *) =
 				cq[pos + p1].flow_table_metadata;
-			*RTE_FLOW_DYNF_METADATA(pkts[pos + 2]) =
+			*RTE_MBUF_DYNFIELD(pkts[pos + 2], offs, uint32_t *) =
 				cq[pos + p2].flow_table_metadata;
-			*RTE_FLOW_DYNF_METADATA(pkts[pos + 3]) =
+			*RTE_MBUF_DYNFIELD(pkts[pos + 3], offs, uint32_t *) =
 				cq[pos + p3].flow_table_metadata;
-			if (*RTE_FLOW_DYNF_METADATA(pkts[pos]))
-				pkts[pos]->ol_flags |= PKT_RX_DYNF_METADATA;
-			if (*RTE_FLOW_DYNF_METADATA(pkts[pos + 1]))
-				pkts[pos + 1]->ol_flags |= PKT_RX_DYNF_METADATA;
-			if (*RTE_FLOW_DYNF_METADATA(pkts[pos + 2]))
-				pkts[pos + 2]->ol_flags |= PKT_RX_DYNF_METADATA;
-			if (*RTE_FLOW_DYNF_METADATA(pkts[pos + 3]))
-				pkts[pos + 3]->ol_flags |= PKT_RX_DYNF_METADATA;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos], offs, uint32_t *))
+				pkts[pos]->ol_flags |= rxq->flow_meta_mask;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos + 1], offs, uint32_t *))
+				pkts[pos + 1]->ol_flags |= rxq->flow_meta_mask;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos + 2], offs, uint32_t *))
+				pkts[pos + 2]->ol_flags |= rxq->flow_meta_mask;
+			if (*RTE_MBUF_DYNFIELD(pkts[pos + 3], offs, uint32_t *))
+				pkts[pos + 3]->ol_flags |= rxq->flow_meta_mask;
 		}
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		/* Add up received bytes count. */
@@ -674,8 +698,10 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 			break;
 	}
 	/* If no new CQE seen, return without updating cq_db. */
-	if (unlikely(!nocmp_n && comp_idx == MLX5_VPMD_DESCS_PER_LOOP))
+	if (unlikely(!nocmp_n && comp_idx == MLX5_VPMD_DESCS_PER_LOOP)) {
+		*no_cq = true;
 		return rcvd_pkt;
+	}
 	/* Update the consumer indexes for non-compressed CQEs. */
 	assert(nocmp_n <= pkts_n);
 	rxq->cq_ci += nocmp_n;
@@ -703,6 +729,7 @@ rxq_burst_v(struct mlx5_rxq_data *rxq, struct rte_mbuf **pkts, uint16_t pkts_n,
 	}
 	rte_compiler_barrier();
 	*rxq->cq_db = rte_cpu_to_be_32(rxq->cq_ci);
+	*no_cq = !rcvd_pkt;
 	return rcvd_pkt;
 }
 
diff --git a/dpdk/drivers/net/mlx5/mlx5_stats.c b/dpdk/drivers/net/mlx5/mlx5_stats.c
index 205e4fec78..ccdcdcfff6 100644
--- a/dpdk/drivers/net/mlx5/mlx5_stats.c
+++ b/dpdk/drivers/net/mlx5/mlx5_stats.c
@@ -3,11 +3,13 @@
  * Copyright 2015 Mellanox Technologies, Ltd
  */
 
+#include <fcntl.h>
 #include <inttypes.h>
 #include <linux/sockios.h>
 #include <linux/ethtool.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #include <rte_ethdev_driver.h>
 #include <rte_common.h>
@@ -136,26 +138,40 @@ static const struct mlx5_counter_ctrl mlx5_counters_init[] = {
 
 static const unsigned int xstats_n = RTE_DIM(mlx5_counters_init);
 
-static inline void
+static inline int
 mlx5_read_ib_stat(struct mlx5_priv *priv, const char *ctr_name, uint64_t *stat)
 {
-	FILE *file;
+	int fd;
+
 	if (priv->sh) {
 		MKSTR(path, "%s/ports/%d/hw_counters/%s",
-			  priv->sh->ibdev_path,
-			  priv->ibv_port,
-			  ctr_name);
-
-		file = fopen(path, "rb");
-		if (file) {
-			int n = fscanf(file, "%" SCNu64, stat);
-
-			fclose(file);
-			if (n == 1)
-				return;
+		      priv->sh->ibdev_path,
+		      priv->ibv_port,
+		      ctr_name);
+		fd = open(path, O_RDONLY);
+		/*
+		 * in switchdev the file location is not per port
+		 * but rather in <ibdev_path>/hw_counters/<file_name>.
+		 */
+		if (fd == -1) {
+			MKSTR(path1, "%s/hw_counters/%s",
+			      priv->sh->ibdev_path,
+			      ctr_name);
+			fd = open(path1, O_RDONLY);
+		}
+		if (fd != -1) {
+			char buf[21] = {'\0'};
+			ssize_t n = read(fd, buf, sizeof(buf));
+
+			close(fd);
+			if (n != -1) {
+				*stat = strtoull(buf, NULL, 10);
+				return 0;
+			}
 		}
 	}
 	*stat = 0;
+	return 1;
 }
 
 /**
@@ -194,8 +210,14 @@ mlx5_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)
 	}
 	for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
 		if (xstats_ctrl->info[i].ib) {
-			mlx5_read_ib_stat(priv, xstats_ctrl->info[i].ctr_name,
-					  &stats[i]);
+			ret = mlx5_read_ib_stat(priv,
+						xstats_ctrl->info[i].ctr_name,
+						&stats[i]);
+			/* return last xstats counter if fail to read. */
+			if (ret == 0)
+				xstats_ctrl->xstats[i] = stats[i];
+			else
+				stats[i] = xstats_ctrl->xstats[i];
 		} else {
 			stats[i] = (uint64_t)
 				et_stats->data[xstats_ctrl->dev_table_idx[i]];
@@ -301,6 +323,7 @@ mlx5_stats_init(struct rte_eth_dev *dev)
 			unsigned int idx = xstats_ctrl->mlx5_stats_n++;
 
 			xstats_ctrl->info[idx] = mlx5_counters_init[i];
+			xstats_ctrl->hw_stats[idx] = 0;
 		}
 	}
 	assert(xstats_ctrl->mlx5_stats_n <= MLX5_MAX_XSTATS);
@@ -311,6 +334,7 @@ mlx5_stats_init(struct rte_eth_dev *dev)
 		DRV_LOG(ERR, "port %u cannot read device counters: %s",
 			dev->data->port_id, strerror(rte_errno));
 	mlx5_read_ib_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
+	stats_ctrl->imissed = 0;
 free:
 	rte_free(strings);
 }
@@ -353,7 +377,23 @@ mlx5_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *stats,
 			return ret;
 		for (i = 0; i != mlx5_stats_n; ++i) {
 			stats[i].id = i;
-			stats[i].value = (counters[i] - xstats_ctrl->base[i]);
+			if (xstats_ctrl->info[i].ib) {
+				uint64_t wrap_n;
+				uint64_t hw_stat = xstats_ctrl->hw_stats[i];
+
+				stats[i].value = (counters[i] -
+						  xstats_ctrl->base[i]) &
+						  (uint64_t)UINT32_MAX;
+				wrap_n = hw_stat >> 32;
+				if (stats[i].value <
+					    (hw_stat & (uint64_t)UINT32_MAX))
+					wrap_n++;
+				stats[i].value |= (wrap_n) << 32;
+				xstats_ctrl->hw_stats[i] = stats[i].value;
+			} else {
+				stats[i].value =
+					(counters[i] - xstats_ctrl->base[i]);
+			}
 		}
 	}
 	return mlx5_stats_n;
@@ -375,9 +415,12 @@ int
 mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_stats_ctrl *stats_ctrl = &priv->stats_ctrl;
 	struct rte_eth_stats tmp;
 	unsigned int i;
 	unsigned int idx;
+	uint64_t wrap_n;
+	int ret;
 
 	memset(&tmp, 0, sizeof(tmp));
 	/* Add software counters. */
@@ -420,8 +463,18 @@ mlx5_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 #endif
 		tmp.oerrors += txq->stats.oerrors;
 	}
-	mlx5_read_ib_stat(priv, "out_of_buffer", &tmp.imissed);
-	tmp.imissed -= priv->stats_ctrl.imissed_base;
+	ret = mlx5_read_ib_stat(priv, "out_of_buffer", &tmp.imissed);
+	if (ret == 0) {
+		tmp.imissed = (tmp.imissed - stats_ctrl->imissed_base) &
+				 (uint64_t)UINT32_MAX;
+		wrap_n = stats_ctrl->imissed >> 32;
+		if (tmp.imissed < (stats_ctrl->imissed & (uint64_t)UINT32_MAX))
+			wrap_n++;
+		tmp.imissed |= (wrap_n) << 32;
+		stats_ctrl->imissed = tmp.imissed;
+	} else {
+		tmp.imissed = stats_ctrl->imissed;
+	}
 #ifndef MLX5_PMD_SOFT_COUNTERS
 	/* FIXME: retrieve and add hardware counters. */
 #endif
@@ -458,6 +511,7 @@ mlx5_stats_reset(struct rte_eth_dev *dev)
 		       sizeof(struct mlx5_txq_stats));
 	}
 	mlx5_read_ib_stat(priv, "out_of_buffer", &stats_ctrl->imissed_base);
+	stats_ctrl->imissed = 0;
 #ifndef MLX5_PMD_SOFT_COUNTERS
 	/* FIXME: reset hardware counters. */
 #endif
@@ -482,8 +536,7 @@ mlx5_xstats_reset(struct rte_eth_dev *dev)
 	struct mlx5_xstats_ctrl *xstats_ctrl = &priv->xstats_ctrl;
 	int stats_n;
 	unsigned int i;
-	unsigned int n = xstats_ctrl->mlx5_stats_n;
-	uint64_t counters[n];
+	uint64_t *counters;
 	int ret;
 
 	stats_n = mlx5_ethtool_get_stats_n(dev);
@@ -494,15 +547,26 @@ mlx5_xstats_reset(struct rte_eth_dev *dev)
 	}
 	if (xstats_ctrl->stats_n != stats_n)
 		mlx5_stats_init(dev);
+	counters =  malloc(sizeof(*counters) * xstats_ctrl->mlx5_stats_n);
+	if (!counters) {
+		DRV_LOG(WARNING, "port %u unable to allocate memory for xstats "
+				"counters",
+		     dev->data->port_id);
+		rte_errno = ENOMEM;
+		return -rte_errno;
+	}
 	ret = mlx5_read_dev_counters(dev, counters);
 	if (ret) {
 		DRV_LOG(ERR, "port %u cannot read device counters: %s",
 			dev->data->port_id, strerror(rte_errno));
+		free(counters);
 		return ret;
 	}
-	for (i = 0; i != n; ++i)
+	for (i = 0; i != xstats_ctrl->mlx5_stats_n; ++i) {
 		xstats_ctrl->base[i] = counters[i];
-
+		xstats_ctrl->hw_stats[i] = 0;
+	}
+	free(counters);
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/mlx5/mlx5_trigger.c b/dpdk/drivers/net/mlx5/mlx5_trigger.c
index cafab25c67..04b06e11d7 100644
--- a/dpdk/drivers/net/mlx5/mlx5_trigger.c
+++ b/dpdk/drivers/net/mlx5/mlx5_trigger.c
@@ -106,9 +106,12 @@ mlx5_rxq_start(struct rte_eth_dev *dev)
 	unsigned int i;
 	int ret = 0;
 	enum mlx5_rxq_obj_type obj_type = MLX5_RXQ_OBJ_TYPE_IBV;
+	struct mlx5_rxq_data *rxq = NULL;
 
 	for (i = 0; i < priv->rxqs_n; ++i) {
-		if ((*priv->rxqs)[i]->lro) {
+		rxq = (*priv->rxqs)[i];
+
+		if (rxq && rxq->lro) {
 			obj_type =  MLX5_RXQ_OBJ_TYPE_DEVX_RQ;
 			break;
 		}
@@ -269,11 +272,13 @@ mlx5_dev_start(struct rte_eth_dev *dev)
 	int ret;
 
 	DRV_LOG(DEBUG, "port %u starting device", dev->data->port_id);
-	ret = mlx5_dev_configure_rss_reta(dev);
-	if (ret) {
-		DRV_LOG(ERR, "port %u reta config failed: %s",
-			dev->data->port_id, strerror(rte_errno));
-		return -rte_errno;
+	if (dev->data->nb_rx_queues > 0) {
+		ret = mlx5_dev_configure_rss_reta(dev);
+		if (ret) {
+			DRV_LOG(ERR, "port %u reta config failed: %s",
+				dev->data->port_id, strerror(rte_errno));
+			return -rte_errno;
+		}
 	}
 	ret = mlx5_txq_start(dev);
 	if (ret) {
@@ -309,6 +314,8 @@ mlx5_dev_start(struct rte_eth_dev *dev)
 			dev->data->port_id);
 		goto error;
 	}
+	/* Set a mask and offset of dynamic metadata flows into Rx queues*/
+	mlx5_flow_rxq_dynf_metadata_set(dev);
 	ret = mlx5_flow_start(dev, &priv->flows);
 	if (ret) {
 		DRV_LOG(DEBUG, "port %u failed to set flows",
@@ -320,7 +327,18 @@ mlx5_dev_start(struct rte_eth_dev *dev)
 	dev->rx_pkt_burst = mlx5_select_rx_function(dev);
 	/* Enable datapath on secondary process. */
 	mlx5_mp_req_start_rxtx(dev);
-	mlx5_dev_interrupt_handler_install(dev);
+	if (priv->sh->intr_handle.fd >= 0) {
+		priv->sh->port[priv->ibv_port - 1].ih_port_id =
+					(uint32_t)dev->data->port_id;
+	} else {
+		DRV_LOG(INFO, "port %u starts without LSC and RMV interrupts.",
+			dev->data->port_id);
+		dev->data->dev_conf.intr_conf.lsc = 0;
+		dev->data->dev_conf.intr_conf.rmv = 0;
+	}
+	if (priv->sh->intr_handle_devx.fd >= 0)
+		priv->sh->port[priv->ibv_port - 1].devx_ih_port_id =
+					(uint32_t)dev->data->port_id;
 	return 0;
 error:
 	ret = rte_errno; /* Save rte_errno before cleanup. */
@@ -359,7 +377,8 @@ mlx5_dev_stop(struct rte_eth_dev *dev)
 	mlx5_flow_stop(dev, &priv->flows);
 	mlx5_traffic_disable(dev);
 	mlx5_rx_intr_vec_disable(dev);
-	mlx5_dev_interrupt_handler_uninstall(dev);
+	priv->sh->port[priv->ibv_port - 1].ih_port_id = RTE_MAX_ETHPORTS;
+	priv->sh->port[priv->ibv_port - 1].devx_ih_port_id = RTE_MAX_ETHPORTS;
 	mlx5_txq_stop(dev);
 	mlx5_rxq_stop(dev);
 }
@@ -420,9 +439,14 @@ mlx5_traffic_enable(struct rte_eth_dev *dev)
 		}
 		mlx5_txq_release(dev, i);
 	}
-	if (priv->config.dv_esw_en && !priv->config.vf)
-		if (!mlx5_flow_create_esw_table_zero_flow(dev))
-			goto error;
+	if (priv->config.dv_esw_en && !priv->config.vf) {
+		if (mlx5_flow_create_esw_table_zero_flow(dev))
+			priv->fdb_def_rule = 1;
+		else
+			DRV_LOG(INFO, "port %u FDB default rule cannot be"
+				" configured - only Eswitch group 0 flows are"
+				" supported.", dev->data->port_id);
+	}
 	if (priv->isolated)
 		return 0;
 	if (dev->data->promiscuous) {
diff --git a/dpdk/drivers/net/mlx5/mlx5_txq.c b/dpdk/drivers/net/mlx5/mlx5_txq.c
index bac4f71c24..9c929a57ea 100644
--- a/dpdk/drivers/net/mlx5/mlx5_txq.c
+++ b/dpdk/drivers/net/mlx5/mlx5_txq.c
@@ -62,7 +62,7 @@ txq_alloc_elts(struct mlx5_txq_ctrl *txq_ctrl)
  * @param txq_ctrl
  *   Pointer to TX queue structure.
  */
-static void
+void
 txq_free_elts(struct mlx5_txq_ctrl *txq_ctrl)
 {
 	const uint16_t elts_n = 1 << txq_ctrl->txq.elts_n;
@@ -147,27 +147,27 @@ mlx5_get_tx_port_offloads(struct rte_eth_dev *dev)
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-mlx5_tx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc)
+mlx5_tx_queue_pre_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t *desc)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 
-	if (desc <= MLX5_TX_COMP_THRESH) {
+	if (*desc <= MLX5_TX_COMP_THRESH) {
 		DRV_LOG(WARNING,
 			"port %u number of descriptors requested for Tx queue"
 			" %u must be higher than MLX5_TX_COMP_THRESH, using %u"
-			" instead of %u",
-			dev->data->port_id, idx, MLX5_TX_COMP_THRESH + 1, desc);
-		desc = MLX5_TX_COMP_THRESH + 1;
+			" instead of %u", dev->data->port_id, idx,
+			MLX5_TX_COMP_THRESH + 1, *desc);
+		*desc = MLX5_TX_COMP_THRESH + 1;
 	}
-	if (!rte_is_power_of_2(desc)) {
-		desc = 1 << log2above(desc);
+	if (!rte_is_power_of_2(*desc)) {
+		*desc = 1 << log2above(*desc);
 		DRV_LOG(WARNING,
 			"port %u increased number of descriptors in Tx queue"
 			" %u to the next power of two (%d)",
-			dev->data->port_id, idx, desc);
+			dev->data->port_id, idx, *desc);
 	}
 	DRV_LOG(DEBUG, "port %u configuring queue %u for %u descriptors",
-		dev->data->port_id, idx, desc);
+		dev->data->port_id, idx, *desc);
 	if (idx >= priv->txqs_n) {
 		DRV_LOG(ERR, "port %u Tx queue index out of range (%u >= %u)",
 			dev->data->port_id, idx, priv->txqs_n);
@@ -210,7 +210,7 @@ mlx5_tx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		container_of(txq, struct mlx5_txq_ctrl, txq);
 	int res;
 
-	res = mlx5_tx_queue_pre_setup(dev, idx, desc);
+	res = mlx5_tx_queue_pre_setup(dev, idx, &desc);
 	if (res)
 		return res;
 	txq_ctrl = mlx5_txq_new(dev, idx, desc, socket, conf);
@@ -251,7 +251,7 @@ mlx5_tx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
 		container_of(txq, struct mlx5_txq_ctrl, txq);
 	int res;
 
-	res = mlx5_tx_queue_pre_setup(dev, idx, desc);
+	res = mlx5_tx_queue_pre_setup(dev, idx, &desc);
 	if (res)
 		return res;
 	if (hairpin_conf->peer_count != 1 ||
@@ -272,7 +272,6 @@ mlx5_tx_hairpin_queue_setup(struct rte_eth_dev *dev, uint16_t idx,
 	DRV_LOG(DEBUG, "port %u adding Tx queue %u to list",
 		dev->data->port_id, idx);
 	(*priv->txqs)[idx] = &txq_ctrl->txq;
-	txq_ctrl->type = MLX5_TXQ_TYPE_HAIRPIN;
 	return 0;
 }
 
@@ -296,9 +295,9 @@ mlx5_tx_queue_release(void *dpdk_txq)
 	priv = txq_ctrl->priv;
 	for (i = 0; (i != priv->txqs_n); ++i)
 		if ((*priv->txqs)[i] == txq) {
-			mlx5_txq_release(ETH_DEV(priv), i);
 			DRV_LOG(DEBUG, "port %u removing Tx queue %u from list",
 				PORT_ID(priv), txq->idx);
+			mlx5_txq_release(ETH_DEV(priv), i);
 			break;
 		}
 }
@@ -315,7 +314,7 @@ static void
 txq_uar_ncattr_init(struct mlx5_txq_ctrl *txq_ctrl, size_t page_size)
 {
 	struct mlx5_priv *priv = txq_ctrl->priv;
-	unsigned int cmd;
+	off_t cmd;
 
 	txq_ctrl->txq.db_heu = priv->config.dbnc == MLX5_TXDB_HEURISTIC;
 	txq_ctrl->txq.db_nc = 0;
@@ -353,7 +352,7 @@ txq_uar_init(struct mlx5_txq_ctrl *txq_ctrl)
 	/* Assign an UAR lock according to UAR page number */
 	lock_idx = (txq_ctrl->uar_mmap_offset / page_size) &
 		   MLX5_UAR_PAGE_NUM_MASK;
-	txq_ctrl->txq.uar_lock = &priv->uar_lock[lock_idx];
+	txq_ctrl->txq.uar_lock = &priv->sh->uar_lock[lock_idx];
 #endif
 }
 
@@ -425,6 +424,35 @@ txq_uar_uninit_secondary(struct mlx5_txq_ctrl *txq_ctrl)
 	munmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
 }
 
+/**
+ * Deinitialize Tx UAR registers for secondary process.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ */
+void
+mlx5_tx_uar_uninit_secondary(struct rte_eth_dev *dev)
+{
+	struct mlx5_proc_priv *ppriv = (struct mlx5_proc_priv *)
+					dev->process_private;
+	const size_t page_size = sysconf(_SC_PAGESIZE);
+	void *addr;
+	unsigned int i;
+
+	if (page_size == (size_t)-1) {
+		DRV_LOG(ERR, "Failed to get mem page size");
+		return;
+	}
+	assert(rte_eal_process_type() == RTE_PROC_SECONDARY);
+	for (i = 0; i != ppriv->uar_table_sz; ++i) {
+		if (!ppriv->uar_table[i])
+			continue;
+		addr = ppriv->uar_table[i];
+		munmap(RTE_PTR_ALIGN_FLOOR(addr, page_size), page_size);
+
+	}
+}
+
 /**
  * Initialize Tx UAR registers for secondary process.
  *
@@ -491,7 +519,7 @@ mlx5_txq_obj_hairpin_new(struct rte_eth_dev *dev, uint16_t idx)
 		container_of(txq_data, struct mlx5_txq_ctrl, txq);
 	struct mlx5_devx_create_sq_attr attr = { 0 };
 	struct mlx5_txq_obj *tmpl = NULL;
-	int ret = 0;
+	uint32_t max_wq_data;
 
 	assert(txq_data);
 	assert(!txq_ctrl->obj);
@@ -502,39 +530,36 @@ mlx5_txq_obj_hairpin_new(struct rte_eth_dev *dev, uint16_t idx)
 			"port %u Tx queue %u cannot allocate memory resources",
 			dev->data->port_id, txq_data->idx);
 		rte_errno = ENOMEM;
-		goto error;
+		return NULL;
 	}
 	tmpl->type = MLX5_TXQ_OBJ_TYPE_DEVX_HAIRPIN;
 	tmpl->txq_ctrl = txq_ctrl;
 	attr.hairpin = 1;
 	attr.tis_lst_sz = 1;
-	/* Workaround for hairpin startup */
-	attr.wq_attr.log_hairpin_num_packets = log2above(32);
-	/* Workaround for packets larger than 1KB */
+	max_wq_data = priv->config.hca_attr.log_max_hairpin_wq_data_sz;
+	/* Jumbo frames > 9KB should be supported, and more packets. */
 	attr.wq_attr.log_hairpin_data_sz =
-			priv->config.hca_attr.log_max_hairpin_wq_data_sz;
+			(max_wq_data < MLX5_HAIRPIN_JUMBO_LOG_SIZE) ?
+			max_wq_data : MLX5_HAIRPIN_JUMBO_LOG_SIZE;
+	/* Set the packets number to the maximum value for performance. */
+	attr.wq_attr.log_hairpin_num_packets =
+			attr.wq_attr.log_hairpin_data_sz -
+			MLX5_HAIRPIN_QUEUE_STRIDE;
 	attr.tis_num = priv->sh->tis->id;
 	tmpl->sq = mlx5_devx_cmd_create_sq(priv->sh->ctx, &attr);
 	if (!tmpl->sq) {
 		DRV_LOG(ERR,
 			"port %u tx hairpin queue %u can't create sq object",
 			dev->data->port_id, idx);
+		rte_free(tmpl);
 		rte_errno = errno;
-		goto error;
+		return NULL;
 	}
 	DRV_LOG(DEBUG, "port %u sxq %u updated with %p", dev->data->port_id,
 		idx, (void *)&tmpl);
 	rte_atomic32_inc(&tmpl->refcnt);
 	LIST_INSERT_HEAD(&priv->txqsobj, tmpl, next);
 	return tmpl;
-error:
-	ret = rte_errno; /* Save rte_errno before cleanup. */
-	if (tmpl->tis)
-		mlx5_devx_cmd_destroy(tmpl->tis);
-	if (tmpl->sq)
-		mlx5_devx_cmd_destroy(tmpl->sq);
-	rte_errno = ret; /* Restore rte_errno. */
-	return NULL;
 }
 
 /**
@@ -562,7 +587,6 @@ mlx5_txq_obj_new(struct rte_eth_dev *dev, uint16_t idx,
 	struct mlx5_txq_obj *txq_obj = NULL;
 	union {
 		struct ibv_qp_init_attr_ex init;
-		struct ibv_cq_init_attr_ex cq;
 		struct ibv_qp_attr mod;
 	} attr;
 	unsigned int cqe_n;
@@ -590,9 +614,6 @@ mlx5_txq_obj_new(struct rte_eth_dev *dev, uint16_t idx,
 		return NULL;
 	}
 	memset(&tmpl, 0, sizeof(struct mlx5_txq_obj));
-	attr.cq = (struct ibv_cq_init_attr_ex){
-		.comp_mask = 0,
-	};
 	cqe_n = desc / MLX5_TX_COMP_THRESH +
 		1 + MLX5_TX_COMP_THRESH_INLINE_DIV;
 	tmpl.cq = mlx5_glue->create_cq(priv->sh->ctx, cqe_n, NULL, NULL, 0);
@@ -718,13 +739,22 @@ mlx5_txq_obj_new(struct rte_eth_dev *dev, uint16_t idx,
 	txq_data->cq_db = cq_info.dbrec;
 	txq_data->cqes = (volatile struct mlx5_cqe *)cq_info.buf;
 	txq_data->cq_ci = 0;
-#ifndef NDEBUG
 	txq_data->cq_pi = 0;
-#endif
 	txq_data->wqe_ci = 0;
 	txq_data->wqe_pi = 0;
 	txq_data->wqe_comp = 0;
 	txq_data->wqe_thres = txq_data->wqe_s / MLX5_TX_COMP_THRESH_INLINE_DIV;
+	txq_data->fcqs = rte_calloc_socket(__func__,
+					   txq_data->cqe_s,
+					   sizeof(*txq_data->fcqs),
+					   RTE_CACHE_LINE_SIZE,
+					   txq_ctrl->socket);
+	if (!txq_data->fcqs) {
+		DRV_LOG(ERR, "port %u Tx queue %u cannot allocate memory (FCQ)",
+			dev->data->port_id, idx);
+		rte_errno = ENOMEM;
+		goto error;
+	}
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	/*
 	 * If using DevX need to query and store TIS transport domain value.
@@ -773,6 +803,8 @@ mlx5_txq_obj_new(struct rte_eth_dev *dev, uint16_t idx,
 		claim_zero(mlx5_glue->destroy_cq(tmpl.cq));
 	if (tmpl.qp)
 		claim_zero(mlx5_glue->destroy_qp(tmpl.qp));
+	if (txq_data->fcqs)
+		rte_free(txq_data->fcqs);
 	if (txq_obj)
 		rte_free(txq_obj);
 	priv->verbs_alloc_ctx.type = MLX5_VERBS_ALLOC_TYPE_NONE;
@@ -827,6 +859,8 @@ mlx5_txq_obj_release(struct mlx5_txq_obj *txq_obj)
 		} else {
 			claim_zero(mlx5_glue->destroy_qp(txq_obj->qp));
 			claim_zero(mlx5_glue->destroy_cq(txq_obj->cq));
+				if (txq_obj->txq_ctrl->txq.fcqs)
+					rte_free(txq_obj->txq_ctrl->txq.fcqs);
 		}
 		LIST_REMOVE(txq_obj, next);
 		rte_free(txq_obj);
@@ -964,7 +998,7 @@ txq_set_params(struct mlx5_txq_ctrl *txq_ctrl)
 	 * If there is requested minimal amount of data to inline
 	 * we MUST enable inlining. This is a case for ConnectX-4
 	 * which usually requires L2 inlined for correct operating
-	 * and ConnectX-4LX which requires L2-L4 inlined to
+	 * and ConnectX-4 Lx which requires L2-L4 inlined to
 	 * support E-Switch Flows.
 	 */
 	if (inlen_mode) {
@@ -1288,6 +1322,7 @@ mlx5_txq_new(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 	LIST_INSERT_HEAD(&priv->txqsctrl, tmpl, next);
 	return tmpl;
 error:
+	mlx5_mr_btree_free(&tmpl->txq.mr_ctrl.cache_bh);
 	rte_free(tmpl);
 	return NULL;
 }
diff --git a/dpdk/drivers/net/mlx5/mlx5_utils.c b/dpdk/drivers/net/mlx5/mlx5_utils.c
index 5d86615ea0..c1c238941d 100644
--- a/dpdk/drivers/net/mlx5/mlx5_utils.c
+++ b/dpdk/drivers/net/mlx5/mlx5_utils.c
@@ -20,7 +20,7 @@ mlx5_hlist_create(const char *name, uint32_t size)
 	if (!rte_is_power_of_2(size)) {
 		act_size = rte_align32pow2(size);
 		DRV_LOG(WARNING, "Size 0x%" PRIX32 " is not power of 2, will "
-			"be aligned to 0x%" PRIX32 ".\n", size, act_size);
+			"be aligned to 0x%" PRIX32 ".", size, act_size);
 	} else {
 		act_size = size;
 	}
@@ -29,7 +29,7 @@ mlx5_hlist_create(const char *name, uint32_t size)
 	/* Using zmalloc, then no need to initialize the heads. */
 	h = rte_zmalloc(name, alloc_size, RTE_CACHE_LINE_SIZE);
 	if (!h) {
-		DRV_LOG(ERR, "No memory for hash list %s creation\n",
+		DRV_LOG(ERR, "No memory for hash list %s creation",
 			name ? name : "None");
 		return NULL;
 	}
@@ -37,7 +37,7 @@ mlx5_hlist_create(const char *name, uint32_t size)
 		snprintf(h->name, MLX5_HLIST_NAMESIZE, "%s", name);
 	h->table_sz = act_size;
 	h->mask = act_size - 1;
-	DRV_LOG(DEBUG, "Hash list with %s size 0x%" PRIX32 " is created.\n",
+	DRV_LOG(DEBUG, "Hash list with %s size 0x%" PRIX32 " is created.",
 		h->name, act_size);
 	return h;
 }
diff --git a/dpdk/drivers/net/mlx5/mlx5_utils.h b/dpdk/drivers/net/mlx5/mlx5_utils.h
index b4ed8c6dad..b23eec622d 100644
--- a/dpdk/drivers/net/mlx5/mlx5_utils.h
+++ b/dpdk/drivers/net/mlx5/mlx5_utils.h
@@ -15,16 +15,6 @@
 
 #include "mlx5_defs.h"
 
-/*
- * Compilation workaround for PPC64 when AltiVec is fully enabled, e.g. std=c11.
- * Otherwise there would be a type conflict between stdbool and altivec.
- */
-#if defined(__PPC64__) && !defined(__APPLE_ALTIVEC__)
-#undef bool
-/* redefine as in stdbool.h */
-#define bool _Bool
-#endif
-
 /* Bit-field manipulation. */
 #define BITFIELD_DECLARE(bf, type, size) \
 	type bf[(((size_t)(size) / (sizeof(type) * CHAR_BIT)) + \
@@ -125,10 +115,6 @@ extern int mlx5_logtype;
 
 #endif /* NDEBUG */
 
-#define INFO(...) DRV_LOG(INFO, __VA_ARGS__)
-#define WARN(...) DRV_LOG(WARNING, __VA_ARGS__)
-#define ERROR(...) DRV_LOG(ERR, __VA_ARGS__)
-
 /* Convenience macros for accessing mbuf fields. */
 #define NEXT(m) ((m)->next)
 #define DATA_LEN(m) ((m)->data_len)
@@ -146,9 +132,10 @@ extern int mlx5_logtype;
 
 /* Allocate a buffer on the stack and fill it with a printf format string. */
 #define MKSTR(name, ...) \
-	char name[snprintf(NULL, 0, __VA_ARGS__) + 1]; \
+	int mkstr_size_##name = snprintf(NULL, 0, "" __VA_ARGS__); \
+	char name[mkstr_size_##name + 1]; \
 	\
-	snprintf(name, sizeof(name), __VA_ARGS__)
+	snprintf(name, sizeof(name), "" __VA_ARGS__)
 
 /**
  * Return logarithm of the nearest power of two above input value.
diff --git a/dpdk/drivers/net/mvneta/mvneta_ethdev.c b/dpdk/drivers/net/mvneta/mvneta_ethdev.c
index 865ad61aed..4aea876488 100644
--- a/dpdk/drivers/net/mvneta/mvneta_ethdev.c
+++ b/dpdk/drivers/net/mvneta/mvneta_ethdev.c
@@ -751,7 +751,7 @@ mvneta_stats_reset(struct rte_eth_dev *dev)
 
 	ret = mvneta_stats_get(dev, &priv->prev_stats);
 	if (unlikely(ret))
-		RTE_LOG(ERR, PMD, "Failed to reset port statistics");
+		MVNETA_LOG(ERR, "Failed to reset port statistics");
 
 	return ret;
 }
diff --git a/dpdk/drivers/net/mvneta/mvneta_rxtx.c b/dpdk/drivers/net/mvneta/mvneta_rxtx.c
index 10b6f57584..dfa7ecc090 100644
--- a/dpdk/drivers/net/mvneta/mvneta_rxtx.c
+++ b/dpdk/drivers/net/mvneta/mvneta_rxtx.c
@@ -872,7 +872,17 @@ mvneta_rx_queue_flush(struct mvneta_rxq *rxq)
 	int ret, i;
 
 	descs = rte_malloc("rxdesc", MRVL_NETA_RXD_MAX * sizeof(*descs), 0);
+	if (descs == NULL) {
+		MVNETA_LOG(ERR, "Failed to allocate descs.");
+		return;
+	}
+
 	bufs = rte_malloc("buffs", MRVL_NETA_RXD_MAX * sizeof(*bufs), 0);
+	if (bufs == NULL) {
+		MVNETA_LOG(ERR, "Failed to allocate bufs.");
+		rte_free(descs);
+		return;
+	}
 
 	do {
 		num = MRVL_NETA_RXD_MAX;
diff --git a/dpdk/drivers/net/mvpp2/mrvl_ethdev.c b/dpdk/drivers/net/mvpp2/mrvl_ethdev.c
index b98b1fd667..fe4cadda04 100644
--- a/dpdk/drivers/net/mvpp2/mrvl_ethdev.c
+++ b/dpdk/drivers/net/mvpp2/mrvl_ethdev.c
@@ -443,8 +443,8 @@ mrvl_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	 * when this feature has not been enabled/supported so far
 	 * (TODO check scattered_rx flag here once scattered RX is supported).
 	 */
-	if (mru + MRVL_PKT_OFFS > mbuf_data_size) {
-		mru = mbuf_data_size - MRVL_PKT_OFFS;
+	if (mru - RTE_ETHER_CRC_LEN + MRVL_PKT_OFFS > mbuf_data_size) {
+		mru = mbuf_data_size + RTE_ETHER_CRC_LEN - MRVL_PKT_OFFS;
 		mtu = MRVL_PP2_MRU_TO_MTU(mru);
 		MRVL_LOG(WARNING, "MTU too big, max MTU possible limitted "
 			"by current mbuf size: %u. Set MTU to %u, MRU to %u",
@@ -673,18 +673,6 @@ mrvl_dev_start(struct rte_eth_dev *dev)
 		priv->uc_mc_flushed = 1;
 	}
 
-	if (!priv->vlan_flushed) {
-		ret = pp2_ppio_flush_vlan(priv->ppio);
-		if (ret) {
-			MRVL_LOG(ERR, "Failed to flush vlan list");
-			/*
-			 * TODO
-			 * once pp2_ppio_flush_vlan() is supported jump to out
-			 * goto out;
-			 */
-		}
-		priv->vlan_flushed = 1;
-	}
 	ret = mrvl_mtu_set(dev, dev->data->mtu);
 	if (ret)
 		MRVL_LOG(ERR, "Failed to set MTU to %d", dev->data->mtu);
@@ -816,7 +804,7 @@ mrvl_flush_bpool(struct rte_eth_dev *dev)
 	unsigned int core_id = rte_lcore_id();
 
 	if (core_id == LCORE_ID_ANY)
-		core_id = 0;
+		core_id = rte_get_master_lcore();
 
 	hif = mrvl_get_hif(priv, core_id);
 
@@ -1611,8 +1599,8 @@ mrvl_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
 static int
 mrvl_fill_bpool(struct mrvl_rxq *rxq, int num)
 {
-	struct buff_release_entry entries[MRVL_PP2_RXD_MAX];
-	struct rte_mbuf *mbufs[MRVL_PP2_RXD_MAX];
+	struct buff_release_entry entries[num];
+	struct rte_mbuf *mbufs[num];
 	int i, ret;
 	unsigned int core_id;
 	struct pp2_hif *hif;
@@ -1620,7 +1608,7 @@ mrvl_fill_bpool(struct mrvl_rxq *rxq, int num)
 
 	core_id = rte_lcore_id();
 	if (core_id == LCORE_ID_ANY)
-		core_id = 0;
+		core_id = rte_get_master_lcore();
 
 	hif = mrvl_get_hif(rxq->priv, core_id);
 	if (!hif)
@@ -1708,7 +1696,8 @@ mrvl_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t desc,
 		return -EFAULT;
 	}
 
-	frame_size = buf_size - RTE_PKTMBUF_HEADROOM - MRVL_PKT_EFFEC_OFFS;
+	frame_size = buf_size - RTE_PKTMBUF_HEADROOM -
+		     MRVL_PKT_EFFEC_OFFS + RTE_ETHER_CRC_LEN;
 	if (frame_size < max_rx_pkt_len) {
 		MRVL_LOG(WARNING,
 			"Mbuf size must be increased to %u bytes to hold up "
@@ -1770,7 +1759,7 @@ mrvl_rx_queue_release(void *rxq)
 	unsigned int core_id = rte_lcore_id();
 
 	if (core_id == LCORE_ID_ANY)
-		core_id = 0;
+		core_id = rte_get_master_lcore();
 
 	if (!q)
 		return;
@@ -2168,7 +2157,6 @@ mrvl_desc_to_packet_type_and_offset(struct pp2_ppio_desc *desc,
 		*l4_offset = *l3_offset + MRVL_ARP_LENGTH;
 		break;
 	default:
-		MRVL_LOG(DEBUG, "Failed to recognise l3 packet type");
 		break;
 	}
 
@@ -2180,7 +2168,6 @@ mrvl_desc_to_packet_type_and_offset(struct pp2_ppio_desc *desc,
 		packet_type |= RTE_PTYPE_L4_UDP;
 		break;
 	default:
-		MRVL_LOG(DEBUG, "Failed to recognise l4 packet type");
 		break;
 	}
 
@@ -2250,10 +2237,9 @@ mrvl_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 	ret = pp2_ppio_recv(q->priv->ppio, q->priv->rxq_map[q->queue_id].tc,
 			    q->priv->rxq_map[q->queue_id].inq, descs, &nb_pkts);
-	if (unlikely(ret < 0)) {
-		MRVL_LOG(ERR, "Failed to receive packets");
+	if (unlikely(ret < 0))
 		return 0;
-	}
+
 	mrvl_port_bpool_size[bpool->pp2_id][bpool->id][core_id] -= nb_pkts;
 
 	for (i = 0; i < nb_pkts; i++) {
@@ -2316,21 +2302,13 @@ mrvl_rx_pkt_burst(void *rxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 		if (unlikely(num <= q->priv->bpool_min_size ||
 			     (!rx_done && num < q->priv->bpool_init_size))) {
-			ret = mrvl_fill_bpool(q, MRVL_BURST_SIZE);
-			if (ret)
-				MRVL_LOG(ERR, "Failed to fill bpool");
+			mrvl_fill_bpool(q, MRVL_BURST_SIZE);
 		} else if (unlikely(num > q->priv->bpool_max_size)) {
 			int i;
 			int pkt_to_remove = num - q->priv->bpool_init_size;
 			struct rte_mbuf *mbuf;
 			struct pp2_buff_inf buff;
 
-			MRVL_LOG(DEBUG,
-				"port-%d:%d: bpool %d oversize - remove %d buffers (pool size: %d -> %d)",
-				bpool->pp2_id, q->priv->ppio->port_id,
-				bpool->id, pkt_to_remove, num,
-				q->priv->bpool_init_size);
-
 			for (i = 0; i < pkt_to_remove; i++) {
 				ret = pp2_bpool_get_buff(hif, bpool, &buff);
 				if (ret)
@@ -2523,12 +2501,8 @@ mrvl_tx_pkt_burst(void *txq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 				       sq, q->queue_id, 0);
 
 	sq_free_size = MRVL_PP2_TX_SHADOWQ_SIZE - sq->size - 1;
-	if (unlikely(nb_pkts > sq_free_size)) {
-		MRVL_LOG(DEBUG,
-			"No room in shadow queue for %d packets! %d packets will be sent.",
-			nb_pkts, sq_free_size);
+	if (unlikely(nb_pkts > sq_free_size))
 		nb_pkts = sq_free_size;
-	}
 
 	for (i = 0; i < nb_pkts; i++) {
 		struct rte_mbuf *mbuf = tx_pkts[i];
@@ -2645,10 +2619,6 @@ mrvl_tx_sg_pkt_burst(void *txq, struct rte_mbuf **tx_pkts,
 		 */
 		if (unlikely(total_descs > sq_free_size)) {
 			total_descs -= nb_segs;
-			RTE_LOG(DEBUG, PMD,
-				"No room in shadow queue for %d packets! "
-				"%d packets will be sent.\n",
-				nb_pkts, i);
 			break;
 		}
 
diff --git a/dpdk/drivers/net/mvpp2/mrvl_ethdev.h b/dpdk/drivers/net/mvpp2/mrvl_ethdev.h
index db6632f5b6..eee5182ce8 100644
--- a/dpdk/drivers/net/mvpp2/mrvl_ethdev.h
+++ b/dpdk/drivers/net/mvpp2/mrvl_ethdev.h
@@ -186,7 +186,6 @@ struct mrvl_priv {
 	uint8_t bpool_bit;
 	uint8_t rss_hf_tcp;
 	uint8_t uc_mc_flushed;
-	uint8_t vlan_flushed;
 	uint8_t isolated;
 	uint8_t multiseg;
 
diff --git a/dpdk/drivers/net/mvpp2/mrvl_flow.c b/dpdk/drivers/net/mvpp2/mrvl_flow.c
index 381b54e291..ea43255284 100644
--- a/dpdk/drivers/net/mvpp2/mrvl_flow.c
+++ b/dpdk/drivers/net/mvpp2/mrvl_flow.c
@@ -2511,14 +2511,14 @@ mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
 
 	if (first_flow->pattern & F_UDP_SPORT) {
 		key->proto_field[key->num_fields].proto = MV_NET_PROTO_UDP;
-		key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_SP;
+		key->proto_field[key->num_fields].field.udp = MV_NET_UDP_F_SP;
 		key->key_size += 2;
 		key->num_fields += 1;
 	}
 
 	if (first_flow->pattern & F_UDP_DPORT) {
 		key->proto_field[key->num_fields].proto = MV_NET_PROTO_UDP;
-		key->proto_field[key->num_fields].field.udp = MV_NET_TCP_F_DP;
+		key->proto_field[key->num_fields].field.udp = MV_NET_UDP_F_DP;
 		key->key_size += 2;
 		key->num_fields += 1;
 	}
diff --git a/dpdk/drivers/net/mvpp2/mrvl_mtr.c b/dpdk/drivers/net/mvpp2/mrvl_mtr.c
index 39272acea4..2fa5cb43ad 100644
--- a/dpdk/drivers/net/mvpp2/mrvl_mtr.c
+++ b/dpdk/drivers/net/mvpp2/mrvl_mtr.c
@@ -329,6 +329,12 @@ mrvl_create(struct rte_eth_dev *dev, uint32_t mtr_id,
 	struct mrvl_mtr_profile *profile;
 	struct mrvl_mtr *mtr;
 
+	profile = mrvl_mtr_profile_from_id(priv, params->meter_profile_id);
+	if (!profile)
+		return -rte_mtr_error_set(error, EINVAL,
+					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
+					  NULL, "Profile id does not exist\n");
+
 	mtr = mrvl_mtr_from_id(priv, mtr_id);
 	if (mtr)
 		return -rte_mtr_error_set(error, EEXIST,
@@ -341,12 +347,6 @@ mrvl_create(struct rte_eth_dev *dev, uint32_t mtr_id,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED,
 					  NULL, NULL);
 
-	profile = mrvl_mtr_profile_from_id(priv, params->meter_profile_id);
-	if (!profile)
-		return -rte_mtr_error_set(error, EINVAL,
-					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-					  NULL, "Profile id does not exist\n");
-
 	mtr->shared = shared;
 	mtr->mtr_id = mtr_id;
 	mtr->plcr_bit = MRVL_PLCR_BIT_INVALID;
diff --git a/dpdk/drivers/net/netvsc/hn_ethdev.c b/dpdk/drivers/net/netvsc/hn_ethdev.c
index 164e9ad174..988f3cf1cb 100644
--- a/dpdk/drivers/net/netvsc/hn_ethdev.c
+++ b/dpdk/drivers/net/netvsc/hn_ethdev.c
@@ -42,7 +42,8 @@
 			    DEV_TX_OFFLOAD_VLAN_INSERT)
 
 #define HN_RX_OFFLOAD_CAPS (DEV_RX_OFFLOAD_CHECKSUM | \
-			    DEV_RX_OFFLOAD_VLAN_STRIP)
+			    DEV_RX_OFFLOAD_VLAN_STRIP | \
+			    DEV_RX_OFFLOAD_RSS_HASH)
 
 int hn_logtype_init;
 int hn_logtype_driver;
@@ -71,7 +72,7 @@ static const struct hn_xstats_name_off hn_stat_strings[] = {
 
 /* The default RSS key.
  * This value is the same as MLX5 so that flows will be
- * received on same path for both VF ans synthetic NIC.
+ * received on same path for both VF and synthetic NIC.
  */
 static const uint8_t rss_default_key[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
 	0x2c, 0xc6, 0x81, 0xd1,	0x5b, 0xdb, 0xf4, 0xf7,
@@ -133,8 +134,6 @@ eth_dev_vmbus_allocate(struct rte_vmbus_device *dev, size_t private_data_size)
 static void
 eth_dev_vmbus_release(struct rte_eth_dev *eth_dev)
 {
-	/* mac_addrs must not be freed alone because part of dev_private */
-	eth_dev->data->mac_addrs = NULL;
 	/* free ether device */
 	rte_eth_dev_release_port(eth_dev);
 
@@ -202,7 +201,7 @@ static int hn_parse_args(const struct rte_eth_dev *dev)
  */
 int
 hn_dev_link_update(struct rte_eth_dev *dev,
-		   int wait_to_complete)
+		   int wait_to_complete __rte_unused)
 {
 	struct hn_data *hv = dev->data->dev_private;
 	struct rte_eth_link link, old;
@@ -216,8 +215,6 @@ hn_dev_link_update(struct rte_eth_dev *dev,
 
 	hn_rndis_get_linkspeed(hv);
 
-	hn_vf_link_update(dev, wait_to_complete);
-
 	link = (struct rte_eth_link) {
 		.link_duplex = ETH_LINK_FULL_DUPLEX,
 		.link_autoneg = ETH_LINK_SPEED_FIXED,
@@ -256,15 +253,19 @@ static int hn_dev_info_get(struct rte_eth_dev *dev,
 	dev_info->max_rx_queues = hv->max_queues;
 	dev_info->max_tx_queues = hv->max_queues;
 
-	rc = hn_rndis_get_offload(hv, dev_info);
-	if (rc != 0)
-		return rc;
+	dev_info->tx_desc_lim.nb_min = 1;
+	dev_info->tx_desc_lim.nb_max = 4096;
 
-	rc = hn_vf_info_get(hv, dev_info);
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	/* fills in rx and tx offload capability */
+	rc = hn_rndis_get_offload(hv, dev_info);
 	if (rc != 0)
 		return rc;
 
-	return 0;
+	/* merges the offload and queues of vf */
+	return hn_vf_info_get(hv, dev_info);
 }
 
 static int hn_rss_reta_update(struct rte_eth_dev *dev,
@@ -291,6 +292,13 @@ static int hn_rss_reta_update(struct rte_eth_dev *dev,
 			hv->rss_ind[i] = reta_conf[idx].reta[shift];
 	}
 
+	err = hn_rndis_conf_rss(hv, NDIS_RSS_FLAG_DISABLE);
+	if (err) {
+		PMD_DRV_LOG(NOTICE,
+			"rss disable failed");
+		return err;
+	}
+
 	err = hn_rndis_conf_rss(hv, 0);
 	if (err) {
 		PMD_DRV_LOG(NOTICE,
@@ -366,14 +374,15 @@ static int hn_rss_hash_update(struct rte_eth_dev *dev,
 
 	hn_rss_hash_init(hv, rss_conf);
 
-	err = hn_rndis_conf_rss(hv, 0);
-	if (err) {
-		PMD_DRV_LOG(NOTICE,
-			    "rss reconfig failed (RSS disabled)");
-		return err;
+	if (rss_conf->rss_hf != 0) {
+		err = hn_rndis_conf_rss(hv, 0);
+		if (err) {
+			PMD_DRV_LOG(NOTICE,
+				    "rss reconfig failed (RSS disabled)");
+			return err;
+		}
 	}
 
-
 	return hn_vf_rss_hash_update(dev, rss_conf);
 }
 
@@ -565,7 +574,7 @@ static int hn_dev_configure(struct rte_eth_dev *dev)
 				 dev->data->nb_tx_queues);
 
 	for (i = 0; i < NDIS_HASH_INDCNT; i++)
-		hv->rss_ind[i] = i % hv->num_queues;
+		hv->rss_ind[i] = i % dev->data->nb_rx_queues;
 
 	hn_rss_hash_init(hv, rss_conf);
 
@@ -578,12 +587,21 @@ static int hn_dev_configure(struct rte_eth_dev *dev)
 			return err;
 		}
 
-		err = hn_rndis_conf_rss(hv, 0);
+		err = hn_rndis_conf_rss(hv, NDIS_RSS_FLAG_DISABLE);
 		if (err) {
 			PMD_DRV_LOG(NOTICE,
-				    "initial RSS config failed");
+				"rss disable failed");
 			return err;
 		}
+
+		if (rss_conf->rss_hf != 0) {
+			err = hn_rndis_conf_rss(hv, 0);
+			if (err) {
+				PMD_DRV_LOG(NOTICE,
+					    "initial RSS config failed");
+				return err;
+			}
+		}
 	}
 
 	return hn_vf_configure(dev, dev_conf);
@@ -807,6 +825,10 @@ hn_dev_start(struct rte_eth_dev *dev)
 	if (error)
 		hn_rndis_set_rxfilter(hv, 0);
 
+	/* Initialize Link state */
+	if (error == 0)
+		hn_dev_link_update(dev, 0);
+
 	return error;
 }
 
@@ -921,8 +943,14 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return 0;
 
-	/* Since Hyper-V only supports one MAC address, just use local data */
-	eth_dev->data->mac_addrs = &hv->mac_addr;
+	/* Since Hyper-V only supports one MAC address */
+	eth_dev->data->mac_addrs = rte_calloc("hv_mac", HN_MAX_MAC_ADDRS,
+					      sizeof(struct rte_ether_addr), 0);
+	if (eth_dev->data->mac_addrs == NULL) {
+		PMD_INIT_LOG(ERR,
+			     "Failed to allocate memory store MAC addresses");
+		return -ENOMEM;
+	}
 
 	hv->vmbus = vmbus;
 	hv->rxbuf_res = &vmbus->resource[HV_RECV_BUF_MAP];
@@ -930,7 +958,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev)
 	hv->port_id = eth_dev->data->port_id;
 	hv->latency = HN_CHAN_LATENCY_NS;
 	hv->max_queues = 1;
-	rte_spinlock_init(&hv->vf_lock);
+	rte_rwlock_init(&hv->vf_lock);
 	hv->vf_port = HN_INVALID_PORT;
 
 	err = hn_parse_args(eth_dev);
@@ -962,11 +990,11 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev)
 	if  (err)
 		goto failed;
 
-	err = hn_tx_pool_init(eth_dev);
+	err = hn_chim_init(eth_dev);
 	if (err)
 		goto failed;
 
-	err = hn_rndis_get_eaddr(hv, hv->mac_addr.addr_bytes);
+	err = hn_rndis_get_eaddr(hv, eth_dev->data->mac_addrs->addr_bytes);
 	if (err)
 		goto failed;
 
@@ -998,7 +1026,7 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev)
 failed:
 	PMD_INIT_LOG(NOTICE, "device init failed");
 
-	hn_tx_pool_uninit(eth_dev);
+	hn_chim_uninit(eth_dev);
 	hn_detach(hv);
 	return err;
 }
@@ -1022,7 +1050,7 @@ eth_hn_dev_uninit(struct rte_eth_dev *eth_dev)
 	eth_dev->rx_pkt_burst = NULL;
 
 	hn_detach(hv);
-	hn_tx_pool_uninit(eth_dev);
+	hn_chim_uninit(eth_dev);
 	rte_vmbus_chan_close(hv->primary->chan);
 	rte_free(hv->primary);
 	ret = rte_eth_dev_owner_delete(hv->owner.id);
diff --git a/dpdk/drivers/net/netvsc/hn_nvs.c b/dpdk/drivers/net/netvsc/hn_nvs.c
index 6b518685ab..03b6cc1551 100644
--- a/dpdk/drivers/net/netvsc/hn_nvs.c
+++ b/dpdk/drivers/net/netvsc/hn_nvs.c
@@ -54,7 +54,7 @@ static int hn_nvs_req_send(struct hn_data *hv,
 }
 
 static int
-hn_nvs_execute(struct hn_data *hv,
+__hn_nvs_execute(struct hn_data *hv,
 	       void *req, uint32_t reqlen,
 	       void *resp, uint32_t resplen,
 	       uint32_t type)
@@ -62,6 +62,7 @@ hn_nvs_execute(struct hn_data *hv,
 	struct vmbus_channel *chan = hn_primary_chan(hv);
 	char buffer[NVS_RESPSIZE_MAX];
 	const struct hn_nvs_hdr *hdr;
+	uint64_t xactid;
 	uint32_t len;
 	int ret;
 
@@ -77,7 +78,7 @@ hn_nvs_execute(struct hn_data *hv,
 
  retry:
 	len = sizeof(buffer);
-	ret = rte_vmbus_chan_recv(chan, buffer, &len, NULL);
+	ret = rte_vmbus_chan_recv(chan, buffer, &len, &xactid);
 	if (ret == -EAGAIN) {
 		rte_delay_us(HN_CHAN_INTERVAL_US);
 		goto retry;
@@ -88,7 +89,24 @@ hn_nvs_execute(struct hn_data *hv,
 		return ret;
 	}
 
+	if (len < sizeof(*hdr)) {
+		PMD_DRV_LOG(ERR, "response missing NVS header");
+		return -EINVAL;
+	}
+
 	hdr = (struct hn_nvs_hdr *)buffer;
+
+	/* Silently drop received packets while waiting for response */
+	switch (hdr->type) {
+	case NVS_TYPE_RNDIS:
+		hn_nvs_ack_rxbuf(chan, xactid);
+		/* fallthrough */
+
+	case NVS_TYPE_TXTBL_NOTE:
+		PMD_DRV_LOG(DEBUG, "discard packet type 0x%x", hdr->type);
+		goto retry;
+	}
+
 	if (hdr->type != type) {
 		PMD_DRV_LOG(ERR, "unexpected NVS resp %#x, expect %#x",
 			    hdr->type, type);
@@ -108,6 +126,29 @@ hn_nvs_execute(struct hn_data *hv,
 	return 0;
 }
 
+
+/*
+ * Execute one control command and get the response.
+ * Only one command can be active on a channel at once
+ * Unlike BSD, DPDK does not have an interrupt context
+ * so the polling is required to wait for response.
+ */
+static int
+hn_nvs_execute(struct hn_data *hv,
+	       void *req, uint32_t reqlen,
+	       void *resp, uint32_t resplen,
+	       uint32_t type)
+{
+	struct hn_rx_queue *rxq = hv->primary;
+	int ret;
+
+	rte_spinlock_lock(&rxq->ring_lock);
+	ret = __hn_nvs_execute(hv, req, reqlen, resp, resplen, type);
+	rte_spinlock_unlock(&rxq->ring_lock);
+
+	return ret;
+}
+
 static int
 hn_nvs_doinit(struct hn_data *hv, uint32_t nvs_ver)
 {
@@ -187,9 +228,15 @@ hn_nvs_conn_rxbuf(struct hn_data *hv)
 		    resp.nvs_sect[0].slotcnt);
 	hv->rxbuf_section_cnt = resp.nvs_sect[0].slotcnt;
 
-	hv->rxbuf_info = rte_calloc("HN_RXBUF_INFO", hv->rxbuf_section_cnt,
-				    sizeof(*hv->rxbuf_info), RTE_CACHE_LINE_SIZE);
-	if (!hv->rxbuf_info) {
+	/*
+	 * Pimary queue's rxbuf_info is not allocated at creation time.
+	 * Now we can allocate it after we figure out the slotcnt.
+	 */
+	hv->primary->rxbuf_info = rte_calloc("HN_RXBUF_INFO",
+			hv->rxbuf_section_cnt,
+			sizeof(*hv->primary->rxbuf_info),
+			RTE_CACHE_LINE_SIZE);
+	if (!hv->primary->rxbuf_info) {
 		PMD_DRV_LOG(ERR,
 			    "could not allocate rxbuf info");
 		return -ENOMEM;
@@ -219,7 +266,6 @@ hn_nvs_disconn_rxbuf(struct hn_data *hv)
 			    error);
 	}
 
-	rte_free(hv->rxbuf_info);
 	/*
 	 * Linger long enough for NVS to disconnect RXBUF.
 	 */
diff --git a/dpdk/drivers/net/netvsc/hn_nvs.h b/dpdk/drivers/net/netvsc/hn_nvs.h
index 2563fd8d86..015839e364 100644
--- a/dpdk/drivers/net/netvsc/hn_nvs.h
+++ b/dpdk/drivers/net/netvsc/hn_nvs.h
@@ -37,7 +37,7 @@
 #define NVS_RNDIS_MTYPE_CTRL		1
 
 /*
- * NVS message transacion status codes.
+ * NVS message transaction status codes.
  */
 #define NVS_STATUS_OK		1
 #define NVS_STATUS_FAILED		2
diff --git a/dpdk/drivers/net/netvsc/hn_rndis.c b/dpdk/drivers/net/netvsc/hn_rndis.c
index 2b4714042e..6a976ce5e8 100644
--- a/dpdk/drivers/net/netvsc/hn_rndis.c
+++ b/dpdk/drivers/net/netvsc/hn_rndis.c
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
+#include <time.h>
 
 #include <rte_ethdev_driver.h>
 #include <rte_ethdev.h>
@@ -33,6 +34,9 @@
 #include "hn_rndis.h"
 #include "ndis.h"
 
+#define RNDIS_TIMEOUT_SEC 5
+#define RNDIS_DELAY_MS    10
+
 #define HN_RNDIS_XFER_SIZE		0x4000
 
 #define HN_NDIS_TXCSUM_CAP_IP4		\
@@ -272,7 +276,7 @@ static int hn_nvs_send_rndis_ctrl(struct vmbus_channel *chan,
 	sg.len  = reqlen;
 
 	if (sg.ofs + reqlen >  PAGE_SIZE) {
-		PMD_DRV_LOG(ERR, "RNDIS request crosses page bounary");
+		PMD_DRV_LOG(ERR, "RNDIS request crosses page boundary");
 		return -EINVAL;
 	}
 
@@ -348,7 +352,7 @@ void hn_rndis_receive_response(struct hn_data *hv,
 	rte_smp_wmb();
 
 	if (rte_atomic32_cmpset(&hv->rndis_pending, hdr->rid, 0) == 0) {
-		PMD_DRV_LOG(ERR,
+		PMD_DRV_LOG(NOTICE,
 			    "received id %#x pending id %#x",
 			    hdr->rid, (uint32_t)hv->rndis_pending);
 	}
@@ -371,6 +375,11 @@ static int hn_rndis_exec1(struct hn_data *hv,
 		return -EIO;
 	}
 
+	if (rid == 0) {
+		PMD_DRV_LOG(ERR, "Invalid request id");
+		return -EINVAL;
+	}
+
 	if (comp != NULL &&
 	    rte_atomic32_cmpset(&hv->rndis_pending, 0, rid) == 0) {
 		PMD_DRV_LOG(ERR,
@@ -385,9 +394,26 @@ static int hn_rndis_exec1(struct hn_data *hv,
 	}
 
 	if (comp) {
+		time_t start = time(NULL);
+
 		/* Poll primary channel until response received */
-		while (hv->rndis_pending == rid)
+		while (hv->rndis_pending == rid) {
+			if (hv->closed)
+				return -ENETDOWN;
+
+			if (time(NULL) - start > RNDIS_TIMEOUT_SEC) {
+				PMD_DRV_LOG(ERR,
+					    "RNDIS response timed out");
+
+				rte_atomic32_cmpset(&hv->rndis_pending, rid, 0);
+				return -ETIMEDOUT;
+			}
+
+			if (rte_vmbus_chan_rx_empty(hv->primary->chan))
+				rte_delay_ms(RNDIS_DELAY_MS);
+
 			hn_process_events(hv, 0, 1);
+		}
 
 		memcpy(comp, hv->rndis_resp, comp_len);
 	}
diff --git a/dpdk/drivers/net/netvsc/hn_rxtx.c b/dpdk/drivers/net/netvsc/hn_rxtx.c
index 7212780c15..af702dafe6 100644
--- a/dpdk/drivers/net/netvsc/hn_rxtx.c
+++ b/dpdk/drivers/net/netvsc/hn_rxtx.c
@@ -18,6 +18,7 @@
 #include <rte_memzone.h>
 #include <rte_malloc.h>
 #include <rte_atomic.h>
+#include <rte_bitmap.h>
 #include <rte_branch_prediction.h>
 #include <rte_ether.h>
 #include <rte_common.h>
@@ -41,7 +42,7 @@
 #define HN_TXD_CACHE_SIZE	32 /* per cpu tx_descriptor pool cache */
 #define HN_TXCOPY_THRESHOLD	512
 
-#define HN_RXCOPY_THRESHOLD	256
+#define HN_RXCOPY_THRESHOLD	UINT_MAX
 #define HN_RXQ_EVENT_DEFAULT	2048
 
 struct hn_rxinfo {
@@ -83,7 +84,7 @@ struct hn_txdesc {
 	struct rte_mbuf *m;
 
 	uint16_t	queue_id;
-	uint16_t	chim_index;
+	uint32_t	chim_index;
 	uint32_t	chim_size;
 	uint32_t	data_size;
 	uint32_t	packets;
@@ -98,11 +99,13 @@ struct hn_txdesc {
 	 RNDIS_PKTINFO_SIZE(NDIS_LSO2_INFO_SIZE) +	\
 	 RNDIS_PKTINFO_SIZE(NDIS_TXCSUM_INFO_SIZE))
 
+#define HN_RNDIS_PKT_ALIGNED	RTE_ALIGN(HN_RNDIS_PKT_LEN, RTE_CACHE_LINE_SIZE)
+
 /* Minimum space required for a packet */
 #define HN_PKTSIZE_MIN(align) \
 	RTE_ALIGN(RTE_ETHER_MIN_LEN + HN_RNDIS_PKT_LEN, align)
 
-#define DEFAULT_TX_FREE_THRESH 32U
+#define DEFAULT_TX_FREE_THRESH 32
 
 static void
 hn_update_packet_stats(struct hn_stats *stats, const struct rte_mbuf *m)
@@ -150,63 +153,79 @@ hn_rndis_pktmsg_offset(uint32_t ofs)
 static void hn_txd_init(struct rte_mempool *mp __rte_unused,
 			void *opaque, void *obj, unsigned int idx)
 {
+	struct hn_tx_queue *txq = opaque;
 	struct hn_txdesc *txd = obj;
-	struct rte_eth_dev *dev = opaque;
-	struct rndis_packet_msg *pkt;
 
 	memset(txd, 0, sizeof(*txd));
-	txd->chim_index = idx;
 
-	pkt = rte_malloc_socket("RNDIS_TX", HN_RNDIS_PKT_LEN,
-				rte_align32pow2(HN_RNDIS_PKT_LEN),
-				dev->device->numa_node);
-	if (!pkt)
-		rte_exit(EXIT_FAILURE, "can not allocate RNDIS header");
-
-	txd->rndis_pkt = pkt;
+	txd->queue_id = txq->queue_id;
+	txd->chim_index = NVS_CHIM_IDX_INVALID;
+	txd->rndis_pkt = (struct rndis_packet_msg *)((char *)txq->tx_rndis
+		+ idx * HN_RNDIS_PKT_ALIGNED);
 }
 
-/*
- * Unlike Linux and FreeBSD, this driver uses a mempool
- * to limit outstanding transmits and reserve buffers
- */
 int
-hn_tx_pool_init(struct rte_eth_dev *dev)
+hn_chim_init(struct rte_eth_dev *dev)
 {
 	struct hn_data *hv = dev->data->dev_private;
-	char name[RTE_MEMPOOL_NAMESIZE];
-	struct rte_mempool *mp;
+	uint32_t i, chim_bmp_size;
+
+	rte_spinlock_init(&hv->chim_lock);
+	chim_bmp_size = rte_bitmap_get_memory_footprint(hv->chim_cnt);
+	hv->chim_bmem = rte_zmalloc("hn_chim_bitmap", chim_bmp_size,
+				    RTE_CACHE_LINE_SIZE);
+	if (hv->chim_bmem == NULL) {
+		PMD_INIT_LOG(ERR, "failed to allocate bitmap size %u",
+			     chim_bmp_size);
+		return -1;
+	}
 
-	snprintf(name, sizeof(name),
-		 "hn_txd_%u", dev->data->port_id);
-
-	PMD_INIT_LOG(DEBUG, "create a TX send pool %s n=%u size=%zu socket=%d",
-		     name, hv->chim_cnt, sizeof(struct hn_txdesc),
-		     dev->device->numa_node);
-
-	mp = rte_mempool_create(name, hv->chim_cnt, sizeof(struct hn_txdesc),
-				HN_TXD_CACHE_SIZE, 0,
-				NULL, NULL,
-				hn_txd_init, dev,
-				dev->device->numa_node, 0);
-	if (!mp) {
-		PMD_DRV_LOG(ERR,
-			    "mempool %s create failed: %d", name, rte_errno);
-		return -rte_errno;
+	hv->chim_bmap = rte_bitmap_init(hv->chim_cnt,
+					hv->chim_bmem, chim_bmp_size);
+	if (hv->chim_bmap == NULL) {
+		PMD_INIT_LOG(ERR, "failed to init chim bitmap");
+		return -1;
 	}
 
-	hv->tx_pool = mp;
+	for (i = 0; i < hv->chim_cnt; i++)
+		rte_bitmap_set(hv->chim_bmap, i);
+
 	return 0;
 }
 
 void
-hn_tx_pool_uninit(struct rte_eth_dev *dev)
+hn_chim_uninit(struct rte_eth_dev *dev)
 {
 	struct hn_data *hv = dev->data->dev_private;
 
-	if (hv->tx_pool) {
-		rte_mempool_free(hv->tx_pool);
-		hv->tx_pool = NULL;
+	rte_bitmap_free(hv->chim_bmap);
+	rte_free(hv->chim_bmem);
+	hv->chim_bmem = NULL;
+}
+
+static uint32_t hn_chim_alloc(struct hn_data *hv)
+{
+	uint32_t index = NVS_CHIM_IDX_INVALID;
+	uint64_t slab = 0;
+
+	rte_spinlock_lock(&hv->chim_lock);
+	if (rte_bitmap_scan(hv->chim_bmap, &index, &slab)) {
+		index += rte_bsf64(slab);
+		rte_bitmap_clear(hv->chim_bmap, index);
+	}
+	rte_spinlock_unlock(&hv->chim_lock);
+
+	return index;
+}
+
+static void hn_chim_free(struct hn_data *hv, uint32_t chim_idx)
+{
+	if (chim_idx >= hv->chim_cnt) {
+		PMD_DRV_LOG(ERR, "Invalid chimney index %u", chim_idx);
+	} else {
+		rte_spinlock_lock(&hv->chim_lock);
+		rte_bitmap_set(hv->chim_bmap, chim_idx);
+		rte_spinlock_unlock(&hv->chim_lock);
 	}
 }
 
@@ -220,18 +239,33 @@ static void hn_reset_txagg(struct hn_tx_queue *txq)
 
 int
 hn_dev_tx_queue_setup(struct rte_eth_dev *dev,
-		      uint16_t queue_idx, uint16_t nb_desc __rte_unused,
+		      uint16_t queue_idx, uint16_t nb_desc,
 		      unsigned int socket_id,
 		      const struct rte_eth_txconf *tx_conf)
 
 {
 	struct hn_data *hv = dev->data->dev_private;
 	struct hn_tx_queue *txq;
+	char name[RTE_MEMPOOL_NAMESIZE];
 	uint32_t tx_free_thresh;
-	int err;
+	int err = -ENOMEM;
 
 	PMD_INIT_FUNC_TRACE();
 
+	tx_free_thresh = tx_conf->tx_free_thresh;
+	if (tx_free_thresh == 0)
+		tx_free_thresh = RTE_MIN(nb_desc / 4,
+					 DEFAULT_TX_FREE_THRESH);
+
+	if (tx_free_thresh + 3 >= nb_desc) {
+		PMD_INIT_LOG(ERR,
+			     "tx_free_thresh must be less than the number of TX entries minus 3(%u)."
+			     " (tx_free_thresh=%u port=%u queue=%u)\n",
+			     nb_desc - 3,
+			     tx_free_thresh, dev->data->port_id, queue_idx);
+		return -EINVAL;
+	}
+
 	txq = rte_zmalloc_socket("HN_TXQ", sizeof(*txq), RTE_CACHE_LINE_SIZE,
 				 socket_id);
 	if (!txq)
@@ -241,16 +275,34 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev,
 	txq->chan = hv->channels[queue_idx];
 	txq->port_id = dev->data->port_id;
 	txq->queue_id = queue_idx;
+	txq->free_thresh = tx_free_thresh;
 
-	tx_free_thresh = tx_conf->tx_free_thresh;
-	if (tx_free_thresh == 0)
-		tx_free_thresh = RTE_MIN(hv->chim_cnt / 4,
-					 DEFAULT_TX_FREE_THRESH);
+	snprintf(name, sizeof(name),
+		 "hn_txd_%u_%u", dev->data->port_id, queue_idx);
 
-	if (tx_free_thresh >= hv->chim_cnt - 3)
-		tx_free_thresh = hv->chim_cnt - 3;
+	PMD_INIT_LOG(DEBUG, "TX descriptor pool %s n=%u size=%zu",
+		     name, nb_desc, sizeof(struct hn_txdesc));
 
-	txq->free_thresh = tx_free_thresh;
+	txq->tx_rndis_mz = rte_memzone_reserve_aligned(name,
+			nb_desc * HN_RNDIS_PKT_ALIGNED, rte_socket_id(),
+			RTE_MEMZONE_IOVA_CONTIG, HN_RNDIS_PKT_ALIGNED);
+	if (!txq->tx_rndis_mz) {
+		err = -rte_errno;
+		goto error;
+	}
+	txq->tx_rndis = txq->tx_rndis_mz->addr;
+	txq->tx_rndis_iova = txq->tx_rndis_mz->iova;
+
+	txq->txdesc_pool = rte_mempool_create(name, nb_desc,
+					      sizeof(struct hn_txdesc),
+					      0, 0, NULL, NULL,
+					      hn_txd_init, txq,
+					      dev->device->numa_node, 0);
+	if (txq->txdesc_pool == NULL) {
+		PMD_DRV_LOG(ERR,
+			    "mempool %s create failed: %d", name, rte_errno);
+		goto error;
+	}
 
 	txq->agg_szmax  = RTE_MIN(hv->chim_szmax, hv->rndis_agg_size);
 	txq->agg_pktmax = hv->rndis_agg_pkts;
@@ -260,31 +312,57 @@ hn_dev_tx_queue_setup(struct rte_eth_dev *dev,
 
 	err = hn_vf_tx_queue_setup(dev, queue_idx, nb_desc,
 				     socket_id, tx_conf);
-	if (err) {
-		rte_free(txq);
-		return err;
+	if (err == 0) {
+		dev->data->tx_queues[queue_idx] = txq;
+		return 0;
 	}
 
-	dev->data->tx_queues[queue_idx] = txq;
-	return 0;
+error:
+	if (txq->txdesc_pool)
+		rte_mempool_free(txq->txdesc_pool);
+	rte_memzone_free(txq->tx_rndis_mz);
+	rte_free(txq);
+	return err;
+}
+
+
+static struct hn_txdesc *hn_txd_get(struct hn_tx_queue *txq)
+{
+	struct hn_txdesc *txd;
+
+	if (rte_mempool_get(txq->txdesc_pool, (void **)&txd)) {
+		++txq->stats.ring_full;
+		PMD_TX_LOG(DEBUG, "tx pool exhausted!");
+		return NULL;
+	}
+
+	txd->m = NULL;
+	txd->packets = 0;
+	txd->data_size = 0;
+	txd->chim_size = 0;
+
+	return txd;
+}
+
+static void hn_txd_put(struct hn_tx_queue *txq, struct hn_txdesc *txd)
+{
+	rte_mempool_put(txq->txdesc_pool, txd);
 }
 
 void
 hn_dev_tx_queue_release(void *arg)
 {
 	struct hn_tx_queue *txq = arg;
-	struct hn_txdesc *txd;
 
 	PMD_INIT_FUNC_TRACE();
 
 	if (!txq)
 		return;
 
-	/* If any pending data is still present just drop it */
-	txd = txq->agg_txd;
-	if (txd)
-		rte_mempool_put(txq->hv->tx_pool, txd);
+	if (txq->txdesc_pool)
+		rte_mempool_free(txq->txdesc_pool);
 
+	rte_memzone_free(txq->tx_rndis_mz);
 	rte_free(txq);
 }
 
@@ -292,6 +370,7 @@ static void
 hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id,
 		      unsigned long xactid, const struct hn_nvs_rndis_ack *ack)
 {
+	struct hn_data *hv = dev->data->dev_private;
 	struct hn_txdesc *txd = (struct hn_txdesc *)xactid;
 	struct hn_tx_queue *txq;
 
@@ -312,9 +391,13 @@ hn_nvs_send_completed(struct rte_eth_dev *dev, uint16_t queue_id,
 		++txq->stats.errors;
 	}
 
-	rte_pktmbuf_free(txd->m);
+	if (txd->chim_index != NVS_CHIM_IDX_INVALID) {
+		hn_chim_free(hv, txd->chim_index);
+		txd->chim_index = NVS_CHIM_IDX_INVALID;
+	}
 
-	rte_mempool_put(txq->hv->tx_pool, txd);
+	rte_pktmbuf_free(txd->m);
+	hn_txd_put(txq, txd);
 }
 
 /* Handle transmit completion events */
@@ -413,35 +496,24 @@ hn_rndis_rxinfo(const void *info_data, unsigned int info_dlen,
 	return 0;
 }
 
-/*
- * Ack the consumed RXBUF associated w/ this channel packet,
- * so that this RXBUF can be recycled by the hypervisor.
- */
-static void hn_rx_buf_release(struct hn_rx_bufinfo *rxb)
-{
-	struct rte_mbuf_ext_shared_info *shinfo = &rxb->shinfo;
-	struct hn_data *hv = rxb->hv;
-
-	if (rte_mbuf_ext_refcnt_update(shinfo, -1) == 0) {
-		hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
-		--hv->rxbuf_outstanding;
-	}
-}
-
 static void hn_rx_buf_free_cb(void *buf __rte_unused, void *opaque)
 {
-	hn_rx_buf_release(opaque);
+	struct hn_rx_bufinfo *rxb = opaque;
+	struct hn_rx_queue *rxq = rxb->rxq;
+
+	rte_atomic32_dec(&rxq->rxbuf_outstanding);
+	hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
 }
 
-static struct hn_rx_bufinfo *hn_rx_buf_init(const struct hn_rx_queue *rxq,
+static struct hn_rx_bufinfo *hn_rx_buf_init(struct hn_rx_queue *rxq,
 					    const struct vmbus_chanpkt_rxbuf *pkt)
 {
 	struct hn_rx_bufinfo *rxb;
 
-	rxb = rxq->hv->rxbuf_info + pkt->hdr.xactid;
+	rxb = rxq->rxbuf_info + pkt->hdr.xactid;
 	rxb->chan = rxq->chan;
 	rxb->xactid = pkt->hdr.xactid;
-	rxb->hv = rxq->hv;
+	rxb->rxq = rxq;
 
 	rxb->shinfo.free_cb = hn_rx_buf_free_cb;
 	rxb->shinfo.fcb_opaque = rxb;
@@ -470,7 +542,8 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
 	 * some space available in receive area for later packets.
 	 */
 	if (dlen >= HN_RXCOPY_THRESHOLD &&
-	    hv->rxbuf_outstanding < hv->rxbuf_section_cnt / 2) {
+	    (uint32_t)rte_atomic32_read(&rxq->rxbuf_outstanding) <
+			hv->rxbuf_section_cnt / 2) {
 		struct rte_mbuf_ext_shared_info *shinfo;
 		const void *rxbuf;
 		rte_iova_t iova;
@@ -484,8 +557,9 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
 		iova = rte_mem_virt2iova(rxbuf) + RTE_PTR_DIFF(data, rxbuf);
 		shinfo = &rxb->shinfo;
 
-		if (rte_mbuf_ext_refcnt_update(shinfo, 1) == 1)
-			++hv->rxbuf_outstanding;
+		/* shinfo is already set to 1 by the caller */
+		if (rte_mbuf_ext_refcnt_update(shinfo, 1) == 2)
+			rte_atomic32_inc(&rxq->rxbuf_outstanding);
 
 		rte_pktmbuf_attach_extbuf(m, data, iova,
 					  dlen + headroom, shinfo);
@@ -558,7 +632,8 @@ static void hn_rndis_rx_data(struct hn_rx_queue *rxq,
 			     struct hn_rx_bufinfo *rxb,
 			     void *data, uint32_t dlen)
 {
-	unsigned int data_off, data_len, pktinfo_off, pktinfo_len;
+	unsigned int data_off, data_len;
+	unsigned int pktinfo_off, pktinfo_len;
 	const struct rndis_packet_msg *pkt = data;
 	struct hn_rxinfo info = {
 		.vlan_info = HN_NDIS_VLAN_INFO_INVALID,
@@ -603,7 +678,8 @@ static void hn_rndis_rx_data(struct hn_rx_queue *rxq,
 			goto error;
 	}
 
-	if (unlikely(data_off + data_len > pkt->len))
+	/* overflow check */
+	if (data_len > data_len + data_off || data_len + data_off > pkt->len)
 		goto error;
 
 	if (unlikely(data_len < RTE_ETHER_HDR_LEN))
@@ -725,7 +801,8 @@ hn_nvs_handle_rxbuf(struct rte_eth_dev *dev,
 	}
 
 	/* Send ACK now if external mbuf not used */
-	hn_rx_buf_release(rxb);
+	if (rte_mbuf_ext_refcnt_update(&rxb->shinfo, -1) == 0)
+		hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
 }
 
 /*
@@ -781,6 +858,23 @@ struct hn_rx_queue *hn_rx_queue_alloc(struct hn_data *hv,
 		return NULL;
 	}
 
+	/* setup rxbuf_info for non-primary queue */
+	if (queue_id) {
+		rxq->rxbuf_info = rte_calloc("HN_RXBUF_INFO",
+					hv->rxbuf_section_cnt,
+					sizeof(*rxq->rxbuf_info),
+					RTE_CACHE_LINE_SIZE);
+
+		if (!rxq->rxbuf_info) {
+			PMD_DRV_LOG(ERR,
+				"Could not allocate rxbuf info for queue %d\n",
+				queue_id);
+			rte_free(rxq->event_buf);
+			rte_free(rxq);
+			return NULL;
+		}
+	}
+
 	return rxq;
 }
 
@@ -835,6 +929,7 @@ hn_dev_rx_queue_setup(struct rte_eth_dev *dev,
 
 fail:
 	rte_ring_free(rxq->rx_ring);
+	rte_free(rxq->rxbuf_info);
 	rte_free(rxq->event_buf);
 	rte_free(rxq);
 	return error;
@@ -857,6 +952,7 @@ hn_rx_queue_free(struct hn_rx_queue *rxq, bool keep_primary)
 	if (keep_primary && rxq == rxq->hv->primary)
 		return;
 
+	rte_free(rxq->rxbuf_info);
 	rte_free(rxq->event_buf);
 	rte_free(rxq);
 }
@@ -894,10 +990,6 @@ uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id,
 
 	rxq = queue_id == 0 ? hv->primary : dev->data->rx_queues[queue_id];
 
-	/* If no pending data then nothing to do */
-	if (rte_vmbus_chan_rx_empty(rxq->chan))
-		return 0;
-
 	/*
 	 * Since channel is shared between Rx and TX queue need to have a lock
 	 * since DPDK does not force same CPU to be used for Rx/Tx.
@@ -961,9 +1053,6 @@ uint32_t hn_process_events(struct hn_data *hv, uint16_t queue_id,
 
 		if (tx_limit && tx_done >= tx_limit)
 			break;
-
-		if (rxq->rx_ring && rte_ring_full(rxq->rx_ring))
-			break;
 	}
 
 	if (bytes_read > 0)
@@ -1036,28 +1125,15 @@ static int hn_flush_txagg(struct hn_tx_queue *txq, bool *need_sig)
 	return ret;
 }
 
-static struct hn_txdesc *hn_new_txd(struct hn_data *hv,
-				    struct hn_tx_queue *txq)
-{
-	struct hn_txdesc *txd;
-
-	if (rte_mempool_get(hv->tx_pool, (void **)&txd)) {
-		++txq->stats.ring_full;
-		PMD_TX_LOG(DEBUG, "tx pool exhausted!");
-		return NULL;
-	}
-
-	txd->m = NULL;
-	txd->queue_id = txq->queue_id;
-	txd->packets = 0;
-	txd->data_size = 0;
-	txd->chim_size = 0;
-
-	return txd;
-}
-
+/*
+ * Try and find a place in a send chimney buffer to put
+ * the small packet. If space is available, this routine
+ * returns a pointer of where to place the data.
+ * If no space, caller should try direct transmit.
+ */
 static void *
-hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize)
+hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq,
+	     struct hn_txdesc *txd, uint32_t pktsize)
 {
 	struct hn_txdesc *agg_txd = txq->agg_txd;
 	struct rndis_packet_msg *pkt;
@@ -1085,7 +1161,7 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize)
 		}
 
 		chim = (uint8_t *)pkt + pkt->len;
-
+		txq->agg_prevpkt = chim;
 		txq->agg_pktleft--;
 		txq->agg_szleft -= pktsize;
 		if (txq->agg_szleft < HN_PKTSIZE_MIN(txq->agg_align)) {
@@ -1095,18 +1171,21 @@ hn_try_txagg(struct hn_data *hv, struct hn_tx_queue *txq, uint32_t pktsize)
 			 */
 			txq->agg_pktleft = 0;
 		}
-	} else {
-		agg_txd = hn_new_txd(hv, txq);
-		if (!agg_txd)
-			return NULL;
-
-		chim = (uint8_t *)hv->chim_res->addr
-			+ agg_txd->chim_index * hv->chim_szmax;
 
-		txq->agg_txd = agg_txd;
-		txq->agg_pktleft = txq->agg_pktmax - 1;
-		txq->agg_szleft = txq->agg_szmax - pktsize;
+		hn_txd_put(txq, txd);
+		return chim;
 	}
+
+	txd->chim_index = hn_chim_alloc(hv);
+	if (txd->chim_index == NVS_CHIM_IDX_INVALID)
+		return NULL;
+
+	chim = (uint8_t *)hv->chim_res->addr
+			+ txd->chim_index * hv->chim_szmax;
+
+	txq->agg_txd = txd;
+	txq->agg_pktleft = txq->agg_pktmax - 1;
+	txq->agg_szleft = txq->agg_szmax - pktsize;
 	txq->agg_prevpkt = chim;
 
 	return chim;
@@ -1282,11 +1361,8 @@ static int hn_xmit_sg(struct hn_tx_queue *txq,
 	hn_rndis_dump(txd->rndis_pkt);
 
 	/* pass IOVA of rndis header in first segment */
-	addr = rte_malloc_virt2iova(txd->rndis_pkt);
-	if (unlikely(addr == RTE_BAD_IOVA)) {
-		PMD_DRV_LOG(ERR, "RNDIS transmit can not get iova");
-		return -EINVAL;
-	}
+	addr = txq->tx_rndis_iova +
+		((char *)txd->rndis_pkt - (char *)txq->tx_rndis);
 
 	sg[0].page = addr / PAGE_SIZE;
 	sg[0].ofs = addr & PAGE_MASK;
@@ -1314,28 +1390,38 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	struct hn_data *hv = txq->hv;
 	struct rte_eth_dev *vf_dev;
 	bool need_sig = false;
-	uint16_t nb_tx;
+	uint16_t nb_tx, avail;
 	int ret;
 
 	if (unlikely(hv->closed))
 		return 0;
 
 	/* Transmit over VF if present and up */
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 
 	if (vf_dev && vf_dev->data->dev_started) {
 		void *sub_q = vf_dev->data->tx_queues[queue_id];
 
-		return (*vf_dev->tx_pkt_burst)(sub_q, tx_pkts, nb_pkts);
+		nb_tx = (*vf_dev->tx_pkt_burst)(sub_q, tx_pkts, nb_pkts);
+		rte_rwlock_read_unlock(&hv->vf_lock);
+		return nb_tx;
 	}
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
-	if (rte_mempool_avail_count(hv->tx_pool) <= txq->free_thresh)
+	avail = rte_mempool_avail_count(txq->txdesc_pool);
+	if (nb_pkts > avail || avail <= txq->free_thresh)
 		hn_process_events(hv, txq->queue_id, 0);
 
 	for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
 		struct rte_mbuf *m = tx_pkts[nb_tx];
 		uint32_t pkt_size = m->pkt_len + HN_RNDIS_PKT_LEN;
 		struct rndis_packet_msg *pkt;
+		struct hn_txdesc *txd;
+
+		txd = hn_txd_get(txq);
+		if (txd == NULL)
+			break;
 
 		/* For small packets aggregate them in chimney buffer */
 		if (m->pkt_len < HN_TXCOPY_THRESHOLD && pkt_size <= txq->agg_szmax) {
@@ -1346,7 +1432,8 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 					goto fail;
 			}
 
-			pkt = hn_try_txagg(hv, txq, pkt_size);
+
+			pkt = hn_try_txagg(hv, txq, txd, pkt_size);
 			if (unlikely(!pkt))
 				break;
 
@@ -1360,21 +1447,13 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			    hn_flush_txagg(txq, &need_sig))
 				goto fail;
 		} else {
-			struct hn_txdesc *txd;
-
-			/* can send chimney data and large packet at once */
-			txd = txq->agg_txd;
-			if (txd) {
-				hn_reset_txagg(txq);
-			} else {
-				txd = hn_new_txd(hv, txq);
-				if (unlikely(!txd))
-					break;
-			}
+			/* Send any outstanding packets in buffer */
+			if (txq->agg_txd && hn_flush_txagg(txq, &need_sig))
+				goto fail;
 
 			pkt = txd->rndis_pkt;
 			txd->m = m;
-			txd->data_size += m->pkt_len;
+			txd->data_size = m->pkt_len;
 			++txd->packets;
 
 			hn_encap(pkt, queue_id, m);
@@ -1383,7 +1462,7 @@ hn_xmit_pkts(void *ptxq, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			if (unlikely(ret != 0)) {
 				PMD_TX_LOG(NOTICE, "sg send failed: %d", ret);
 				++txq->stats.errors;
-				rte_mempool_put(hv->tx_pool, txd);
+				hn_txd_put(txq, txd);
 				goto fail;
 			}
 		}
@@ -1442,10 +1521,12 @@ hn_recv_pkts(void *prxq, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 					   (void **)rx_pkts, nb_pkts, NULL);
 
 	/* If VF is available, check that as well */
+	rte_rwlock_read_lock(&hv->vf_lock);
 	if (vf_dev && vf_dev->data->dev_started)
 		nb_rcv += hn_recv_vf(vf_dev->data->port_id, rxq,
 				     rx_pkts + nb_rcv, nb_pkts - nb_rcv);
 
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return nb_rcv;
 }
 
diff --git a/dpdk/drivers/net/netvsc/hn_var.h b/dpdk/drivers/net/netvsc/hn_var.h
index 05bc492511..9814113a0c 100644
--- a/dpdk/drivers/net/netvsc/hn_var.h
+++ b/dpdk/drivers/net/netvsc/hn_var.h
@@ -52,6 +52,10 @@ struct hn_tx_queue {
 	uint16_t	port_id;
 	uint16_t	queue_id;
 	uint32_t	free_thresh;
+	struct rte_mempool *txdesc_pool;
+	const struct rte_memzone *tx_rndis_mz;
+	void		*tx_rndis;
+	rte_iova_t	tx_rndis_iova;
 
 	/* Applied packet transmission aggregation limits. */
 	uint32_t	agg_szmax;
@@ -80,13 +84,15 @@ struct hn_rx_queue {
 	struct hn_stats stats;
 
 	void *event_buf;
+	struct hn_rx_bufinfo *rxbuf_info;
+	rte_atomic32_t  rxbuf_outstanding;
 };
 
 
 /* multi-packet data from host */
 struct hn_rx_bufinfo {
 	struct vmbus_channel *chan;
-	struct hn_data *hv;
+	struct hn_rx_queue *rxq;
 	uint64_t	xactid;
 	struct rte_mbuf_ext_shared_info shinfo;
 } __rte_cache_aligned;
@@ -96,7 +102,7 @@ struct hn_rx_bufinfo {
 struct hn_data {
 	struct rte_vmbus_device *vmbus;
 	struct hn_rx_queue *primary;
-	rte_spinlock_t  vf_lock;
+	rte_rwlock_t    vf_lock;
 	uint16_t	port_id;
 	uint16_t	vf_port;
 
@@ -108,15 +114,15 @@ struct hn_data {
 	uint32_t	link_speed;
 
 	struct rte_mem_resource *rxbuf_res;	/* UIO resource for Rx */
-	struct hn_rx_bufinfo *rxbuf_info;
 	uint32_t	rxbuf_section_cnt;	/* # of Rx sections */
-	volatile uint32_t rxbuf_outstanding;
 	uint16_t	max_queues;		/* Max available queues */
 	uint16_t	num_queues;
 	uint64_t	rss_offloads;
 
+	rte_spinlock_t	chim_lock;
 	struct rte_mem_resource *chim_res;	/* UIO resource for Tx */
-	struct rte_mempool *tx_pool;		/* Tx descriptors */
+	struct rte_bitmap *chim_bmap;		/* Send buffer map */
+	void		*chim_bmem;
 	uint32_t	chim_szmax;		/* Max size per buffer */
 	uint32_t	chim_cnt;		/* Max packets per buffer */
 
@@ -135,10 +141,7 @@ struct hn_data {
 	uint8_t		rss_key[40];
 	uint16_t	rss_ind[128];
 
-	struct rte_ether_addr mac_addr;
-
 	struct rte_eth_dev_owner owner;
-	struct rte_intr_handle vf_intr;
 
 	struct vmbus_channel *channels[HN_MAX_CHANNELS];
 };
@@ -157,8 +160,8 @@ uint16_t hn_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
 uint16_t hn_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
 		      uint16_t nb_pkts);
 
-int	hn_tx_pool_init(struct rte_eth_dev *dev);
-void	hn_tx_pool_uninit(struct rte_eth_dev *dev);
+int	hn_chim_init(struct rte_eth_dev *dev);
+void	hn_chim_uninit(struct rte_eth_dev *dev);
 int	hn_dev_link_update(struct rte_eth_dev *dev, int wait);
 int	hn_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 			      uint16_t nb_desc, unsigned int socket_id,
@@ -186,15 +189,15 @@ hn_vf_attached(const struct hn_data *hv)
 	return hv->vf_port != HN_INVALID_PORT;
 }
 
-/* Get VF device for existing netvsc device */
+/*
+ * Get VF device for existing netvsc device
+ * Assumes vf_lock is held.
+ */
 static inline struct rte_eth_dev *
 hn_get_vf_dev(const struct hn_data *hv)
 {
 	uint16_t vf_port = hv->vf_port;
 
-	/* make sure vf_port is loaded */
-	rte_smp_rmb();
-
 	if (vf_port == HN_INVALID_PORT)
 		return NULL;
 	else
@@ -220,8 +223,6 @@ int	hn_vf_mc_addr_list(struct rte_eth_dev *dev,
 			   struct rte_ether_addr *mc_addr_set,
 			   uint32_t nb_mc_addr);
 
-int	hn_vf_link_update(struct rte_eth_dev *dev,
-			  int wait_to_complete);
 int	hn_vf_tx_queue_setup(struct rte_eth_dev *dev,
 			     uint16_t queue_idx, uint16_t nb_desc,
 			     unsigned int socket_id,
diff --git a/dpdk/drivers/net/netvsc/hn_vf.c b/dpdk/drivers/net/netvsc/hn_vf.c
index 7a3734cadf..f5f15c0462 100644
--- a/dpdk/drivers/net/netvsc/hn_vf.c
+++ b/dpdk/drivers/net/netvsc/hn_vf.c
@@ -82,8 +82,6 @@ static int hn_vf_attach(struct hn_data *hv, uint16_t port_id)
 
 	PMD_DRV_LOG(DEBUG, "Attach VF device %u", port_id);
 	hv->vf_port = port_id;
-	rte_smp_wmb();
-
 	return 0;
 }
 
@@ -98,19 +96,9 @@ int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv)
 		return port;
 	}
 
-	rte_spinlock_lock(&hv->vf_lock);
 	err = hn_vf_attach(hv, port);
-
-	if (err == 0) {
-		dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
-		hv->vf_intr = (struct rte_intr_handle) {
-			.fd = -1,
-			.type = RTE_INTR_HANDLE_EXT,
-		};
-		dev->intr_handle = &hv->vf_intr;
+	if (err == 0)
 		hn_nvs_set_datapath(hv, NVS_DATAPATH_VF);
-	}
-	rte_spinlock_unlock(&hv->vf_lock);
 
 	return err;
 }
@@ -119,22 +107,18 @@ int hn_vf_add(struct rte_eth_dev *dev, struct hn_data *hv)
 static void hn_vf_remove(struct hn_data *hv)
 {
 
-	rte_spinlock_lock(&hv->vf_lock);
-
 	if (!hn_vf_attached(hv)) {
 		PMD_DRV_LOG(ERR, "VF path not active");
 	} else {
 		/* Stop incoming packets from arriving on VF */
 		hn_nvs_set_datapath(hv, NVS_DATAPATH_SYNTHETIC);
 
-		/* Stop transmission over VF */
-		hv->vf_port = HN_INVALID_PORT;
-		rte_smp_wmb();
-
 		/* Give back ownership */
 		rte_eth_dev_owner_unset(hv->vf_port, hv->owner.id);
+
+		/* Stop transmission over VF */
+		hv->vf_port = HN_INVALID_PORT;
 	}
-	rte_spinlock_unlock(&hv->vf_lock);
 }
 
 /* Handle VF association message from host */
@@ -156,15 +140,27 @@ hn_nvs_handle_vfassoc(struct rte_eth_dev *dev,
 		    vf_assoc->allocated ? "add to" : "remove from",
 		    dev->data->port_id);
 
+	rte_rwlock_write_lock(&hv->vf_lock);
 	hv->vf_present = vf_assoc->allocated;
 
-	if (dev->state != RTE_ETH_DEV_ATTACHED)
-		return;
+	if (dev->state == RTE_ETH_DEV_ATTACHED) {
+		if (vf_assoc->allocated)
+			hn_vf_add(dev, hv);
+		else
+			hn_vf_remove(hv);
+	}
+	rte_rwlock_write_unlock(&hv->vf_lock);
+}
 
-	if (vf_assoc->allocated)
-		hn_vf_add(dev, hv);
-	else
-		hn_vf_remove(hv);
+static void
+hn_vf_merge_desc_lim(struct rte_eth_desc_lim *lim,
+		     const struct rte_eth_desc_lim *vf_lim)
+{
+	lim->nb_max = RTE_MIN(vf_lim->nb_max, lim->nb_max);
+	lim->nb_min = RTE_MAX(vf_lim->nb_min, lim->nb_min);
+	lim->nb_align = RTE_MAX(vf_lim->nb_align, lim->nb_align);
+	lim->nb_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max);
+	lim->nb_mtu_seg_max = RTE_MIN(vf_lim->nb_seg_max, lim->nb_seg_max);
 }
 
 /*
@@ -196,11 +192,13 @@ static int hn_vf_info_merge(struct rte_eth_dev *vf_dev,
 				      info->max_tx_queues);
 	info->tx_offload_capa &= vf_info.tx_offload_capa;
 	info->tx_queue_offload_capa &= vf_info.tx_queue_offload_capa;
+	hn_vf_merge_desc_lim(&info->tx_desc_lim, &vf_info.tx_desc_lim);
 
 	info->min_rx_bufsize = RTE_MAX(vf_info.min_rx_bufsize,
 				       info->min_rx_bufsize);
 	info->max_rx_pktlen  = RTE_MAX(vf_info.max_rx_pktlen,
 				       info->max_rx_pktlen);
+	hn_vf_merge_desc_lim(&info->rx_desc_lim, &vf_info.rx_desc_lim);
 
 	return 0;
 }
@@ -210,85 +208,11 @@ int hn_vf_info_get(struct hn_data *hv, struct rte_eth_dev_info *info)
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = hn_vf_info_merge(vf_dev, info);
-	rte_spinlock_unlock(&hv->vf_lock);
-	return ret;
-}
-
-int hn_vf_link_update(struct rte_eth_dev *dev,
-		      int wait_to_complete)
-{
-	struct hn_data *hv = dev->data->dev_private;
-	struct rte_eth_dev *vf_dev;
-	int ret = 0;
-
-	rte_spinlock_lock(&hv->vf_lock);
-	vf_dev = hn_get_vf_dev(hv);
-	if (vf_dev && vf_dev->dev_ops->link_update)
-		ret = (*vf_dev->dev_ops->link_update)(vf_dev, wait_to_complete);
-	rte_spinlock_unlock(&hv->vf_lock);
-
-	return ret;
-}
-
-/* called when VF has link state interrupts enabled */
-static int hn_vf_lsc_event(uint16_t port_id __rte_unused,
-			   enum rte_eth_event_type event,
-			   void *cb_arg, void *out __rte_unused)
-{
-	struct rte_eth_dev *dev = cb_arg;
-
-	if (event != RTE_ETH_EVENT_INTR_LSC)
-		return 0;
-
-	/* if link state has changed pass on */
-	if (hn_dev_link_update(dev, 0) == 0)
-		return 0; /* no change */
-
-	return _rte_eth_dev_callback_process(dev,
-					     RTE_ETH_EVENT_INTR_LSC,
-					     NULL);
-}
-
-static int _hn_vf_configure(struct rte_eth_dev *dev,
-			    uint16_t vf_port,
-			    const struct rte_eth_conf *dev_conf)
-{
-	struct rte_eth_conf vf_conf = *dev_conf;
-	struct rte_eth_dev *vf_dev;
-	int ret;
-
-	vf_dev = &rte_eth_devices[vf_port];
-	if (dev_conf->intr_conf.lsc &&
-	    (vf_dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)) {
-		PMD_DRV_LOG(DEBUG, "enabling LSC for VF %u",
-			    vf_port);
-		vf_conf.intr_conf.lsc = 1;
-	} else {
-		PMD_DRV_LOG(DEBUG, "disabling LSC for VF %u",
-			    vf_port);
-		vf_conf.intr_conf.lsc = 0;
-	}
-
-	ret = rte_eth_dev_configure(vf_port,
-				    dev->data->nb_rx_queues,
-				    dev->data->nb_tx_queues,
-				    &vf_conf);
-	if (ret) {
-		PMD_DRV_LOG(ERR,
-			    "VF configuration failed: %d", ret);
-	} else if (vf_conf.intr_conf.lsc) {
-		ret = rte_eth_dev_callback_register(vf_port,
-						    RTE_ETH_DEV_INTR_LSC,
-						    hn_vf_lsc_event, dev);
-		if (ret)
-			PMD_DRV_LOG(ERR,
-				    "Failed to register LSC callback for VF %u",
-				    vf_port);
-	}
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -300,12 +224,23 @@ int hn_vf_configure(struct rte_eth_dev *dev,
 		    const struct rte_eth_conf *dev_conf)
 {
 	struct hn_data *hv = dev->data->dev_private;
+	struct rte_eth_conf vf_conf = *dev_conf;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
-	if (hv->vf_port != HN_INVALID_PORT)
-		ret = _hn_vf_configure(dev, hv->vf_port, dev_conf);
-	rte_spinlock_unlock(&hv->vf_lock);
+	/* link state interrupt does not matter here. */
+	vf_conf.intr_conf.lsc = 0;
+
+	rte_rwlock_read_lock(&hv->vf_lock);
+	if (hv->vf_port != HN_INVALID_PORT) {
+		ret = rte_eth_dev_configure(hv->vf_port,
+					    dev->data->nb_rx_queues,
+					    dev->data->nb_tx_queues,
+					    &vf_conf);
+		if (ret != 0)
+			PMD_DRV_LOG(ERR,
+				    "VF configuration failed: %d", ret);
+	}
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -315,11 +250,11 @@ const uint32_t *hn_vf_supported_ptypes(struct rte_eth_dev *dev)
 	struct rte_eth_dev *vf_dev;
 	const uint32_t *ptypes = NULL;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev && vf_dev->dev_ops->dev_supported_ptypes_get)
 		ptypes = (*vf_dev->dev_ops->dev_supported_ptypes_get)(vf_dev);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	return ptypes;
 }
@@ -330,11 +265,11 @@ int hn_vf_start(struct rte_eth_dev *dev)
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = rte_eth_dev_start(vf_dev->data->port_id);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -343,11 +278,11 @@ void hn_vf_stop(struct rte_eth_dev *dev)
 	struct hn_data *hv = dev->data->dev_private;
 	struct rte_eth_dev *vf_dev;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		rte_eth_dev_stop(vf_dev->data->port_id);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 }
 
 /* If VF is present, then cascade configuration down */
@@ -355,11 +290,11 @@ void hn_vf_stop(struct rte_eth_dev *dev)
 	{							\
 		struct hn_data *hv = (dev)->data->dev_private;	\
 		struct rte_eth_dev *vf_dev;			\
-		rte_spinlock_lock(&hv->vf_lock);		\
+		rte_rwlock_read_lock(&hv->vf_lock);		\
 		vf_dev = hn_get_vf_dev(hv);			\
 		if (vf_dev)					\
 			func(vf_dev->data->port_id);		\
-		rte_spinlock_unlock(&hv->vf_lock);		\
+		rte_rwlock_read_unlock(&hv->vf_lock);		\
 	}
 
 /* If VF is present, then cascade configuration down */
@@ -368,11 +303,11 @@ void hn_vf_stop(struct rte_eth_dev *dev)
 		struct hn_data *hv = (dev)->data->dev_private;	\
 		struct rte_eth_dev *vf_dev;			\
 		int ret = 0;					\
-		rte_spinlock_lock(&hv->vf_lock);		\
+		rte_rwlock_read_lock(&hv->vf_lock);		\
 		vf_dev = hn_get_vf_dev(hv);			\
 		if (vf_dev)					\
 			ret = func(vf_dev->data->port_id);	\
-		rte_spinlock_unlock(&hv->vf_lock);		\
+		rte_rwlock_read_unlock(&hv->vf_lock);		\
 		return ret;					\
 	}
 
@@ -386,13 +321,13 @@ void hn_vf_close(struct rte_eth_dev *dev)
 	struct hn_data *hv = dev->data->dev_private;
 	uint16_t vf_port;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_port = hv->vf_port;
 	if (vf_port != HN_INVALID_PORT)
 		rte_eth_dev_close(vf_port);
 
 	hv->vf_port = HN_INVALID_PORT;
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 }
 
 int hn_vf_stats_reset(struct rte_eth_dev *dev)
@@ -428,12 +363,12 @@ int hn_vf_mc_addr_list(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = rte_eth_dev_set_mc_addr_list(vf_dev->data->port_id,
 						   mc_addr_set, nb_mc_addr);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -446,13 +381,13 @@ int hn_vf_tx_queue_setup(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = rte_eth_tx_queue_setup(vf_dev->data->port_id,
 					     queue_idx, nb_desc,
 					     socket_id, tx_conf);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -460,7 +395,7 @@ void hn_vf_tx_queue_release(struct hn_data *hv, uint16_t queue_id)
 {
 	struct rte_eth_dev *vf_dev;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev && vf_dev->dev_ops->tx_queue_release) {
 		void *subq = vf_dev->data->tx_queues[queue_id];
@@ -468,7 +403,7 @@ void hn_vf_tx_queue_release(struct hn_data *hv, uint16_t queue_id)
 		(*vf_dev->dev_ops->tx_queue_release)(subq);
 	}
 
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 }
 
 int hn_vf_rx_queue_setup(struct rte_eth_dev *dev,
@@ -481,13 +416,13 @@ int hn_vf_rx_queue_setup(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = rte_eth_rx_queue_setup(vf_dev->data->port_id,
 					     queue_idx, nb_desc,
 					     socket_id, rx_conf, mp);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -495,14 +430,14 @@ void hn_vf_rx_queue_release(struct hn_data *hv, uint16_t queue_id)
 {
 	struct rte_eth_dev *vf_dev;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev && vf_dev->dev_ops->rx_queue_release) {
 		void *subq = vf_dev->data->rx_queues[queue_id];
 
 		(*vf_dev->dev_ops->rx_queue_release)(subq);
 	}
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 }
 
 int hn_vf_stats_get(struct rte_eth_dev *dev,
@@ -512,11 +447,11 @@ int hn_vf_stats_get(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = rte_eth_stats_get(vf_dev->data->port_id, stats);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 	return ret;
 }
 
@@ -528,12 +463,12 @@ int hn_vf_xstats_get_names(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int i, count = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		count = rte_eth_xstats_get_names(vf_dev->data->port_id,
 						 names, n);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	/* add vf_ prefix to xstat names */
 	if (names) {
@@ -557,12 +492,12 @@ int hn_vf_xstats_get(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int i, count = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		count = rte_eth_xstats_get(vf_dev->data->port_id,
 					   xstats + offset, n - offset);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	/* Offset id's for VF stats */
 	if (count > 0) {
@@ -579,13 +514,13 @@ int hn_vf_xstats_reset(struct rte_eth_dev *dev)
 	struct rte_eth_dev *vf_dev;
 	int ret;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev)
 		ret = rte_eth_xstats_reset(vf_dev->data->port_id);
 	else
 		ret = -EINVAL;
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	return ret;
 }
@@ -597,11 +532,11 @@ int hn_vf_rss_hash_update(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev && vf_dev->dev_ops->rss_hash_update)
 		ret = vf_dev->dev_ops->rss_hash_update(vf_dev, rss_conf);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	return ret;
 }
@@ -614,12 +549,12 @@ int hn_vf_reta_hash_update(struct rte_eth_dev *dev,
 	struct rte_eth_dev *vf_dev;
 	int ret = 0;
 
-	rte_spinlock_lock(&hv->vf_lock);
+	rte_rwlock_read_lock(&hv->vf_lock);
 	vf_dev = hn_get_vf_dev(hv);
 	if (vf_dev && vf_dev->dev_ops->reta_update)
 		ret = vf_dev->dev_ops->reta_update(vf_dev,
 						   reta_conf, reta_size);
-	rte_spinlock_unlock(&hv->vf_lock);
+	rte_rwlock_read_unlock(&hv->vf_lock);
 
 	return ret;
 }
diff --git a/dpdk/drivers/net/nfb/meson.build b/dpdk/drivers/net/nfb/meson.build
index d53e8eca7d..995c44c61c 100644
--- a/dpdk/drivers/net/nfb/meson.build
+++ b/dpdk/drivers/net/nfb/meson.build
@@ -3,7 +3,7 @@
 # Copyright(c) 2019 Netcope Technologies, a.s. <info@netcope.com>
 # All rights reserved.
 
-dep = dependency('netcope-common', required: false)
+dep = dependency('netcope-common', required: false, method: 'pkg-config')
 reason = 'missing dependency, "libnfb"'
 build = dep.found()
 ext_deps += dep
diff --git a/dpdk/drivers/net/nfp/nfp_net.c b/dpdk/drivers/net/nfp/nfp_net.c
index 3aafa7f80f..2aa3b2a103 100644
--- a/dpdk/drivers/net/nfp/nfp_net.c
+++ b/dpdk/drivers/net/nfp/nfp_net.c
@@ -1250,6 +1250,20 @@ nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 		.tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH,
 	};
 
+	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = NFP_NET_MAX_RX_DESC,
+		.nb_min = NFP_NET_MIN_RX_DESC,
+		.nb_align = NFP_ALIGN_RING_DESC,
+	};
+
+	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
+		.nb_max = NFP_NET_MAX_TX_DESC,
+		.nb_min = NFP_NET_MIN_TX_DESC,
+		.nb_align = NFP_ALIGN_RING_DESC,
+		.nb_seg_max = NFP_TX_MAX_SEG,
+		.nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG,
+	};
+
 	dev_info->flow_type_rss_offloads = ETH_RSS_IPV4 |
 					   ETH_RSS_NONFRAG_IPV4_TCP |
 					   ETH_RSS_NONFRAG_IPV4_UDP |
@@ -1487,7 +1501,7 @@ nfp_net_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu)
 	}
 
 	/* switch to jumbo mode if needed */
-	if ((uint32_t)mtu > RTE_ETHER_MAX_LEN)
+	if ((uint32_t)mtu > RTE_ETHER_MTU)
 		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
 		dev->data->dev_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
@@ -1513,15 +1527,17 @@ nfp_net_rx_queue_setup(struct rte_eth_dev *dev,
 	const struct rte_memzone *tz;
 	struct nfp_net_rxq *rxq;
 	struct nfp_net_hw *hw;
+	uint32_t rx_desc_sz;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	PMD_INIT_FUNC_TRACE();
 
 	/* Validating number of descriptors */
-	if (((nb_desc * sizeof(struct nfp_net_rx_desc)) % 128) != 0 ||
-	    (nb_desc > NFP_NET_MAX_RX_DESC) ||
-	    (nb_desc < NFP_NET_MIN_RX_DESC)) {
+	rx_desc_sz = nb_desc * sizeof(struct nfp_net_rx_desc);
+	if (rx_desc_sz % NFP_ALIGN_RING_DESC != 0 ||
+	    nb_desc > NFP_NET_MAX_RX_DESC ||
+	    nb_desc < NFP_NET_MIN_RX_DESC) {
 		PMD_DRV_LOG(ERR, "Wrong nb_desc value");
 		return -EINVAL;
 	}
@@ -1660,15 +1676,17 @@ nfp_net_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
 	struct nfp_net_txq *txq;
 	uint16_t tx_free_thresh;
 	struct nfp_net_hw *hw;
+	uint32_t tx_desc_sz;
 
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
 	PMD_INIT_FUNC_TRACE();
 
 	/* Validating number of descriptors */
-	if (((nb_desc * sizeof(struct nfp_net_tx_desc)) % 128) != 0 ||
-	    (nb_desc > NFP_NET_MAX_TX_DESC) ||
-	    (nb_desc < NFP_NET_MIN_TX_DESC)) {
+	tx_desc_sz = nb_desc * sizeof(struct nfp_net_tx_desc);
+	if (tx_desc_sz % NFP_ALIGN_RING_DESC != 0 ||
+	    nb_desc > NFP_NET_MAX_TX_DESC ||
+	    nb_desc < NFP_NET_MIN_TX_DESC) {
 		PMD_DRV_LOG(ERR, "Wrong nb_desc value");
 		return -EINVAL;
 	}
@@ -2353,11 +2371,6 @@ nfp_net_vlan_offload_set(struct rte_eth_dev *dev, int mask)
 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 	new_ctrl = 0;
 
-	if ((mask & ETH_VLAN_FILTER_OFFLOAD) ||
-	    (mask & ETH_VLAN_EXTEND_OFFLOAD))
-		PMD_DRV_LOG(INFO, "No support for ETH_VLAN_FILTER_OFFLOAD or"
-			" ETH_VLAN_EXTEND_OFFLOAD");
-
 	/* Enable vlan strip if it is not configured yet */
 	if ((mask & ETH_VLAN_STRIP_OFFLOAD) &&
 	    !(hw->ctrl & NFP_NET_CFG_CTRL_RXVLAN))
@@ -2626,6 +2639,9 @@ nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev,
 	if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6)
 		rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP;
 
+	/* Propagate current RSS hash functions to caller */
+	rss_conf->rss_hf = rss_hf;
+
 	/* Reading the key size */
 	rss_conf->rss_key_len = nn_cfg_readl(hw, NFP_NET_CFG_RSS_KEY_SZ);
 
@@ -3014,7 +3030,7 @@ nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp)
 	size_t count, curlen, totlen = 0;
 	int err = 0;
 
-	PMD_CPP_LOG(DEBUG, "%s: offset size %lu, count_size: %lu\n", __func__,
+	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu\n", __func__,
 		sizeof(off_t), sizeof(size_t));
 
 	/* Reading the count param */
@@ -3033,9 +3049,9 @@ nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp)
 	cpp_id = (offset >> 40) << 8;
 	nfp_offset = offset & ((1ull << 40) - 1);
 
-	PMD_CPP_LOG(DEBUG, "%s: count %lu and offset %ld\n", __func__, count,
+	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd\n", __func__, count,
 		offset);
-	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %ld\n", __func__,
+	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd\n", __func__,
 		cpp_id, nfp_offset);
 
 	/* Adjust length if not aligned */
@@ -3067,12 +3083,12 @@ nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp)
 			if (len > sizeof(tmpbuf))
 				len = sizeof(tmpbuf);
 
-			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %lu\n", __func__,
+			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %zu\n", __func__,
 					   len, count);
 			err = recv(sockfd, tmpbuf, len, MSG_WAITALL);
 			if (err != (int)len) {
 				RTE_LOG(ERR, PMD,
-					"%s: error when receiving, %d of %lu\n",
+					"%s: error when receiving, %d of %zu\n",
 					__func__, err, count);
 				nfp_cpp_area_release(area);
 				nfp_cpp_area_free(area);
@@ -3116,7 +3132,7 @@ nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp)
 	size_t count, curlen, totlen = 0;
 	int err = 0;
 
-	PMD_CPP_LOG(DEBUG, "%s: offset size %lu, count_size: %lu\n", __func__,
+	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu\n", __func__,
 		sizeof(off_t), sizeof(size_t));
 
 	/* Reading the count param */
@@ -3135,9 +3151,9 @@ nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp)
 	cpp_id = (offset >> 40) << 8;
 	nfp_offset = offset & ((1ull << 40) - 1);
 
-	PMD_CPP_LOG(DEBUG, "%s: count %lu and offset %ld\n", __func__, count,
+	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd\n", __func__, count,
 			   offset);
-	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %ld\n", __func__,
+	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd\n", __func__,
 			   cpp_id, nfp_offset);
 
 	/* Adjust length if not aligned */
@@ -3174,13 +3190,13 @@ nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp)
 				nfp_cpp_area_free(area);
 				return -EIO;
 			}
-			PMD_CPP_LOG(DEBUG, "%s: sending %u of %lu\n", __func__,
+			PMD_CPP_LOG(DEBUG, "%s: sending %u of %zu\n", __func__,
 					   len, count);
 
 			err = send(sockfd, tmpbuf, len, 0);
 			if (err != (int)len) {
 				RTE_LOG(ERR, PMD,
-					"%s: error when sending: %d of %lu\n",
+					"%s: error when sending: %d of %zu\n",
 					__func__, err, count);
 				nfp_cpp_area_release(area);
 				nfp_cpp_area_free(area);
@@ -3451,9 +3467,10 @@ nfp_pf_create_dev(struct rte_pci_device *dev, int port, int ports,
 probe_failed:
 	rte_free(port_name);
 	/* free ports private data if primary process */
-	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
 		rte_free(eth_dev->data->dev_private);
-
+		eth_dev->data->dev_private = NULL;
+	}
 	rte_eth_dev_release_port(eth_dev);
 
 	return retval;
diff --git a/dpdk/drivers/net/nfp/nfp_net_pmd.h b/dpdk/drivers/net/nfp/nfp_net_pmd.h
index cc1055c49a..466a11aca2 100644
--- a/dpdk/drivers/net/nfp/nfp_net_pmd.h
+++ b/dpdk/drivers/net/nfp/nfp_net_pmd.h
@@ -33,6 +33,12 @@ struct nfp_net_adapter;
 #define NFP_NET_MAX_RX_DESC (32 * 1024)
 #define NFP_NET_MIN_RX_DESC 64
 
+/* Descriptor alignment */
+#define NFP_ALIGN_RING_DESC 128
+
+#define NFP_TX_MAX_SEG     UINT8_MAX
+#define NFP_TX_MAX_MTU_SEG 8
+
 /* Bar allocation */
 #define NFP_NET_CRTL_BAR        0
 #define NFP_NET_TX_BAR          2
diff --git a/dpdk/drivers/net/nfp/nfpcore/nfp_cpp.h b/dpdk/drivers/net/nfp/nfpcore/nfp_cpp.h
index 1427954c17..08d656da14 100644
--- a/dpdk/drivers/net/nfp/nfpcore/nfp_cpp.h
+++ b/dpdk/drivers/net/nfp/nfpcore/nfp_cpp.h
@@ -170,7 +170,7 @@ void *nfp_cpp_priv(struct nfp_cpp *cpp);
  */
 void *nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area);
 
-uint32_t __nfp_cpp_model_autodetect(struct nfp_cpp *cpp);
+uint32_t __nfp_cpp_model_autodetect(struct nfp_cpp *cpp, uint32_t *model);
 
 /*
  * NFP CPP core interface for CPP clients.
diff --git a/dpdk/drivers/net/nfp/nfpcore/nfp_cppcore.c b/dpdk/drivers/net/nfp/nfpcore/nfp_cppcore.c
index dec4a8b6d1..6d629430d4 100644
--- a/dpdk/drivers/net/nfp/nfpcore/nfp_cppcore.c
+++ b/dpdk/drivers/net/nfp/nfpcore/nfp_cppcore.c
@@ -22,8 +22,9 @@
 
 #define NFP_PL_DEVICE_ID                        0x00000004
 #define NFP_PL_DEVICE_ID_MASK                   0xff
-
-#define NFP6000_ARM_GCSR_SOFTMODEL0             0x00400144
+#define NFP_PL_DEVICE_PART_MASK                 0xffff0000
+#define NFP_PL_DEVICE_MODEL_MASK               (NFP_PL_DEVICE_PART_MASK | \
+						NFP_PL_DEVICE_ID_MASK)
 
 void
 nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv)
@@ -46,13 +47,18 @@ nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model)
 uint32_t
 nfp_cpp_model(struct nfp_cpp *cpp)
 {
+	int err;
+	uint32_t model;
+
 	if (!cpp)
 		return NFP_CPP_MODEL_INVALID;
 
-	if (cpp->model == 0)
-		cpp->model = __nfp_cpp_model_autodetect(cpp);
+	err = __nfp_cpp_model_autodetect(cpp, &model);
 
-	return cpp->model;
+	if (err < 0)
+		return err;
+
+	return model;
 }
 
 void
@@ -389,9 +395,6 @@ nfp_xpb_to_cpp(struct nfp_cpp *cpp, uint32_t *xpb_addr)
 	uint32_t xpb;
 	int island;
 
-	if (!NFP_CPP_MODEL_IS_6000(cpp->model))
-		return 0;
-
 	xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
 
 	/*
@@ -796,29 +799,21 @@ nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
  * as those are model-specific
  */
 uint32_t
-__nfp_cpp_model_autodetect(struct nfp_cpp *cpp)
+__nfp_cpp_model_autodetect(struct nfp_cpp *cpp, uint32_t *model)
 {
-	uint32_t arm_id = NFP_CPP_ID(NFP_CPP_TARGET_ARM, 0, 0);
-	uint32_t model = 0;
-
-	if (nfp_cpp_readl(cpp, arm_id, NFP6000_ARM_GCSR_SOFTMODEL0, &model))
-		return 0;
-
-	if (NFP_CPP_MODEL_IS_6000(model)) {
-		uint32_t tmp;
-
-		nfp_cpp_model_set(cpp, model);
+	uint32_t reg;
+	int err;
 
-		/* The PL's PluDeviceID revision code is authoratative */
-		model &= ~0xff;
-		if (nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) +
-				   NFP_PL_DEVICE_ID, &tmp))
-			return 0;
+	err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
+			    &reg);
+	if (err < 0)
+		return err;
 
-		model |= (NFP_PL_DEVICE_ID_MASK & tmp) - 0x10;
-	}
+	*model = reg & NFP_PL_DEVICE_MODEL_MASK;
+	if (*model & NFP_PL_DEVICE_ID_MASK)
+		*model -= 0x10;
 
-	return model;
+	return 0;
 }
 
 /*
diff --git a/dpdk/drivers/net/null/rte_eth_null.c b/dpdk/drivers/net/null/rte_eth_null.c
index 025b73acb3..beedd5f4b2 100644
--- a/dpdk/drivers/net/null/rte_eth_null.c
+++ b/dpdk/drivers/net/null/rte_eth_null.c
@@ -584,6 +584,7 @@ rte_pmd_null_probe(struct rte_vdev_device *dev)
 	PMD_LOG(INFO, "Initializing pmd_null for %s", name);
 
 	if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+		struct pmd_internals *internals;
 		eth_dev = rte_eth_dev_attach_secondary(name);
 		if (!eth_dev) {
 			PMD_LOG(ERR, "Failed to probe %s", name);
@@ -592,7 +593,8 @@ rte_pmd_null_probe(struct rte_vdev_device *dev)
 		/* TODO: request info from primary to set up Rx and Tx */
 		eth_dev->dev_ops = &ops;
 		eth_dev->device = &dev->device;
-		if (packet_copy) {
+		internals = eth_dev->data->dev_private;
+		if (internals->packet_copy) {
 			eth_dev->rx_pkt_burst = eth_null_copy_rx;
 			eth_dev->tx_pkt_burst = eth_null_copy_tx;
 		} else {
@@ -608,23 +610,18 @@ rte_pmd_null_probe(struct rte_vdev_device *dev)
 		if (kvlist == NULL)
 			return -1;
 
-		if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_SIZE_ARG) == 1) {
+		ret = rte_kvargs_process(kvlist,
+				ETH_NULL_PACKET_SIZE_ARG,
+				&get_packet_size_arg, &packet_size);
+		if (ret < 0)
+			goto free_kvlist;
 
-			ret = rte_kvargs_process(kvlist,
-					ETH_NULL_PACKET_SIZE_ARG,
-					&get_packet_size_arg, &packet_size);
-			if (ret < 0)
-				goto free_kvlist;
-		}
-
-		if (rte_kvargs_count(kvlist, ETH_NULL_PACKET_COPY_ARG) == 1) {
 
-			ret = rte_kvargs_process(kvlist,
-					ETH_NULL_PACKET_COPY_ARG,
-					&get_packet_copy_arg, &packet_copy);
-			if (ret < 0)
-				goto free_kvlist;
-		}
+		ret = rte_kvargs_process(kvlist,
+				ETH_NULL_PACKET_COPY_ARG,
+				&get_packet_copy_arg, &packet_copy);
+		if (ret < 0)
+			goto free_kvlist;
 	}
 
 	PMD_LOG(INFO, "Configure pmd_null: packet size is %d, "
diff --git a/dpdk/drivers/net/octeontx/base/meson.build b/dpdk/drivers/net/octeontx/base/meson.build
index a06a2c89c9..e1060fc4ec 100644
--- a/dpdk/drivers/net/octeontx/base/meson.build
+++ b/dpdk/drivers/net/octeontx/base/meson.build
@@ -10,7 +10,10 @@ sources = [
 depends = ['ethdev', 'mempool_octeontx']
 static_objs = []
 foreach d: depends
-	static_objs += [get_variable('static_rte_' + d)]
+	if not is_variable('shared_rte_' + d)
+		subdir_done()
+	endif
+	static_objs += get_variable('static_rte_' + d)
 endforeach
 
 c_args = cflags
diff --git a/dpdk/drivers/net/octeontx/base/octeontx_io.h b/dpdk/drivers/net/octeontx/base/octeontx_io.h
index 04b9ce1910..d0b9cfbc67 100644
--- a/dpdk/drivers/net/octeontx/base/octeontx_io.h
+++ b/dpdk/drivers/net/octeontx/base/octeontx_io.h
@@ -52,6 +52,11 @@ do {							\
 #endif
 
 #if defined(RTE_ARCH_ARM64)
+#if defined(__ARM_FEATURE_SVE)
+#define __LSE_PREAMBLE " .cpu	generic+lse+sve\n"
+#else
+#define __LSE_PREAMBLE " .cpu	generic+lse\n"
+#endif
 /**
  * Perform an atomic fetch-and-add operation.
  */
@@ -61,7 +66,7 @@ octeontx_reg_ldadd_u64(void *addr, int64_t off)
 	uint64_t old_val;
 
 	__asm__ volatile(
-		" .cpu		generic+lse\n"
+		__LSE_PREAMBLE
 		" ldadd	%1, %0, [%2]\n"
 		: "=r" (old_val) : "r" (off), "r" (addr) : "memory");
 
@@ -98,12 +103,13 @@ octeontx_reg_lmtst(void *lmtline_va, void *ioreg_va, const uint64_t cmdbuf[],
 
 		/* LDEOR initiates atomic transfer to I/O device */
 		__asm__ volatile(
-			" .cpu		generic+lse\n"
+			__LSE_PREAMBLE
 			" ldeor	xzr, %0, [%1]\n"
 			: "=r" (result) : "r" (ioreg_va) : "memory");
 	} while (!result);
 }
 
+#undef __LSE_PREAMBLE
 #else
 
 static inline uint64_t
diff --git a/dpdk/drivers/net/octeontx/octeontx_ethdev.c b/dpdk/drivers/net/octeontx/octeontx_ethdev.c
index 679803dd4c..e85acdde0a 100644
--- a/dpdk/drivers/net/octeontx/octeontx_ethdev.c
+++ b/dpdk/drivers/net/octeontx/octeontx_ethdev.c
@@ -351,6 +351,10 @@ octeontx_dev_close(struct rte_eth_dev *dev)
 		rte_free(txq);
 	}
 
+	/* Free MAC address table */
+	rte_free(dev->data->mac_addrs);
+	dev->data->mac_addrs = NULL;
+
 	dev->tx_pkt_burst = NULL;
 	dev->rx_pkt_burst = NULL;
 }
@@ -1099,7 +1103,7 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 		octeontx_log_err("eth_dev->port_id (%d) is diff to orig (%d)",
 				data->port_id, nic->port_id);
 		res = -EINVAL;
-		goto err;
+		goto free_mac_addrs;
 	}
 
 	/* Update port_id mac to eth_dev */
@@ -1118,6 +1122,9 @@ octeontx_create(struct rte_vdev_device *dev, int port, uint8_t evdev,
 	rte_eth_dev_probing_finish(eth_dev);
 	return data->port_id;
 
+free_mac_addrs:
+	rte_free(data->mac_addrs);
+	data->mac_addrs = NULL;
 err:
 	if (nic)
 		octeontx_port_close(nic);
diff --git a/dpdk/drivers/net/octeontx2/otx2_ethdev.c b/dpdk/drivers/net/octeontx2/otx2_ethdev.c
index ed329273dc..c952373be4 100644
--- a/dpdk/drivers/net/octeontx2/otx2_ethdev.c
+++ b/dpdk/drivers/net/octeontx2/otx2_ethdev.c
@@ -18,7 +18,8 @@ nix_get_rx_offload_capa(struct otx2_eth_dev *dev)
 {
 	uint64_t capa = NIX_RX_OFFLOAD_CAPA;
 
-	if (otx2_dev_is_vf(dev))
+	if (otx2_dev_is_vf(dev) ||
+	    dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_HIGIG)
 		capa &= ~DEV_RX_OFFLOAD_TIMESTAMP;
 
 	return capa;
@@ -204,7 +205,7 @@ cgx_intlbk_enable(struct otx2_eth_dev *dev, bool en)
 {
 	struct otx2_mbox *mbox = dev->mbox;
 
-	if (otx2_dev_is_vf_or_sdp(dev))
+	if (en && otx2_dev_is_vf_or_sdp(dev))
 		return -ENOTSUP;
 
 	if (en)
@@ -349,10 +350,7 @@ nix_cq_rq_init(struct rte_eth_dev *eth_dev, struct otx2_eth_dev *dev,
 	aq->rq.first_skip = first_skip;
 	aq->rq.later_skip = (sizeof(struct rte_mbuf) / 8);
 	aq->rq.flow_tagw = 32; /* 32-bits */
-	aq->rq.lpb_sizem1 = rte_pktmbuf_data_room_size(mp);
-	aq->rq.lpb_sizem1 += rte_pktmbuf_priv_size(mp);
-	aq->rq.lpb_sizem1 += sizeof(struct rte_mbuf);
-	aq->rq.lpb_sizem1 /= 8;
+	aq->rq.lpb_sizem1 = mp->elt_size / 8;
 	aq->rq.lpb_sizem1 -= 1; /* Expressed in size minus one */
 	aq->rq.ena = 1;
 	aq->rq.pb_caching = 0x2; /* First cache aligned block to LLC */
@@ -570,6 +568,9 @@ otx2_nix_rx_queue_setup(struct rte_eth_dev *eth_dev, uint16_t rq,
 		}
 	}
 
+	/* Setup scatter mode if needed by jumbo */
+	otx2_nix_enable_mseg_on_jumbo(rxq);
+
 	return 0;
 
 free_rxq:
@@ -697,6 +698,33 @@ nix_tx_offload_flags(struct rte_eth_dev *eth_dev)
 	return flags;
 }
 
+void
+otx2_nix_enable_mseg_on_jumbo(struct otx2_eth_rxq *rxq)
+{
+	struct rte_pktmbuf_pool_private *mbp_priv;
+	struct rte_eth_dev *eth_dev;
+	struct otx2_eth_dev *dev;
+	uint32_t buffsz;
+
+	eth_dev = rxq->eth_dev;
+	dev = otx2_eth_pmd_priv(eth_dev);
+
+	/* Get rx buffer size */
+	mbp_priv = rte_mempool_get_priv(rxq->pool);
+	buffsz = mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM;
+
+	if (eth_dev->data->dev_conf.rxmode.max_rx_pkt_len > buffsz) {
+		dev->rx_offloads |= DEV_RX_OFFLOAD_SCATTER;
+		dev->tx_offloads |= DEV_TX_OFFLOAD_MULTI_SEGS;
+
+		/* Setting up the rx[tx]_offload_flags due to change
+		 * in rx[tx]_offloads.
+		 */
+		dev->rx_offload_flags |= nix_rx_offload_flags(eth_dev);
+		dev->tx_offload_flags |= nix_tx_offload_flags(eth_dev);
+	}
+}
+
 static int
 nix_sq_init(struct otx2_eth_txq *txq)
 {
@@ -1114,10 +1142,12 @@ nix_store_queue_cfg_and_then_release(struct rte_eth_dev *eth_dev)
 	txq = (struct otx2_eth_txq **)eth_dev->data->tx_queues;
 	for (i = 0; i < nb_txq; i++) {
 		if (txq[i] == NULL) {
-			otx2_err("txq[%d] is already released", i);
-			goto fail;
+			tx_qconf[i].valid = false;
+			otx2_info("txq[%d] is already released", i);
+			continue;
 		}
 		memcpy(&tx_qconf[i], &txq[i]->qconf, sizeof(*tx_qconf));
+		tx_qconf[i].valid = true;
 		otx2_nix_tx_queue_release(txq[i]);
 		eth_dev->data->tx_queues[i] = NULL;
 	}
@@ -1125,10 +1155,12 @@ nix_store_queue_cfg_and_then_release(struct rte_eth_dev *eth_dev)
 	rxq = (struct otx2_eth_rxq **)eth_dev->data->rx_queues;
 	for (i = 0; i < nb_rxq; i++) {
 		if (rxq[i] == NULL) {
-			otx2_err("rxq[%d] is already released", i);
-			goto fail;
+			rx_qconf[i].valid = false;
+			otx2_info("rxq[%d] is already released", i);
+			continue;
 		}
 		memcpy(&rx_qconf[i], &rxq[i]->qconf, sizeof(*rx_qconf));
+		rx_qconf[i].valid = true;
 		otx2_nix_rx_queue_release(rxq[i]);
 		eth_dev->data->rx_queues[i] = NULL;
 	}
@@ -1138,10 +1170,8 @@ nix_store_queue_cfg_and_then_release(struct rte_eth_dev *eth_dev)
 	return 0;
 
 fail:
-	if (tx_qconf)
-		free(tx_qconf);
-	if (rx_qconf)
-		free(rx_qconf);
+	free(tx_qconf);
+	free(rx_qconf);
 
 	return -ENOMEM;
 }
@@ -1183,6 +1213,8 @@ nix_restore_queue_cfg(struct rte_eth_dev *eth_dev)
 	 * queues are already setup in port_configure().
 	 */
 	for (i = 0; i < nb_txq; i++) {
+		if (!tx_qconf[i].valid)
+			continue;
 		rc = otx2_nix_tx_queue_setup(eth_dev, i, tx_qconf[i].nb_desc,
 					     tx_qconf[i].socket_id,
 					     &tx_qconf[i].conf.tx);
@@ -1198,6 +1230,8 @@ nix_restore_queue_cfg(struct rte_eth_dev *eth_dev)
 	free(tx_qconf); tx_qconf = NULL;
 
 	for (i = 0; i < nb_rxq; i++) {
+		if (!rx_qconf[i].valid)
+			continue;
 		rc = otx2_nix_rx_queue_setup(eth_dev, i, rx_qconf[i].nb_desc,
 					     rx_qconf[i].socket_id,
 					     &rx_qconf[i].conf.rx,
@@ -1641,6 +1675,15 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
 		goto fail_offloads;
 	}
 
+	otx2_nix_err_intr_enb_dis(eth_dev, true);
+	otx2_nix_ras_intr_enb_dis(eth_dev, true);
+
+	if (dev->ptp_en &&
+	    dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_HIGIG) {
+		otx2_err("Both PTP and switch header enabled");
+		goto free_nix_lf;
+	}
+
 	rc = nix_lf_switch_header_type_enable(dev);
 	if (rc) {
 		otx2_err("Failed to enable switch type nix_lf rc=%d", rc);
@@ -1714,6 +1757,12 @@ otx2_nix_configure(struct rte_eth_dev *eth_dev)
 		goto cq_fini;
 	}
 
+	rc = otx2_nix_flow_ctrl_init(eth_dev);
+	if (rc) {
+		otx2_err("Failed to init flow ctrl mode %d", rc);
+		goto cq_fini;
+	}
+
 	rc = otx2_nix_mc_addr_list_install(eth_dev);
 	if (rc < 0) {
 		otx2_err("Failed to install mc address list rc=%d", rc);
diff --git a/dpdk/drivers/net/octeontx2/otx2_ethdev.h b/dpdk/drivers/net/octeontx2/otx2_ethdev.h
index 987e7607c4..6855200fb2 100644
--- a/dpdk/drivers/net/octeontx2/otx2_ethdev.h
+++ b/dpdk/drivers/net/octeontx2/otx2_ethdev.h
@@ -50,6 +50,8 @@
 /* ETH_HLEN+ETH_FCS+2*VLAN_HLEN */
 #define NIX_L2_OVERHEAD \
 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + 8)
+#define NIX_L2_MAX_LEN \
+	(RTE_ETHER_MTU + NIX_L2_OVERHEAD)
 
 /* HW config of frame size doesn't include FCS */
 #define NIX_MAX_HW_FRS			9212
@@ -192,6 +194,7 @@ struct otx2_eth_qconf {
 	void *mempool;
 	uint32_t socket_id;
 	uint16_t nb_desc;
+	uint8_t valid;
 };
 
 struct otx2_fc_info {
@@ -266,6 +269,7 @@ struct otx2_eth_dev {
 	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
 	uint8_t mkex_pfl_name[MKEX_NAME_LEN];
 	uint8_t max_mac_entries;
+	bool dmac_filter_enable;
 	uint8_t lf_tx_stats;
 	uint8_t lf_rx_stats;
 	uint16_t flags;
@@ -422,6 +426,8 @@ int otx2_nix_set_mc_addr_list(struct rte_eth_dev *eth_dev,
 /* MTU */
 int otx2_nix_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu);
 int otx2_nix_recalc_mtu(struct rte_eth_dev *eth_dev);
+void otx2_nix_enable_mseg_on_jumbo(struct otx2_eth_rxq *rxq);
+
 
 /* Link */
 void otx2_nix_toggle_flag_link_cfg(struct otx2_eth_dev *dev, bool set);
@@ -438,6 +444,8 @@ int oxt2_nix_register_cq_irqs(struct rte_eth_dev *eth_dev);
 void otx2_nix_unregister_irqs(struct rte_eth_dev *eth_dev);
 void oxt2_nix_unregister_queue_irqs(struct rte_eth_dev *eth_dev);
 void oxt2_nix_unregister_cq_irqs(struct rte_eth_dev *eth_dev);
+void otx2_nix_err_intr_enb_dis(struct rte_eth_dev *eth_dev, bool enb);
+void otx2_nix_ras_intr_enb_dis(struct rte_eth_dev *eth_dev, bool enb);
 
 int otx2_nix_rx_queue_intr_enable(struct rte_eth_dev *eth_dev,
 				  uint16_t rx_queue_id);
@@ -504,6 +512,8 @@ int otx2_cgx_mac_addr_set(struct rte_eth_dev *eth_dev,
 			  struct rte_ether_addr *addr);
 
 /* Flow Control */
+int otx2_nix_flow_ctrl_init(struct rte_eth_dev *eth_dev);
+
 int otx2_nix_flow_ctrl_get(struct rte_eth_dev *eth_dev,
 			   struct rte_eth_fc_conf *fc_conf);
 
diff --git a/dpdk/drivers/net/octeontx2/otx2_ethdev_irq.c b/dpdk/drivers/net/octeontx2/otx2_ethdev_irq.c
index 2256e40b6f..b121488faf 100644
--- a/dpdk/drivers/net/octeontx2/otx2_ethdev_irq.c
+++ b/dpdk/drivers/net/octeontx2/otx2_ethdev_irq.c
@@ -41,11 +41,11 @@ nix_lf_register_err_irq(struct rte_eth_dev *eth_dev)
 	vec = dev->nix_msixoff + NIX_LF_INT_VEC_ERR_INT;
 
 	/* Clear err interrupt */
-	otx2_write64(~0ull, dev->base + NIX_LF_ERR_INT_ENA_W1C);
+	otx2_nix_err_intr_enb_dis(eth_dev, false);
 	/* Set used interrupt vectors */
 	rc = otx2_register_irq(handle, nix_lf_err_irq, eth_dev, vec);
 	/* Enable all dev interrupt except for RQ_DISABLED */
-	otx2_write64(~BIT_ULL(11), dev->base + NIX_LF_ERR_INT_ENA_W1S);
+	otx2_nix_err_intr_enb_dis(eth_dev, true);
 
 	return rc;
 }
@@ -61,7 +61,7 @@ nix_lf_unregister_err_irq(struct rte_eth_dev *eth_dev)
 	vec = dev->nix_msixoff + NIX_LF_INT_VEC_ERR_INT;
 
 	/* Clear err interrupt */
-	otx2_write64(~0ull, dev->base + NIX_LF_ERR_INT_ENA_W1C);
+	otx2_nix_err_intr_enb_dis(eth_dev, false);
 	otx2_unregister_irq(handle, nix_lf_err_irq, eth_dev, vec);
 }
 
@@ -97,11 +97,11 @@ nix_lf_register_ras_irq(struct rte_eth_dev *eth_dev)
 	vec = dev->nix_msixoff + NIX_LF_INT_VEC_POISON;
 
 	/* Clear err interrupt */
-	otx2_write64(~0ull, dev->base + NIX_LF_RAS_ENA_W1C);
+	otx2_nix_ras_intr_enb_dis(eth_dev, false);
 	/* Set used interrupt vectors */
 	rc = otx2_register_irq(handle, nix_lf_ras_irq, eth_dev, vec);
 	/* Enable dev interrupt */
-	otx2_write64(~0ull, dev->base + NIX_LF_RAS_ENA_W1S);
+	otx2_nix_ras_intr_enb_dis(eth_dev, true);
 
 	return rc;
 }
@@ -117,7 +117,7 @@ nix_lf_unregister_ras_irq(struct rte_eth_dev *eth_dev)
 	vec = dev->nix_msixoff + NIX_LF_INT_VEC_POISON;
 
 	/* Clear err interrupt */
-	otx2_write64(~0ull, dev->base + NIX_LF_RAS_ENA_W1C);
+	otx2_nix_ras_intr_enb_dis(eth_dev, false);
 	otx2_unregister_irq(handle, nix_lf_ras_irq, eth_dev, vec);
 }
 
@@ -466,3 +466,29 @@ otx2_nix_rx_queue_intr_disable(struct rte_eth_dev *eth_dev,
 
 	return 0;
 }
+
+void
+otx2_nix_err_intr_enb_dis(struct rte_eth_dev *eth_dev, bool enb)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+	/* Enable all nix lf error interrupts except
+	 * RQ_DISABLED and CQ_DISABLED.
+	 */
+	if (enb)
+		otx2_write64(~(BIT_ULL(11) | BIT_ULL(24)),
+			     dev->base + NIX_LF_ERR_INT_ENA_W1S);
+	else
+		otx2_write64(~0ull, dev->base + NIX_LF_ERR_INT_ENA_W1C);
+}
+
+void
+otx2_nix_ras_intr_enb_dis(struct rte_eth_dev *eth_dev, bool enb)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+	if (enb)
+		otx2_write64(~0ull, dev->base + NIX_LF_RAS_ENA_W1S);
+	else
+		otx2_write64(~0ull, dev->base + NIX_LF_RAS_ENA_W1C);
+}
diff --git a/dpdk/drivers/net/octeontx2/otx2_ethdev_ops.c b/dpdk/drivers/net/octeontx2/otx2_ethdev_ops.c
index 8f1635dbab..beb4f58148 100644
--- a/dpdk/drivers/net/octeontx2/otx2_ethdev_ops.c
+++ b/dpdk/drivers/net/octeontx2/otx2_ethdev_ops.c
@@ -58,7 +58,7 @@ otx2_nix_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
 	if (rc)
 		return rc;
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > NIX_L2_MAX_LEN)
 		dev->rx_offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
 		dev->rx_offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
@@ -72,22 +72,15 @@ otx2_nix_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
 int
 otx2_nix_recalc_mtu(struct rte_eth_dev *eth_dev)
 {
-	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 	struct rte_eth_dev_data *data = eth_dev->data;
-	struct rte_pktmbuf_pool_private *mbp_priv;
 	struct otx2_eth_rxq *rxq;
-	uint32_t buffsz;
 	uint16_t mtu;
 	int rc;
 
-	/* Get rx buffer size */
 	rxq = data->rx_queues[0];
-	mbp_priv = rte_mempool_get_priv(rxq->pool);
-	buffsz = mbp_priv->mbuf_data_room_size - RTE_PKTMBUF_HEADROOM;
 
 	/* Setup scatter mode if needed by jumbo */
-	if (data->dev_conf.rxmode.max_rx_pkt_len > buffsz)
-		dev->rx_offloads |= DEV_RX_OFFLOAD_SCATTER;
+	otx2_nix_enable_mseg_on_jumbo(rxq);
 
 	/* Setup MTU based on max_rx_pkt_len */
 	mtu = data->dev_conf.rxmode.max_rx_pkt_len - NIX_L2_OVERHEAD;
@@ -148,8 +141,10 @@ otx2_nix_promisc_enable(struct rte_eth_dev *eth_dev)
 int
 otx2_nix_promisc_disable(struct rte_eth_dev *eth_dev)
 {
-	otx2_nix_promisc_config(eth_dev, 0);
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	otx2_nix_promisc_config(eth_dev, dev->dmac_filter_enable);
 	nix_cgx_promisc_config(eth_dev, 0);
+	dev->dmac_filter_enable = false;
 
 	return 0;
 }
diff --git a/dpdk/drivers/net/octeontx2/otx2_flow.c b/dpdk/drivers/net/octeontx2/otx2_flow.c
index f1fb9f9884..c9886c9705 100644
--- a/dpdk/drivers/net/octeontx2/otx2_flow.c
+++ b/dpdk/drivers/net/octeontx2/otx2_flow.c
@@ -269,6 +269,8 @@ flow_program_rss_action(struct rte_eth_dev *eth_dev,
 			if (rc)
 				return rc;
 
+			flow->npc_action &= (~(0xfULL));
+			flow->npc_action |= NIX_RX_ACTIONOP_RSS;
 			flow->npc_action |=
 				((uint64_t)(alg_idx & NIX_RSS_ACT_ALG_MASK) <<
 				 NIX_RSS_ACT_ALG_OFFSET) |
diff --git a/dpdk/drivers/net/octeontx2/otx2_flow_ctrl.c b/dpdk/drivers/net/octeontx2/otx2_flow_ctrl.c
index c6d7b1971a..76bf481001 100644
--- a/dpdk/drivers/net/octeontx2/otx2_flow_ctrl.c
+++ b/dpdk/drivers/net/octeontx2/otx2_flow_ctrl.c
@@ -200,19 +200,18 @@ int
 otx2_nix_update_flow_ctrl_mode(struct rte_eth_dev *eth_dev)
 {
 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	struct otx2_fc_info *fc = &dev->fc_info;
 	struct rte_eth_fc_conf fc_conf;
 
 	if (otx2_dev_is_lbk(dev) || otx2_dev_is_sdp(dev))
 		return 0;
 
 	memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
-	/* Both Rx & Tx flow ctrl get enabled(RTE_FC_FULL) in HW
-	 * by AF driver, update those info in PMD structure.
-	 */
-	otx2_nix_flow_ctrl_get(eth_dev, &fc_conf);
+	fc_conf.mode = fc->mode;
 
 	/* To avoid Link credit deadlock on Ax, disable Tx FC if it's enabled */
 	if (otx2_dev_is_Ax(dev) &&
+	    (dev->npc_flow.switch_header_type != OTX2_PRIV_FLAGS_HIGIG) &&
 	    (fc_conf.mode == RTE_FC_FULL || fc_conf.mode == RTE_FC_RX_PAUSE)) {
 		fc_conf.mode =
 				(fc_conf.mode == RTE_FC_FULL ||
@@ -222,3 +221,32 @@ otx2_nix_update_flow_ctrl_mode(struct rte_eth_dev *eth_dev)
 
 	return otx2_nix_flow_ctrl_set(eth_dev, &fc_conf);
 }
+
+int
+otx2_nix_flow_ctrl_init(struct rte_eth_dev *eth_dev)
+{
+	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	struct otx2_fc_info *fc = &dev->fc_info;
+	struct rte_eth_fc_conf fc_conf;
+	int rc;
+
+	if (otx2_dev_is_lbk(dev) || otx2_dev_is_sdp(dev))
+		return 0;
+
+	memset(&fc_conf, 0, sizeof(struct rte_eth_fc_conf));
+	/* Both Rx & Tx flow ctrl get enabled(RTE_FC_FULL) in HW
+	 * by AF driver, update those info in PMD structure.
+	 */
+	rc = otx2_nix_flow_ctrl_get(eth_dev, &fc_conf);
+	if (rc)
+		goto exit;
+
+	fc->mode = fc_conf.mode;
+	fc->rx_pause = (fc_conf.mode == RTE_FC_FULL) ||
+			(fc_conf.mode == RTE_FC_RX_PAUSE);
+	fc->tx_pause = (fc_conf.mode == RTE_FC_FULL) ||
+			(fc_conf.mode == RTE_FC_TX_PAUSE);
+
+exit:
+	return rc;
+}
diff --git a/dpdk/drivers/net/octeontx2/otx2_flow_parse.c b/dpdk/drivers/net/octeontx2/otx2_flow_parse.c
index 2d9a5857c0..7a7cb29fbd 100644
--- a/dpdk/drivers/net/octeontx2/otx2_flow_parse.c
+++ b/dpdk/drivers/net/octeontx2/otx2_flow_parse.c
@@ -1034,7 +1034,10 @@ otx2_flow_parse_actions(struct rte_eth_dev *dev,
 
 set_pf_func:
 	/* Ideally AF must ensure that correct pf_func is set */
-	flow->npc_action |= (uint64_t)pf_func << 4;
+	if (attr->egress)
+		flow->npc_action |= (uint64_t)pf_func << 48;
+	else
+		flow->npc_action |= (uint64_t)pf_func << 4;
 
 	return 0;
 
diff --git a/dpdk/drivers/net/octeontx2/otx2_flow_utils.c b/dpdk/drivers/net/octeontx2/otx2_flow_utils.c
index 14625c9ad1..1adeff2563 100644
--- a/dpdk/drivers/net/octeontx2/otx2_flow_utils.c
+++ b/dpdk/drivers/net/octeontx2/otx2_flow_utils.c
@@ -940,7 +940,7 @@ otx2_flow_mcam_alloc_and_write(struct rte_flow *flow, struct otx2_mbox *mbox,
 		req->entry_data.kw[0] |= flow_info->channel;
 		req->entry_data.kw_mask[0] |=  (BIT_ULL(12) - 1);
 	} else {
-		uint16_t pf_func = (flow->npc_action >> 4) & 0xffff;
+		uint16_t pf_func = (flow->npc_action >> 48) & 0xffff;
 
 		pf_func = htons(pf_func);
 		req->entry_data.kw[0] |= ((uint64_t)pf_func << 32);
diff --git a/dpdk/drivers/net/octeontx2/otx2_link.c b/dpdk/drivers/net/octeontx2/otx2_link.c
index f5679b06e7..4128f56d90 100644
--- a/dpdk/drivers/net/octeontx2/otx2_link.c
+++ b/dpdk/drivers/net/octeontx2/otx2_link.c
@@ -82,32 +82,57 @@ otx2_eth_dev_link_status_update(struct otx2_dev *dev,
 	_rte_eth_dev_callback_process(eth_dev, RTE_ETH_EVENT_INTR_LSC, NULL);
 }
 
+static int
+lbk_link_update(struct rte_eth_link *link)
+{
+	link->link_status = ETH_LINK_UP;
+	link->link_speed = ETH_SPEED_NUM_100G;
+	link->link_autoneg = ETH_LINK_FIXED;
+	link->link_duplex = ETH_LINK_FULL_DUPLEX;
+	return 0;
+}
+
+static int
+cgx_link_update(struct otx2_eth_dev *dev, struct rte_eth_link *link)
+{
+	struct otx2_mbox *mbox = dev->mbox;
+	struct cgx_link_info_msg *rsp;
+	int rc;
+	otx2_mbox_alloc_msg_cgx_get_linkinfo(mbox);
+	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	if (rc)
+		return rc;
+
+	link->link_status = rsp->link_info.link_up;
+	link->link_speed = rsp->link_info.speed;
+	link->link_autoneg = ETH_LINK_AUTONEG;
+
+	if (rsp->link_info.full_duplex)
+		link->link_duplex = rsp->link_info.full_duplex;
+	return 0;
+}
+
 int
 otx2_nix_link_update(struct rte_eth_dev *eth_dev, int wait_to_complete)
 {
 	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
-	struct otx2_mbox *mbox = dev->mbox;
-	struct cgx_link_info_msg *rsp;
 	struct rte_eth_link link;
 	int rc;
 
 	RTE_SET_USED(wait_to_complete);
+	memset(&link, 0, sizeof(struct rte_eth_link));
 
-	if (otx2_dev_is_lbk(dev) || otx2_dev_is_sdp(dev))
+	if (otx2_dev_is_sdp(dev))
 		return 0;
 
-	otx2_mbox_alloc_msg_cgx_get_linkinfo(mbox);
-	rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+	if (otx2_dev_is_lbk(dev))
+		rc = lbk_link_update(&link);
+	else
+		rc = cgx_link_update(dev, &link);
+
 	if (rc)
 		return rc;
 
-	link.link_status = rsp->link_info.link_up;
-	link.link_speed = rsp->link_info.speed;
-	link.link_autoneg = ETH_LINK_AUTONEG;
-
-	if (rsp->link_info.full_duplex)
-		link.link_duplex = rsp->link_info.full_duplex;
-
 	return rte_eth_linkstatus_set(eth_dev, &link);
 }
 
diff --git a/dpdk/drivers/net/octeontx2/otx2_lookup.c b/dpdk/drivers/net/octeontx2/otx2_lookup.c
index bcf2ff4e8f..5685571166 100644
--- a/dpdk/drivers/net/octeontx2/otx2_lookup.c
+++ b/dpdk/drivers/net/octeontx2/otx2_lookup.c
@@ -17,7 +17,7 @@
 const uint32_t *
 otx2_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
 {
-	struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+	RTE_SET_USED(eth_dev);
 
 	static const uint32_t ptypes[] = {
 		RTE_PTYPE_L2_ETHER_QINQ, /* LB */
@@ -56,10 +56,7 @@ otx2_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
 		RTE_PTYPE_UNKNOWN,
 	};
 
-	if (dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)
-		return ptypes;
-	else
-		return NULL;
+	return ptypes;
 }
 
 int
diff --git a/dpdk/drivers/net/octeontx2/otx2_mac.c b/dpdk/drivers/net/octeontx2/otx2_mac.c
index 262d185e54..49a700ca1d 100644
--- a/dpdk/drivers/net/octeontx2/otx2_mac.c
+++ b/dpdk/drivers/net/octeontx2/otx2_mac.c
@@ -76,6 +76,8 @@ otx2_nix_mac_addr_add(struct rte_eth_dev *eth_dev, struct rte_ether_addr *addr,
 
 	/* Enable promiscuous mode at NIX level */
 	otx2_nix_promisc_config(eth_dev, 1);
+	dev->dmac_filter_enable = true;
+	eth_dev->data->promiscuous = 0;
 
 done:
 	return rc;
diff --git a/dpdk/drivers/net/octeontx2/otx2_ptp.c b/dpdk/drivers/net/octeontx2/otx2_ptp.c
index f34b9339c4..ae5a2b7cd1 100644
--- a/dpdk/drivers/net/octeontx2/otx2_ptp.c
+++ b/dpdk/drivers/net/octeontx2/otx2_ptp.c
@@ -221,6 +221,11 @@ otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev)
 		return -EINVAL;
 	}
 
+	if (dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_HIGIG) {
+		otx2_err("Both PTP and switch header enabled");
+		return -EINVAL;
+	}
+
 	/* Allocating a iova address for tx tstamp */
 	const struct rte_memzone *ts;
 	ts = rte_eth_dma_zone_reserve(eth_dev, "otx2_ts",
diff --git a/dpdk/drivers/net/octeontx2/otx2_rss.c b/dpdk/drivers/net/octeontx2/otx2_rss.c
index bc7b64387a..d80579725a 100644
--- a/dpdk/drivers/net/octeontx2/otx2_rss.c
+++ b/dpdk/drivers/net/octeontx2/otx2_rss.c
@@ -341,7 +341,7 @@ otx2_nix_rss_config(struct rte_eth_dev *eth_dev)
 	int rc;
 
 	/* Skip further configuration if selected mode is not RSS */
-	if (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS)
+	if (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS || !qcnt)
 		return 0;
 
 	/* Update default RSS key and cfg */
diff --git a/dpdk/drivers/net/octeontx2/otx2_rx.c b/dpdk/drivers/net/octeontx2/otx2_rx.c
index 48565db030..23d5c30b59 100644
--- a/dpdk/drivers/net/octeontx2/otx2_rx.c
+++ b/dpdk/drivers/net/octeontx2/otx2_rx.c
@@ -273,6 +273,12 @@ nix_recv_pkts_vector(void *rx_queue, struct rte_mbuf **rx_pkts,
 		vst1q_u64((uint64_t *)mbuf2->rearm_data, rearm2);
 		vst1q_u64((uint64_t *)mbuf3->rearm_data, rearm3);
 
+		/* Update that no more segments */
+		mbuf0->next = NULL;
+		mbuf1->next = NULL;
+		mbuf2->next = NULL;
+		mbuf3->next = NULL;
+
 		/* Store the mbufs to rx_pkts */
 		vst1q_u64((uint64_t *)&rx_pkts[packets], mbuf01);
 		vst1q_u64((uint64_t *)&rx_pkts[packets + 2], mbuf23);
diff --git a/dpdk/drivers/net/octeontx2/otx2_rx.h b/dpdk/drivers/net/octeontx2/otx2_rx.h
index 351ad0fcb4..1863bfde72 100644
--- a/dpdk/drivers/net/octeontx2/otx2_rx.h
+++ b/dpdk/drivers/net/octeontx2/otx2_rx.h
@@ -188,6 +188,7 @@ nix_cqe_xtract_mseg(const struct nix_rx_parse_s *rx,
 			iova_list = (const rte_iova_t *)(iova_list + 1);
 		}
 	}
+	mbuf->next = NULL;
 }
 
 static __rte_always_inline void
@@ -235,10 +236,12 @@ otx2_nix_cqe_to_mbuf(const struct nix_cqe_hdr_s *cq, const uint32_t tag,
 	*(uint64_t *)(&mbuf->rearm_data) = val;
 	mbuf->pkt_len = len;
 
-	if (flag & NIX_RX_MULTI_SEG_F)
+	if (flag & NIX_RX_MULTI_SEG_F) {
 		nix_cqe_xtract_mseg(rx, mbuf, val);
-	else
+	} else {
 		mbuf->data_len = len;
+		mbuf->next = NULL;
+	}
 }
 
 #define CKSUM_F NIX_RX_OFFLOAD_CHECKSUM_F
diff --git a/dpdk/drivers/net/octeontx2/otx2_vlan.c b/dpdk/drivers/net/octeontx2/otx2_vlan.c
index 322a565b3e..7357b06695 100644
--- a/dpdk/drivers/net/octeontx2/otx2_vlan.c
+++ b/dpdk/drivers/net/octeontx2/otx2_vlan.c
@@ -717,11 +717,6 @@ otx2_nix_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 
 	rxmode = &eth_dev->data->dev_conf.rxmode;
 
-	if (mask & ETH_VLAN_EXTEND_MASK) {
-		otx2_err("Extend offload not supported");
-		return -ENOTSUP;
-	}
-
 	if (mask & ETH_VLAN_STRIP_MASK) {
 		if (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) {
 			offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
diff --git a/dpdk/drivers/net/pcap/rte_eth_pcap.c b/dpdk/drivers/net/pcap/rte_eth_pcap.c
index aa7ef6fdbc..f4afe67116 100644
--- a/dpdk/drivers/net/pcap/rte_eth_pcap.c
+++ b/dpdk/drivers/net/pcap/rte_eth_pcap.c
@@ -377,7 +377,7 @@ eth_tx_drop(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		return 0;
 
 	for (i = 0; i < nb_pkts; i++) {
-		tx_bytes += bufs[i]->data_len;
+		tx_bytes += bufs[i]->pkt_len;
 		rte_pktmbuf_free(bufs[i]);
 	}
 
@@ -723,6 +723,17 @@ eth_stats_reset(struct rte_eth_dev *dev)
 	return 0;
 }
 
+static inline void
+infinite_rx_ring_free(struct rte_ring *pkts)
+{
+	struct rte_mbuf *bufs;
+
+	while (!rte_ring_dequeue(pkts, (void **)&bufs))
+		rte_pktmbuf_free(bufs);
+
+	rte_ring_free(pkts);
+}
+
 static void
 eth_dev_close(struct rte_eth_dev *dev)
 {
@@ -733,13 +744,15 @@ eth_dev_close(struct rte_eth_dev *dev)
 	if (internals->infinite_rx) {
 		for (i = 0; i < dev->data->nb_rx_queues; i++) {
 			struct pcap_rx_queue *pcap_q = &internals->rx_queue[i];
-			struct rte_mbuf *pcap_buf;
 
-			while (!rte_ring_dequeue(pcap_q->pkts,
-					(void **)&pcap_buf))
-				rte_pktmbuf_free(pcap_buf);
+			/*
+			 * 'pcap_q->pkts' can be NULL if 'eth_dev_close()'
+			 * called before 'eth_rx_queue_setup()' has been called
+			 */
+			if (pcap_q->pkts == NULL)
+				continue;
 
-			rte_ring_free(pcap_q->pkts);
+			infinite_rx_ring_free(pcap_q->pkts);
 		}
 	}
 
@@ -803,21 +816,25 @@ eth_rx_queue_setup(struct rte_eth_dev *dev,
 		while (eth_pcap_rx(pcap_q, bufs, 1)) {
 			/* Check for multiseg mbufs. */
 			if (bufs[0]->nb_segs != 1) {
-				rte_pktmbuf_free(*bufs);
-
-				while (!rte_ring_dequeue(pcap_q->pkts,
-						(void **)bufs))
-					rte_pktmbuf_free(*bufs);
-
-				rte_ring_free(pcap_q->pkts);
-				PMD_LOG(ERR, "Multiseg mbufs are not supported in infinite_rx "
-						"mode.");
+				infinite_rx_ring_free(pcap_q->pkts);
+				PMD_LOG(ERR,
+					"Multiseg mbufs are not supported in infinite_rx mode.");
 				return -EINVAL;
 			}
 
 			rte_ring_enqueue_bulk(pcap_q->pkts,
 					(void * const *)bufs, 1, NULL);
 		}
+
+		if (rte_ring_count(pcap_q->pkts) < pcap_pkt_count) {
+			infinite_rx_ring_free(pcap_q->pkts);
+			PMD_LOG(ERR,
+				"Not enough mbufs to accommodate packets in pcap file. "
+				"At least %" PRIu64 " mbufs per queue is required.",
+				pcap_pkt_count);
+			return -EINVAL;
+		}
+
 		/*
 		 * Reset the stats for this queue since eth_pcap_rx calls above
 		 * didn't result in the application receiving packets.
@@ -1291,9 +1308,8 @@ eth_from_pcaps(struct rte_vdev_device *vdev,
 
 		/* phy_mac arg is applied only only if "iface" devarg is provided */
 		if (rx_queues->phy_mac) {
-			int ret = eth_pcap_update_mac(rx_queues->queue[0].name,
-					eth_dev, vdev->device.numa_node);
-			if (ret == 0)
+			if (eth_pcap_update_mac(rx_queues->queue[0].name,
+					eth_dev, vdev->device.numa_node) == 0)
 				internals->phy_mac = 1;
 		}
 	}
@@ -1398,7 +1414,8 @@ pmd_pcap_probe(struct rte_vdev_device *dev)
 	devargs_all.is_rx_pcap =
 		rte_kvargs_count(kvlist, ETH_PCAP_RX_PCAP_ARG) ? 1 : 0;
 	devargs_all.is_rx_iface =
-		rte_kvargs_count(kvlist, ETH_PCAP_RX_IFACE_ARG) ? 1 : 0;
+		(rte_kvargs_count(kvlist, ETH_PCAP_RX_IFACE_ARG) +
+		 rte_kvargs_count(kvlist, ETH_PCAP_RX_IFACE_IN_ARG)) ? 1 : 0;
 	pcaps.num_of_queue = 0;
 
 	devargs_all.is_tx_pcap =
diff --git a/dpdk/drivers/net/pfe/pfe_ethdev.c b/dpdk/drivers/net/pfe/pfe_ethdev.c
index 9403478198..5a231918a1 100644
--- a/dpdk/drivers/net/pfe/pfe_ethdev.c
+++ b/dpdk/drivers/net/pfe/pfe_ethdev.c
@@ -13,7 +13,7 @@
 #include "pfe_logs.h"
 #include "pfe_mod.h"
 
-#define PFE_MAX_MACS 1 /*we can support upto 4 MACs per IF*/
+#define PFE_MAX_MACS 1 /* we can support up to 4 MACs per IF */
 #define PFE_VDEV_GEM_ID_ARG	"intf"
 
 struct pfe_vdev_init_params {
@@ -396,7 +396,6 @@ pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe)
 	/* Close the device file for link status */
 	pfe_eth_close_cdev(dev->data->dev_private);
 
-	rte_free(dev->data->mac_addrs);
 	rte_eth_dev_release_port(dev);
 	pfe->nb_devs--;
 }
@@ -430,9 +429,6 @@ static int
 pfe_eth_info(struct rte_eth_dev *dev,
 		struct rte_eth_dev_info *dev_info)
 {
-	struct pfe_eth_priv_s *internals = dev->data->dev_private;
-
-	dev_info->if_index = internals->id;
 	dev_info->max_mac_addrs = PFE_MAX_MACS;
 	dev_info->max_rx_queues = dev->data->nb_rx_queues;
 	dev_info->max_tx_queues = dev->data->nb_tx_queues;
@@ -990,7 +986,7 @@ pmd_pfe_probe(struct rte_vdev_device *vdev)
 	if (rc < 0)
 		return -EINVAL;
 
-	RTE_LOG(INFO, PMD, "Initializing pmd_pfe for %s Given gem-id %d\n",
+	PFE_PMD_LOG(INFO, "Initializing pmd_pfe for %s Given gem-id %d",
 		name, init_params.gem_id);
 
 	if (g_pfe) {
@@ -1118,7 +1114,7 @@ pmd_pfe_probe(struct rte_vdev_device *vdev)
 	else
 		gem_id = init_params.gem_id;
 
-	RTE_LOG(INFO, PMD, "Init pmd_pfe for %s gem-id %d(given =%d)\n",
+	PFE_PMD_LOG(INFO, "Init pmd_pfe for %s gem-id %d(given =%d)",
 		name, gem_id, init_params.gem_id);
 
 	rc = pfe_eth_init(vdev, g_pfe, gem_id);
diff --git a/dpdk/drivers/net/qede/base/bcm_osal.h b/dpdk/drivers/net/qede/base/bcm_osal.h
index 0f09557cf0..d9f507f233 100644
--- a/dpdk/drivers/net/qede/base/bcm_osal.h
+++ b/dpdk/drivers/net/qede/base/bcm_osal.h
@@ -81,9 +81,8 @@ typedef int bool;
 
 #define DELAY(x) rte_delay_us(x)
 #define usec_delay(x) DELAY(x)
-#define msec_delay(x) DELAY(1000 * (x))
 #define OSAL_UDELAY(time) usec_delay(time)
-#define OSAL_MSLEEP(time) msec_delay(time)
+#define OSAL_MSLEEP(time) rte_delay_us_sleep(1000 * (time))
 
 /* Memory allocations and deallocations */
 
diff --git a/dpdk/drivers/net/qede/base/ecore_dev.c b/dpdk/drivers/net/qede/base/ecore_dev.c
index 9d1db14590..86ecfb2690 100644
--- a/dpdk/drivers/net/qede/base/ecore_dev.c
+++ b/dpdk/drivers/net/qede/base/ecore_dev.c
@@ -5253,7 +5253,6 @@ static void ecore_emul_hw_info_port_num(struct ecore_hwfn *p_hwfn,
 
 	/* MISCS_REG_ECO_RESERVED[15:12]: num of ports in an engine */
 	eco_reserved = ecore_rd(p_hwfn, p_ptt, MISCS_REG_ECO_RESERVED);
-
 	switch ((eco_reserved & 0xf000) >> 12) {
 		case 1:
 			p_dev->num_ports_in_engine = 1;
@@ -5268,7 +5267,7 @@ static void ecore_emul_hw_info_port_num(struct ecore_hwfn *p_hwfn,
 			DP_NOTICE(p_hwfn, false,
 			  "Emulation: Unknown port mode [ECO_RESERVED 0x%08x]\n",
 			  eco_reserved);
-		p_dev->num_ports_in_engine = 2; /* Default to something */
+		p_dev->num_ports_in_engine = 1; /* Default to something */
 		break;
 		}
 
@@ -5281,8 +5280,8 @@ static void ecore_emul_hw_info_port_num(struct ecore_hwfn *p_hwfn,
 static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
 				   struct ecore_ptt *p_ptt)
 {
+	u32 addr, global_offsize, global_addr, port_mode;
 	struct ecore_dev *p_dev = p_hwfn->p_dev;
-	u32 addr, global_offsize, global_addr;
 
 #ifndef ASIC_ONLY
 	if (CHIP_REV_IS_TEDIBEAR(p_dev)) {
@@ -5304,15 +5303,32 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
 		return;
 	}
 
-		addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
-					    PUBLIC_GLOBAL);
-		global_offsize = ecore_rd(p_hwfn, p_ptt, addr);
-		global_addr = SECTION_ADDR(global_offsize, 0);
-		addr = global_addr + OFFSETOF(struct public_global, max_ports);
-		p_dev->num_ports = (u8)ecore_rd(p_hwfn, p_ptt, addr);
+	/* Determine the number of ports per engine */
+	port_mode = ecore_rd(p_hwfn, p_ptt, MISC_REG_PORT_MODE);
+	switch (port_mode) {
+	case 0x0:
+		p_dev->num_ports_in_engine = 1;
+		break;
+	case 0x1:
+		p_dev->num_ports_in_engine = 2;
+		break;
+	case 0x2:
+		p_dev->num_ports_in_engine = 4;
+		break;
+	default:
+		DP_NOTICE(p_hwfn, false, "Unknown port mode 0x%08x\n",
+			  port_mode);
+		p_dev->num_ports_in_engine = 1; /* Default to something */
+		break;
+	}
 
-	p_dev->num_ports_in_engine = p_dev->num_ports >>
-				     (ecore_device_num_engines(p_dev) - 1);
+	/* Get the total number of ports of the device */
+	addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
+				    PUBLIC_GLOBAL);
+	global_offsize = ecore_rd(p_hwfn, p_ptt, addr);
+	global_addr = SECTION_ADDR(global_offsize, 0);
+	addr = global_addr + OFFSETOF(struct public_global, max_ports);
+	p_dev->num_ports = (u8)ecore_rd(p_hwfn, p_ptt, addr);
 }
 
 static void ecore_mcp_get_eee_caps(struct ecore_hwfn *p_hwfn,
@@ -5601,7 +5617,7 @@ ecore_hw_prepare_single(struct ecore_hwfn *p_hwfn, void OSAL_IOMEM *p_regview,
 	p_hwfn->db_phys_addr = db_phys_addr;
 
 	if (IS_VF(p_dev))
-		return ecore_vf_hw_prepare(p_hwfn);
+		return ecore_vf_hw_prepare(p_hwfn, p_params);
 
 	/* Validate that chip access is feasible */
 	if (REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR) == 0xffffffff) {
diff --git a/dpdk/drivers/net/qede/base/ecore_dev_api.h b/dpdk/drivers/net/qede/base/ecore_dev_api.h
index 4d5cc1a0fa..5ea8427a07 100644
--- a/dpdk/drivers/net/qede/base/ecore_dev_api.h
+++ b/dpdk/drivers/net/qede/base/ecore_dev_api.h
@@ -277,6 +277,9 @@ struct ecore_hw_prepare_params {
 
 	/* Indicates whether this PF serves a storage target */
 	bool b_is_target;
+
+	/* retry count for VF acquire on channel timeout */
+	u8 acquire_retry_cnt;
 };
 
 /**
diff --git a/dpdk/drivers/net/qede/base/ecore_iov_api.h b/dpdk/drivers/net/qede/base/ecore_iov_api.h
index c998dbf8d5..5450018121 100644
--- a/dpdk/drivers/net/qede/base/ecore_iov_api.h
+++ b/dpdk/drivers/net/qede/base/ecore_iov_api.h
@@ -51,6 +51,7 @@ enum ecore_iov_pf_to_vf_status {
 	PFVF_STATUS_NO_RESOURCE,
 	PFVF_STATUS_FORCED,
 	PFVF_STATUS_MALICIOUS,
+	PFVF_STATUS_ACQUIRED,
 };
 
 struct ecore_mcp_link_params;
diff --git a/dpdk/drivers/net/qede/base/ecore_sriov.c b/dpdk/drivers/net/qede/base/ecore_sriov.c
index deee04ac4b..6633d6b42e 100644
--- a/dpdk/drivers/net/qede/base/ecore_sriov.c
+++ b/dpdk/drivers/net/qede/base/ecore_sriov.c
@@ -61,6 +61,39 @@ const char *qede_ecore_channel_tlvs_string[] = {
 	"CHANNEL_TLV_COALESCE_READ",
 	"CHANNEL_TLV_BULLETIN_UPDATE_MAC",
 	"CHANNEL_TLV_UPDATE_MTU",
+	"CHANNEL_TLV_RDMA_ACQUIRE",
+	"CHANNEL_TLV_RDMA_START",
+	"CHANNEL_TLV_RDMA_STOP",
+	"CHANNEL_TLV_RDMA_ADD_USER",
+	"CHANNEL_TLV_RDMA_REMOVE_USER",
+	"CHANNEL_TLV_RDMA_QUERY_COUNTERS",
+	"CHANNEL_TLV_RDMA_ALLOC_TID",
+	"CHANNEL_TLV_RDMA_REGISTER_TID",
+	"CHANNEL_TLV_RDMA_DEREGISTER_TID",
+	"CHANNEL_TLV_RDMA_FREE_TID",
+	"CHANNEL_TLV_RDMA_CREATE_CQ",
+	"CHANNEL_TLV_RDMA_RESIZE_CQ",
+	"CHANNEL_TLV_RDMA_DESTROY_CQ",
+	"CHANNEL_TLV_RDMA_CREATE_QP",
+	"CHANNEL_TLV_RDMA_MODIFY_QP",
+	"CHANNEL_TLV_RDMA_QUERY_QP",
+	"CHANNEL_TLV_RDMA_DESTROY_QP",
+	"CHANNEL_TLV_RDMA_CREATE_SRQ",
+	"CHANNEL_TLV_RDMA_MODIFY_SRQ",
+	"CHANNEL_TLV_RDMA_DESTROY_SRQ",
+	"CHANNEL_TLV_RDMA_QUERY_PORT",
+	"CHANNEL_TLV_RDMA_QUERY_DEVICE",
+	"CHANNEL_TLV_RDMA_IWARP_CONNECT",
+	"CHANNEL_TLV_RDMA_IWARP_ACCEPT",
+	"CHANNEL_TLV_RDMA_IWARP_CREATE_LISTEN",
+	"CHANNEL_TLV_RDMA_IWARP_DESTROY_LISTEN",
+	"CHANNEL_TLV_RDMA_IWARP_PAUSE_LISTEN",
+	"CHANNEL_TLV_RDMA_IWARP_REJECT",
+	"CHANNEL_TLV_RDMA_IWARP_SEND_RTR",
+	"CHANNEL_TLV_ESTABLISH_LL2_CONN",
+	"CHANNEL_TLV_TERMINATE_LL2_CONN",
+	"CHANNEL_TLV_ASYNC_EVENT",
+	"CHANNEL_TLV_SOFT_FLR",
 	"CHANNEL_TLV_MAX"
 };
 
@@ -4042,7 +4075,7 @@ ecore_iov_execute_vf_flr_cleanup(struct ecore_hwfn *p_hwfn,
 		rc = ecore_iov_enable_vf_access(p_hwfn, p_ptt, p_vf);
 		if (rc) {
 			/* TODO - again, a mess... */
-			DP_ERR(p_hwfn, "Failed to re-enable VF[%d] acces\n",
+			DP_ERR(p_hwfn, "Failed to re-enable VF[%d] access\n",
 			       vfid);
 			return rc;
 		}
diff --git a/dpdk/drivers/net/qede/base/ecore_vf.c b/dpdk/drivers/net/qede/base/ecore_vf.c
index 24846cfb51..0e5b7d5eb3 100644
--- a/dpdk/drivers/net/qede/base/ecore_vf.c
+++ b/dpdk/drivers/net/qede/base/ecore_vf.c
@@ -226,7 +226,6 @@ enum _ecore_status_t ecore_vf_pf_release(struct ecore_hwfn *p_hwfn)
 	return _ecore_vf_pf_release(p_hwfn, true);
 }
 
-#define VF_ACQUIRE_THRESH 3
 static void ecore_vf_pf_acquire_reduce_resc(struct ecore_hwfn *p_hwfn,
 					    struct vf_pf_resc_request *p_req,
 					    struct pf_vf_resc *p_resp)
@@ -251,13 +250,47 @@ static void ecore_vf_pf_acquire_reduce_resc(struct ecore_hwfn *p_hwfn,
 	p_req->num_cids = p_resp->num_cids;
 }
 
-static enum _ecore_status_t ecore_vf_pf_acquire(struct ecore_hwfn *p_hwfn)
+static enum _ecore_status_t
+ecore_vf_pf_soft_flr_acquire(struct ecore_hwfn *p_hwfn)
+{
+	struct ecore_vf_iov *p_iov = p_hwfn->vf_iov_info;
+	struct pfvf_def_resp_tlv *resp;
+	struct vfpf_soft_flr_tlv *req;
+	enum _ecore_status_t rc;
+
+	req = ecore_vf_pf_prep(p_hwfn, CHANNEL_TLV_SOFT_FLR, sizeof(*req));
+
+	/* add list termination tlv */
+	ecore_add_tlv(&p_iov->offset,
+		      CHANNEL_TLV_LIST_END,
+		      sizeof(struct channel_list_end_tlv));
+
+	resp = &p_iov->pf2vf_reply->default_resp;
+	rc = ecore_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
+
+	DP_VERBOSE(p_hwfn, ECORE_MSG_IOV, "rc=0x%x\n", rc);
+
+	/* to release the mutex as ecore_vf_pf_acquire() take the mutex */
+	ecore_vf_pf_req_end(p_hwfn, ECORE_AGAIN);
+
+	/* As of today, there is no mechanism in place for VF to know the FLR
+	 * status, so sufficiently (worst case time) wait for FLR to complete,
+	 * as mailbox request to MFW by the PF for initiating VF flr and PF
+	 * processing VF FLR could take time.
+	 */
+	OSAL_MSLEEP(3000);
+
+	return ecore_vf_pf_acquire(p_hwfn);
+}
+
+enum _ecore_status_t ecore_vf_pf_acquire(struct ecore_hwfn *p_hwfn)
 {
 	struct ecore_vf_iov *p_iov = p_hwfn->vf_iov_info;
 	struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp;
 	struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
 	struct ecore_vf_acquire_sw_info vf_sw_info;
 	struct ecore_dev *p_dev = p_hwfn->p_dev;
+	u8 retry_cnt = p_iov->acquire_retry_cnt;
 	struct vf_pf_resc_request *p_resc;
 	bool resources_acquired = false;
 	struct vfpf_acquire_tlv *req;
@@ -318,6 +351,14 @@ static enum _ecore_status_t ecore_vf_pf_acquire(struct ecore_hwfn *p_hwfn)
 		/* send acquire request */
 		rc = ecore_send_msg2pf(p_hwfn,
 				       &resp->hdr.status, sizeof(*resp));
+
+		if (retry_cnt && rc == ECORE_TIMEOUT) {
+			DP_VERBOSE(p_hwfn, ECORE_MSG_IOV,
+				   "VF retrying to acquire due to VPC timeout\n");
+			retry_cnt--;
+			continue;
+		}
+
 		if (rc != ECORE_SUCCESS)
 			goto exit;
 
@@ -343,7 +384,7 @@ static enum _ecore_status_t ecore_vf_pf_acquire(struct ecore_hwfn *p_hwfn)
 			resources_acquired = true;
 		} /* PF refuses to allocate our resources */
 		else if (resp->hdr.status == PFVF_STATUS_NO_RESOURCE &&
-			 attempts < VF_ACQUIRE_THRESH) {
+			 attempts < ECORE_VF_ACQUIRE_THRESH) {
 			ecore_vf_pf_acquire_reduce_resc(p_hwfn, p_resc,
 							&resp->resc);
 
@@ -391,6 +432,9 @@ static enum _ecore_status_t ecore_vf_pf_acquire(struct ecore_hwfn *p_hwfn)
 				  "PF rejected acquisition by VF\n");
 			rc = ECORE_INVAL;
 			goto exit;
+		} else if (resp->hdr.status == PFVF_STATUS_ACQUIRED) {
+			ecore_vf_pf_req_end(p_hwfn, ECORE_AGAIN);
+			return ecore_vf_pf_soft_flr_acquire(p_hwfn);
 		} else {
 			DP_ERR(p_hwfn,
 			       "PF returned err %d to VF acquisition request\n",
@@ -477,7 +521,9 @@ u32 ecore_vf_hw_bar_size(struct ecore_hwfn *p_hwfn,
 	return 0;
 }
 
-enum _ecore_status_t ecore_vf_hw_prepare(struct ecore_hwfn *p_hwfn)
+enum _ecore_status_t
+ecore_vf_hw_prepare(struct ecore_hwfn *p_hwfn,
+		    struct ecore_hw_prepare_params *p_params)
 {
 	struct ecore_hwfn *p_lead = ECORE_LEADING_HWFN(p_hwfn->p_dev);
 	struct ecore_vf_iov *p_iov;
@@ -583,6 +629,7 @@ enum _ecore_status_t ecore_vf_hw_prepare(struct ecore_hwfn *p_hwfn)
 #endif
 	OSAL_MUTEX_INIT(&p_iov->mutex);
 
+	p_iov->acquire_retry_cnt = p_params->acquire_retry_cnt;
 	p_hwfn->vf_iov_info = p_iov;
 
 	p_hwfn->hw_info.personality = ECORE_PCI_ETH;
diff --git a/dpdk/drivers/net/qede/base/ecore_vf.h b/dpdk/drivers/net/qede/base/ecore_vf.h
index a07f82ebd9..f027eba3ea 100644
--- a/dpdk/drivers/net/qede/base/ecore_vf.h
+++ b/dpdk/drivers/net/qede/base/ecore_vf.h
@@ -11,6 +11,7 @@
 #include "ecore_vf_api.h"
 #include "ecore_l2_api.h"
 #include "ecore_vfpf_if.h"
+#include "ecore_dev_api.h"
 
 /* Default number of CIDs [total of both Rx and Tx] to be requested
  * by default.
@@ -59,6 +60,9 @@ struct ecore_vf_iov {
 	 * bar or via the doorbell bar.
 	 */
 	bool b_doorbell_bar;
+
+	/* retry count for VF acquire on channel timeout */
+	u8 acquire_retry_cnt;
 };
 
 /**
@@ -72,6 +76,8 @@ struct ecore_vf_iov {
 enum _ecore_status_t ecore_vf_pf_get_coalesce(struct ecore_hwfn *p_hwfn,
 					      u16 *p_coal,
 					      struct ecore_queue_cid *p_cid);
+
+enum _ecore_status_t ecore_vf_pf_acquire(struct ecore_hwfn *p_hwfn);
 /**
  * @brief VF - Set Rx/Tx coalesce per VF's relative queue.
  *             Coalesce value '0' will omit the configuration.
@@ -92,10 +98,13 @@ enum _ecore_status_t ecore_vf_pf_set_coalesce(struct ecore_hwfn *p_hwfn,
  *	sends ACQUIRE message
  *
  * @param p_hwfn
+ * @param p_params
  *
  * @return enum _ecore_status_t
  */
-enum _ecore_status_t ecore_vf_hw_prepare(struct ecore_hwfn *p_hwfn);
+enum _ecore_status_t
+ecore_vf_hw_prepare(struct ecore_hwfn *p_hwfn,
+		    struct ecore_hw_prepare_params *p_params);
 
 /**
  * @brief VF - start the RX Queue by sending a message to the PF
diff --git a/dpdk/drivers/net/qede/base/ecore_vf_api.h b/dpdk/drivers/net/qede/base/ecore_vf_api.h
index 1a9fb3b1f2..43951a9a34 100644
--- a/dpdk/drivers/net/qede/base/ecore_vf_api.h
+++ b/dpdk/drivers/net/qede/base/ecore_vf_api.h
@@ -11,6 +11,9 @@
 #include "ecore_mcp_api.h"
 
 #ifdef CONFIG_ECORE_SRIOV
+
+#define ECORE_VF_ACQUIRE_THRESH 3
+
 /**
  * @brief Read the VF bulletin and act on it if needed
  *
diff --git a/dpdk/drivers/net/qede/base/ecore_vfpf_if.h b/dpdk/drivers/net/qede/base/ecore_vfpf_if.h
index c7ecb01c28..f92dc428af 100644
--- a/dpdk/drivers/net/qede/base/ecore_vfpf_if.h
+++ b/dpdk/drivers/net/qede/base/ecore_vfpf_if.h
@@ -251,6 +251,13 @@ struct vfpf_qid_tlv {
 	u8			padding[3];
 };
 
+/* Soft FLR req */
+struct vfpf_soft_flr_tlv {
+	struct vfpf_first_tlv first_tlv;
+	u32 reserved1;
+	u32 reserved2;
+};
+
 /* Setup Queue */
 struct vfpf_start_rxq_tlv {
 	struct vfpf_first_tlv	first_tlv;
@@ -557,6 +564,7 @@ union vfpf_tlvs {
 	struct vfpf_read_coal_req_tlv		read_coal_req;
 	struct vfpf_bulletin_update_mac_tlv	bulletin_update_mac;
 	struct vfpf_update_mtu_tlv		update_mtu;
+	struct vfpf_soft_flr_tlv		soft_flr;
 	struct tlv_buffer_size			tlv_buf_size;
 };
 
@@ -689,6 +697,39 @@ enum {
 	CHANNEL_TLV_COALESCE_READ,
 	CHANNEL_TLV_BULLETIN_UPDATE_MAC,
 	CHANNEL_TLV_UPDATE_MTU,
+	CHANNEL_TLV_RDMA_ACQUIRE,
+	CHANNEL_TLV_RDMA_START,
+	CHANNEL_TLV_RDMA_STOP,
+	CHANNEL_TLV_RDMA_ADD_USER,
+	CHANNEL_TLV_RDMA_REMOVE_USER,
+	CHANNEL_TLV_RDMA_QUERY_COUNTERS,
+	CHANNEL_TLV_RDMA_ALLOC_TID,
+	CHANNEL_TLV_RDMA_REGISTER_TID,
+	CHANNEL_TLV_RDMA_DEREGISTER_TID,
+	CHANNEL_TLV_RDMA_FREE_TID,
+	CHANNEL_TLV_RDMA_CREATE_CQ,
+	CHANNEL_TLV_RDMA_RESIZE_CQ,
+	CHANNEL_TLV_RDMA_DESTROY_CQ,
+	CHANNEL_TLV_RDMA_CREATE_QP,
+	CHANNEL_TLV_RDMA_MODIFY_QP,
+	CHANNEL_TLV_RDMA_QUERY_QP,
+	CHANNEL_TLV_RDMA_DESTROY_QP,
+	CHANNEL_TLV_RDMA_QUERY_PORT,
+	CHANNEL_TLV_RDMA_QUERY_DEVICE,
+	CHANNEL_TLV_RDMA_IWARP_CONNECT,
+	CHANNEL_TLV_RDMA_IWARP_ACCEPT,
+	CHANNEL_TLV_RDMA_IWARP_CREATE_LISTEN,
+	CHANNEL_TLV_RDMA_IWARP_DESTROY_LISTEN,
+	CHANNEL_TLV_RDMA_IWARP_PAUSE_LISTEN,
+	CHANNEL_TLV_RDMA_IWARP_REJECT,
+	CHANNEL_TLV_RDMA_IWARP_SEND_RTR,
+	CHANNEL_TLV_ESTABLISH_LL2_CONN,
+	CHANNEL_TLV_TERMINATE_LL2_CONN,
+	CHANNEL_TLV_ASYNC_EVENT,
+	CHANNEL_TLV_RDMA_CREATE_SRQ,
+	CHANNEL_TLV_RDMA_MODIFY_SRQ,
+	CHANNEL_TLV_RDMA_DESTROY_SRQ,
+	CHANNEL_TLV_SOFT_FLR,
 	CHANNEL_TLV_MAX,
 
 	/* Required for iterating over vport-update tlvs.
diff --git a/dpdk/drivers/net/qede/base/mcp_public.h b/dpdk/drivers/net/qede/base/mcp_public.h
index 98b9723dd4..6667c2d7ab 100644
--- a/dpdk/drivers/net/qede/base/mcp_public.h
+++ b/dpdk/drivers/net/qede/base/mcp_public.h
@@ -1290,6 +1290,7 @@ struct public_drv_mb {
 /*deprecated don't use*/
 #define DRV_MSG_CODE_INITIATE_FLR_DEPRECATED    0x02000000
 #define DRV_MSG_CODE_INITIATE_PF_FLR            0x02010000
+#define DRV_MSG_CODE_INITIATE_VF_FLR		0x02020000
 #define DRV_MSG_CODE_VF_DISABLED_DONE           0xc0000000
 #define DRV_MSG_CODE_CFG_VF_MSIX                0xc0010000
 #define DRV_MSG_CODE_CFG_PF_VFS_MSIX            0xc0020000
@@ -1749,6 +1750,7 @@ struct public_drv_mb {
 #define FW_MSG_CODE_NIG_DRAIN_DONE              0x30000000
 #define FW_MSG_CODE_VF_DISABLED_DONE            0xb0000000
 #define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE        0xb0010000
+#define FW_MSG_CODE_INITIATE_VF_FLR_OK		0xb0030000
 #define FW_MSG_CODE_ERR_RESOURCE_TEMPORARY_UNAVAILABLE	0x008b0000
 #define FW_MSG_CODE_ERR_RESOURCE_ALREADY_ALLOCATED	0x008c0000
 #define FW_MSG_CODE_ERR_RESOURCE_NOT_ALLOCATED		0x008d0000
diff --git a/dpdk/drivers/net/qede/qede_ethdev.c b/dpdk/drivers/net/qede/qede_ethdev.c
index 19d2e96191..6f2f0051f6 100644
--- a/dpdk/drivers/net/qede/qede_ethdev.c
+++ b/dpdk/drivers/net/qede/qede_ethdev.c
@@ -551,17 +551,16 @@ qed_configure_filter_rx_mode(struct rte_eth_dev *eth_dev,
 		ECORE_ACCEPT_BCAST;
 
 	if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) {
-		flags.rx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED;
+		flags.rx_accept_filter |= (ECORE_ACCEPT_UCAST_UNMATCHED |
+					   ECORE_ACCEPT_MCAST_UNMATCHED);
 		if (IS_VF(edev)) {
-			flags.tx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED;
-			DP_INFO(edev, "Enabling Tx unmatched flag for VF\n");
+			flags.tx_accept_filter |=
+						(ECORE_ACCEPT_UCAST_UNMATCHED |
+						 ECORE_ACCEPT_MCAST_UNMATCHED);
+			DP_INFO(edev, "Enabling Tx unmatched flags for VF\n");
 		}
 	} else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) {
 		flags.rx_accept_filter |= ECORE_ACCEPT_MCAST_UNMATCHED;
-	} else if (type == (QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC |
-				QED_FILTER_RX_MODE_TYPE_PROMISC)) {
-		flags.rx_accept_filter |= ECORE_ACCEPT_UCAST_UNMATCHED |
-			ECORE_ACCEPT_MCAST_UNMATCHED;
 	}
 
 	return ecore_filter_accept_cmd(edev, 0, flags, false, false,
@@ -962,9 +961,6 @@ static int qede_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
 		}
 	}
 
-	if (mask & ETH_VLAN_EXTEND_MASK)
-		DP_ERR(edev, "Extend VLAN not supported\n");
-
 	qdev->vlan_offload_mask = mask;
 
 	DP_INFO(edev, "VLAN offload mask %d\n", mask);
@@ -1064,7 +1060,7 @@ static int qede_dev_start(struct rte_eth_dev *eth_dev)
 		qede_reset_queue_stats(qdev, true);
 
 	/* Newer SR-IOV PF driver expects RX/TX queues to be started before
-	 * enabling RSS. Hence RSS configuration is deferred upto this point.
+	 * enabling RSS. Hence RSS configuration is deferred up to this point.
 	 * Also, we would like to retain similar behavior in PF case, so we
 	 * don't do PF/VF specific check here.
 	 */
@@ -1076,6 +1072,9 @@ static int qede_dev_start(struct rte_eth_dev *eth_dev)
 	if (qede_activate_vport(eth_dev, true))
 		goto err;
 
+	/* Bring-up the link */
+	qede_dev_set_link_state(eth_dev, true);
+
 	/* Update link status */
 	qede_link_update(eth_dev, 0);
 
@@ -1097,6 +1096,12 @@ static void qede_dev_stop(struct rte_eth_dev *eth_dev)
 
 	PMD_INIT_FUNC_TRACE(edev);
 
+	/* Bring the link down */
+	qede_dev_set_link_state(eth_dev, false);
+
+	/* Update link status */
+	qede_link_update(eth_dev, 0);
+
 	/* Disable vport */
 	if (qede_activate_vport(eth_dev, false))
 		return;
@@ -1182,6 +1187,8 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
 	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct rte_eth_rxmode *rxmode = &eth_dev->data->dev_conf.rxmode;
+	uint8_t num_rxqs;
+	uint8_t num_txqs;
 	int ret;
 
 	PMD_INIT_FUNC_TRACE(edev);
@@ -1214,12 +1221,17 @@ static int qede_dev_configure(struct rte_eth_dev *eth_dev)
 	if (qede_check_fdir_support(eth_dev))
 		return -ENOTSUP;
 
-	qede_dealloc_fp_resc(eth_dev);
-	qdev->num_tx_queues = eth_dev->data->nb_tx_queues * edev->num_hwfns;
-	qdev->num_rx_queues = eth_dev->data->nb_rx_queues * edev->num_hwfns;
-
-	if (qede_alloc_fp_resc(qdev))
-		return -ENOMEM;
+	/* Allocate/reallocate fastpath resources only for new queue config */
+	num_txqs = eth_dev->data->nb_tx_queues * edev->num_hwfns;
+	num_rxqs = eth_dev->data->nb_rx_queues * edev->num_hwfns;
+	if (qdev->num_tx_queues != num_txqs ||
+	    qdev->num_rx_queues != num_rxqs) {
+		qede_dealloc_fp_resc(eth_dev);
+		qdev->num_tx_queues = num_txqs;
+		qdev->num_rx_queues = num_rxqs;
+		if (qede_alloc_fp_resc(qdev))
+			return -ENOMEM;
+	}
 
 	/* If jumbo enabled adjust MTU */
 	if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
@@ -1404,16 +1416,13 @@ qede_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete)
 
 static int qede_promiscuous_enable(struct rte_eth_dev *eth_dev)
 {
-	struct qede_dev *qdev = eth_dev->data->dev_private;
-	struct ecore_dev *edev = &qdev->edev;
-	enum qed_filter_rx_mode_type type = QED_FILTER_RX_MODE_TYPE_PROMISC;
 	enum _ecore_status_t ecore_status;
+	struct qede_dev *qdev = QEDE_INIT_QDEV(eth_dev);
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
+	enum qed_filter_rx_mode_type type = QED_FILTER_RX_MODE_TYPE_PROMISC;
 
 	PMD_INIT_FUNC_TRACE(edev);
 
-	if (rte_eth_allmulticast_get(eth_dev->data->port_id) == 1)
-		type |= QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC;
-
 	ecore_status = qed_configure_filter_rx_mode(eth_dev, type);
 
 	return ecore_status >= ECORE_SUCCESS ? 0 : -EAGAIN;
@@ -1472,7 +1481,8 @@ static void qede_dev_close(struct rte_eth_dev *eth_dev)
 	if (eth_dev->data->dev_started)
 		qede_dev_stop(eth_dev);
 
-	qede_stop_vport(edev);
+	if (qdev->vport_started)
+		qede_stop_vport(edev);
 	qdev->vport_started = false;
 	qede_fdir_dealloc_resc(eth_dev);
 	qede_dealloc_fp_resc(eth_dev);
@@ -1480,8 +1490,6 @@ static void qede_dev_close(struct rte_eth_dev *eth_dev)
 	eth_dev->data->nb_rx_queues = 0;
 	eth_dev->data->nb_tx_queues = 0;
 
-	/* Bring the link down */
-	qede_dev_set_link_state(eth_dev, false);
 	qdev->ops->common->slowpath_stop(edev);
 	qdev->ops->common->remove(edev);
 	rte_intr_disable(&pci_dev->intr_handle);
@@ -1789,8 +1797,7 @@ static int qede_allmulticast_enable(struct rte_eth_dev *eth_dev)
 	enum _ecore_status_t ecore_status;
 
 	if (rte_eth_promiscuous_get(eth_dev->data->port_id) == 1)
-		type |= QED_FILTER_RX_MODE_TYPE_PROMISC;
-
+		type = QED_FILTER_RX_MODE_TYPE_PROMISC;
 	ecore_status = qed_configure_filter_rx_mode(eth_dev, type);
 
 	return ecore_status >= ECORE_SUCCESS ? 0 : -EAGAIN;
@@ -2275,7 +2282,7 @@ static int qede_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 			fp->rxq->rx_buf_size = rc;
 		}
 	}
-	if (max_rx_pkt_len > RTE_ETHER_MAX_LEN)
+	if (frame_size > QEDE_ETH_MAX_LEN)
 		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
 		dev->data->dev_conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
@@ -2604,9 +2611,6 @@ static int qede_common_dev_init(struct rte_eth_dev *eth_dev, bool is_vf)
 
 	eth_dev->dev_ops = (is_vf) ? &qede_eth_vf_dev_ops : &qede_eth_dev_ops;
 
-	/* Bring-up the link */
-	qede_dev_set_link_state(eth_dev, true);
-
 	adapter->num_tx_queues = 0;
 	adapter->num_rx_queues = 0;
 	SLIST_INIT(&adapter->arfs_info.arfs_list_head);
diff --git a/dpdk/drivers/net/qede/qede_main.c b/dpdk/drivers/net/qede/qede_main.c
index 4eb79d0fbb..67392d6aa4 100644
--- a/dpdk/drivers/net/qede/qede_main.c
+++ b/dpdk/drivers/net/qede/qede_main.c
@@ -56,6 +56,10 @@ qed_probe(struct ecore_dev *edev, struct rte_pci_device *pci_dev,
 	qed_init_pci(edev, pci_dev);
 
 	memset(&hw_prepare_params, 0, sizeof(hw_prepare_params));
+
+	if (is_vf)
+		hw_prepare_params.acquire_retry_cnt = ECORE_VF_ACQUIRE_THRESH;
+
 	hw_prepare_params.personality = ECORE_PCI_ETH;
 	hw_prepare_params.drv_resc_alloc = false;
 	hw_prepare_params.chk_reg_fifo = false;
@@ -571,13 +575,12 @@ qed_get_current_link(struct ecore_dev *edev, struct qed_link_output *if_link)
 	hwfn = &edev->hwfns[0];
 	if (IS_PF(edev)) {
 		ptt = ecore_ptt_acquire(hwfn);
-		if (!ptt)
-			DP_NOTICE(hwfn, true, "Failed to fill link; No PTT\n");
-
+		if (ptt) {
 			qed_fill_link(hwfn, ptt, if_link);
-
-		if (ptt)
 			ecore_ptt_release(hwfn, ptt);
+		} else {
+			DP_NOTICE(hwfn, true, "Failed to fill link; No PTT\n");
+		}
 	} else {
 		qed_fill_link(hwfn, NULL, if_link);
 	}
diff --git a/dpdk/drivers/net/qede/qede_rxtx.c b/dpdk/drivers/net/qede/qede_rxtx.c
index a28dd0a07f..64e6de4743 100644
--- a/dpdk/drivers/net/qede/qede_rxtx.c
+++ b/dpdk/drivers/net/qede/qede_rxtx.c
@@ -593,12 +593,14 @@ qede_alloc_mem_sb(struct qede_dev *qdev, struct ecore_sb_info *sb_info,
 
 int qede_alloc_fp_resc(struct qede_dev *qdev)
 {
-	struct ecore_dev *edev = &qdev->edev;
+	struct ecore_dev *edev = QEDE_INIT_EDEV(qdev);
 	struct qede_fastpath *fp;
 	uint32_t num_sbs;
 	uint16_t sb_idx;
 	int i;
 
+	PMD_INIT_FUNC_TRACE(edev);
+
 	if (IS_VF(edev))
 		ecore_vf_get_num_sbs(ECORE_LEADING_HWFN(edev), &num_sbs);
 	else
@@ -645,8 +647,6 @@ int qede_alloc_fp_resc(struct qede_dev *qdev)
 
 	for (sb_idx = 0; sb_idx < QEDE_RXTX_MAX(qdev); sb_idx++) {
 		fp = &qdev->fp_array[sb_idx];
-		if (!fp)
-			continue;
 		fp->sb_info = rte_calloc("sb", 1, sizeof(struct ecore_sb_info),
 				RTE_CACHE_LINE_SIZE);
 		if (!fp->sb_info) {
@@ -676,11 +676,9 @@ void qede_dealloc_fp_resc(struct rte_eth_dev *eth_dev)
 
 	for (sb_idx = 0; sb_idx < QEDE_RXTX_MAX(qdev); sb_idx++) {
 		fp = &qdev->fp_array[sb_idx];
-		if (!fp)
-			continue;
-		DP_INFO(edev, "Free sb_info index 0x%x\n",
-				fp->sb_info->igu_sb_id);
 		if (fp->sb_info) {
+			DP_INFO(edev, "Free sb_info index 0x%x\n",
+					fp->sb_info->igu_sb_id);
 			OSAL_DMA_FREE_COHERENT(edev, fp->sb_info->sb_virt,
 				fp->sb_info->sb_phys,
 				sizeof(struct status_block));
diff --git a/dpdk/drivers/net/qede/qede_rxtx.h b/dpdk/drivers/net/qede/qede_rxtx.h
index 75cc930fd5..8dc669963b 100644
--- a/dpdk/drivers/net/qede/qede_rxtx.h
+++ b/dpdk/drivers/net/qede/qede_rxtx.h
@@ -71,6 +71,7 @@
 				 + (QEDE_LLC_SNAP_HDR_LEN) + 2)
 
 #define QEDE_MAX_ETHER_HDR_LEN	(RTE_ETHER_HDR_LEN + QEDE_ETH_OVERHEAD)
+#define QEDE_ETH_MAX_LEN	(RTE_ETHER_MTU + QEDE_MAX_ETHER_HDR_LEN)
 
 #define QEDE_RSS_OFFLOAD_ALL    (ETH_RSS_IPV4			|\
 				 ETH_RSS_NONFRAG_IPV4_TCP	|\
diff --git a/dpdk/drivers/net/ring/rte_eth_ring.c b/dpdk/drivers/net/ring/rte_eth_ring.c
index 41acbc513d..cae959b76c 100644
--- a/dpdk/drivers/net/ring/rte_eth_ring.c
+++ b/dpdk/drivers/net/ring/rte_eth_ring.c
@@ -16,6 +16,7 @@
 #define ETH_RING_ACTION_CREATE		"CREATE"
 #define ETH_RING_ACTION_ATTACH		"ATTACH"
 #define ETH_RING_INTERNAL_ARG		"internal"
+#define ETH_RING_INTERNAL_ARG_MAX_LEN	19 /* "0x..16chars..\0" */
 
 static const char *valid_arguments[] = {
 	ETH_RING_NUMA_NODE_ACTION_ARG,
@@ -246,6 +247,7 @@ static const struct eth_dev_ops ops = {
 
 static int
 do_eth_dev_ring_create(const char *name,
+		struct rte_vdev_device *vdev,
 		struct rte_ring * const rx_queues[],
 		const unsigned int nb_rx_queues,
 		struct rte_ring *const tx_queues[],
@@ -291,12 +293,15 @@ do_eth_dev_ring_create(const char *name,
 	}
 
 	/* now put it all together
+	 * - store EAL device in eth_dev,
 	 * - store queue data in internals,
 	 * - store numa_node info in eth_dev_data
 	 * - point eth_dev_data to internals
 	 * - and point eth_dev structure to new eth_dev_data structure
 	 */
 
+	eth_dev->device = &vdev->device;
+
 	data = eth_dev->data;
 	data->rx_queues = rx_queues_local;
 	data->tx_queues = tx_queues_local;
@@ -408,7 +413,9 @@ rte_eth_from_ring(struct rte_ring *r)
 }
 
 static int
-eth_dev_ring_create(const char *name, const unsigned int numa_node,
+eth_dev_ring_create(const char *name,
+		struct rte_vdev_device *vdev,
+		const unsigned int numa_node,
 		enum dev_action action, struct rte_eth_dev **eth_dev)
 {
 	/* rx and tx are so-called from point of view of first port.
@@ -438,7 +445,7 @@ eth_dev_ring_create(const char *name, const unsigned int numa_node,
 			return -1;
 	}
 
-	if (do_eth_dev_ring_create(name, rxtx, num_rings, rxtx, num_rings,
+	if (do_eth_dev_ring_create(name, vdev, rxtx, num_rings, rxtx, num_rings,
 		numa_node, action, eth_dev) < 0)
 		return -1;
 
@@ -533,8 +540,21 @@ parse_internal_args(const char *key __rte_unused, const char *value,
 {
 	struct ring_internal_args **internal_args = data;
 	void *args;
+	int ret, n;
 
-	sscanf(value, "%p", &args);
+	/* make sure 'value' is valid pointer length */
+	if (strnlen(value, ETH_RING_INTERNAL_ARG_MAX_LEN) >=
+			ETH_RING_INTERNAL_ARG_MAX_LEN) {
+		PMD_LOG(ERR, "Error parsing internal args, argument is too long");
+		return -1;
+	}
+
+	ret = sscanf(value, "%p%n", &args, &n);
+	if (ret == 0 || (size_t)n != strlen(value)) {
+		PMD_LOG(ERR, "Error parsing internal args");
+
+		return -1;
+	}
 
 	*internal_args = args;
 
@@ -560,12 +580,12 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
 	PMD_LOG(INFO, "Initializing pmd_ring for %s", name);
 
 	if (params == NULL || params[0] == '\0') {
-		ret = eth_dev_ring_create(name, rte_socket_id(), DEV_CREATE,
+		ret = eth_dev_ring_create(name, dev, rte_socket_id(), DEV_CREATE,
 				&eth_dev);
 		if (ret == -1) {
 			PMD_LOG(INFO,
 				"Attach to pmd_ring for %s", name);
-			ret = eth_dev_ring_create(name, rte_socket_id(),
+			ret = eth_dev_ring_create(name, dev, rte_socket_id(),
 						  DEV_ATTACH, &eth_dev);
 		}
 	} else {
@@ -573,20 +593,17 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
 
 		if (!kvlist) {
 			PMD_LOG(INFO,
-				"Ignoring unsupported parameters when creatingrings-backed ethernet device");
-			ret = eth_dev_ring_create(name, rte_socket_id(),
+				"Ignoring unsupported parameters when creating rings-backed ethernet device");
+			ret = eth_dev_ring_create(name, dev, rte_socket_id(),
 						  DEV_CREATE, &eth_dev);
 			if (ret == -1) {
 				PMD_LOG(INFO,
 					"Attach to pmd_ring for %s",
 					name);
-				ret = eth_dev_ring_create(name, rte_socket_id(),
+				ret = eth_dev_ring_create(name, dev, rte_socket_id(),
 							  DEV_ATTACH, &eth_dev);
 			}
 
-			if (eth_dev)
-				eth_dev->device = &dev->device;
-
 			return ret;
 		}
 
@@ -597,7 +614,7 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
 			if (ret < 0)
 				goto out_free;
 
-			ret = do_eth_dev_ring_create(name,
+			ret = do_eth_dev_ring_create(name, dev,
 				internal_args->rx_queues,
 				internal_args->nb_rx_queues,
 				internal_args->tx_queues,
@@ -627,6 +644,7 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
 
 			for (info->count = 0; info->count < info->total; info->count++) {
 				ret = eth_dev_ring_create(info->list[info->count].name,
+							  dev,
 							  info->list[info->count].node,
 							  info->list[info->count].action,
 							  &eth_dev);
@@ -635,7 +653,7 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
 					PMD_LOG(INFO,
 						"Attach to pmd_ring for %s",
 						name);
-					ret = eth_dev_ring_create(name,
+					ret = eth_dev_ring_create(name, dev,
 							info->list[info->count].node,
 							DEV_ATTACH,
 							&eth_dev);
@@ -644,9 +662,6 @@ rte_pmd_ring_probe(struct rte_vdev_device *dev)
 		}
 	}
 
-	if (eth_dev)
-		eth_dev->device = &dev->device;
-
 out_free:
 	rte_kvargs_free(kvlist);
 	rte_free(info);
diff --git a/dpdk/drivers/net/sfc/base/ef10_evb.c b/dpdk/drivers/net/sfc/base/ef10_evb.c
index 1788a2c96a..9b33e89fc1 100644
--- a/dpdk/drivers/net/sfc/base/ef10_evb.c
+++ b/dpdk/drivers/net/sfc/base/ef10_evb.c
@@ -9,15 +9,13 @@
 
 #if EFSYS_OPT_EVB
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
 
 	__checkReturn	efx_rc_t
 ef10_evb_init(
 	__in		efx_nic_t *enp)
 {
-	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-		enp->en_family == EFX_FAMILY_MEDFORD ||
-		enp->en_family == EFX_FAMILY_MEDFORD2);
+	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
 	return (0);
 }
@@ -26,12 +24,10 @@ ef10_evb_init(
 ef10_evb_fini(
 	__in		efx_nic_t *enp)
 {
-	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-		enp->en_family == EFX_FAMILY_MEDFORD ||
-		enp->en_family == EFX_FAMILY_MEDFORD2);
+	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 }
 
-	__checkReturn	efx_rc_t
+static	__checkReturn	efx_rc_t
 efx_mcdi_vswitch_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_vport_id_t vport_id,
@@ -98,7 +94,7 @@ efx_mcdi_vswitch_alloc(
 	return (rc);
 }
 
-	__checkReturn	efx_rc_t
+static	__checkReturn	efx_rc_t
 efx_mcdi_vswitch_free(
 	__in		efx_nic_t *enp)
 {
@@ -129,7 +125,7 @@ efx_mcdi_vswitch_free(
 	return (rc);
 }
 
-	__checkReturn	efx_rc_t
+static	__checkReturn	efx_rc_t
 efx_mcdi_vport_alloc(
 	__in		efx_nic_t *enp,
 	__in		efx_vport_type_t vport_type,
@@ -192,7 +188,7 @@ efx_mcdi_vport_alloc(
 	return (rc);
 }
 
-	__checkReturn	efx_rc_t
+static	__checkReturn	efx_rc_t
 efx_mcdi_vport_free(
 	__in		efx_nic_t *enp,
 	__in		efx_vport_id_t vport_id)
@@ -223,7 +219,7 @@ efx_mcdi_vport_free(
 	return (rc);
 }
 
-	__checkReturn			efx_rc_t
+static	__checkReturn			efx_rc_t
 efx_mcdi_vport_mac_addr_add(
 	__in				efx_nic_t *enp,
 	__in				efx_vport_id_t vport_id,
@@ -258,7 +254,7 @@ efx_mcdi_vport_mac_addr_add(
 	return (rc);
 }
 
-	__checkReturn			efx_rc_t
+static	__checkReturn			efx_rc_t
 efx_mcdi_vport_mac_addr_del(
 	__in				efx_nic_t *enp,
 	__in				efx_vport_id_t vport_id,
@@ -293,7 +289,7 @@ efx_mcdi_vport_mac_addr_del(
 	return (rc);
 }
 
-	__checkReturn	efx_rc_t
+static	__checkReturn	efx_rc_t
 efx_mcdi_port_assign(
 	__in		efx_nic_t *enp,
 	__in		efx_vport_id_t vport_id,
@@ -330,7 +326,7 @@ efx_mcdi_port_assign(
 	return (rc);
 }
 
-	__checkReturn				efx_rc_t
+static	__checkReturn				efx_rc_t
 efx_mcdi_vport_reconfigure(
 	__in					efx_nic_t *enp,
 	__in					efx_vport_id_t vport_id,
@@ -549,5 +545,5 @@ ef10_evb_vport_stats(
 			EFX_STATS_UPLOAD, 0));
 }
 
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
 #endif /* EFSYS_OPT_EVB */
diff --git a/dpdk/drivers/net/sfc/base/ef10_filter.c b/dpdk/drivers/net/sfc/base/ef10_filter.c
index e4f8de51c0..158e77e3bb 100644
--- a/dpdk/drivers/net/sfc/base/ef10_filter.c
+++ b/dpdk/drivers/net/sfc/base/ef10_filter.c
@@ -590,6 +590,231 @@ ef10_filter_restore(
 	return (rc);
 }
 
+enum ef10_filter_add_action_e {
+	/* Insert a new filter */
+	EF10_FILTER_ADD_NEW,
+	/*
+	 * Replace old filter with a new, overriding the old one
+	 * if it has lower priority.
+	 */
+	EF10_FILTER_ADD_REPLACE,
+	/* Store new, lower priority filter as overridden by old filter */
+	EF10_FILTER_ADD_STORE,
+	/* Special case for AUTO filters, remove AUTO_OLD flag */
+	EF10_FILTER_ADD_REFRESH,
+};
+
+static	__checkReturn	efx_rc_t
+ef10_filter_add_lookup_equal_spec(
+	__in		efx_filter_spec_t *spec,
+	__in		efx_filter_spec_t *probe_spec,
+	__in		efx_filter_replacement_policy_t policy,
+	__out		boolean_t *found)
+{
+	efx_rc_t rc;
+
+	/* Refreshing AUTO filter */
+	if (spec->efs_priority == EFX_FILTER_PRI_AUTO &&
+	    probe_spec->efs_priority == EFX_FILTER_PRI_AUTO) {
+		*found = B_TRUE;
+		return (0);
+	}
+
+	/*
+	 * With exclusive filters, higher priority ones
+	 * override lower priority ones, and lower priority
+	 * ones are stored in case the higher priority one
+	 * is removed.
+	 */
+	if (ef10_filter_is_exclusive(spec)) {
+		switch (policy) {
+		case EFX_FILTER_REPLACEMENT_HIGHER_OR_EQUAL_PRIORITY:
+			if (spec->efs_priority == probe_spec->efs_priority) {
+				*found = B_TRUE;
+				break;
+			}
+			/* Fall-through */
+		case EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY:
+			if (spec->efs_priority > probe_spec->efs_priority) {
+				*found = B_TRUE;
+				break;
+			}
+			/* Fall-through */
+		case EFX_FILTER_REPLACEMENT_NEVER:
+			/*
+			 * Lower priority filter needs to be
+			 * stored. It does *not* replace the
+			 * old one. That is why EEXIST is not
+			 * returned in that case.
+			 */
+			if (spec->efs_priority < probe_spec->efs_priority) {
+				*found = B_TRUE;
+				break;
+			} else {
+				rc = EEXIST;
+				goto fail1;
+			}
+		default:
+			EFSYS_ASSERT(0);
+			rc = EEXIST;
+			goto fail2;
+		}
+	} else {
+		*found = B_FALSE;
+	}
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
+
+static			void
+ef10_filter_add_select_action(
+	__in		efx_filter_spec_t *saved_spec,
+	__in		efx_filter_spec_t *spec,
+	__out		enum ef10_filter_add_action_e *action,
+	__out		efx_filter_spec_t **overridden_spec)
+{
+	efx_filter_spec_t *overridden = NULL;
+
+	if (saved_spec == NULL) {
+		*action = EF10_FILTER_ADD_NEW;
+	} else if (ef10_filter_is_exclusive(spec) == B_FALSE) {
+		/*
+		 * Non-exclusive filters are always stored in separate entries
+		 * in the table. The only case involving a saved spec is
+		 * refreshing an AUTO filter.
+		 */
+		EFSYS_ASSERT(saved_spec->efs_overridden_spec == NULL);
+		EFSYS_ASSERT(spec->efs_priority == EFX_FILTER_PRI_AUTO);
+		EFSYS_ASSERT(saved_spec->efs_priority == EFX_FILTER_PRI_AUTO);
+		*action = EF10_FILTER_ADD_REFRESH;
+	} else {
+		/* Exclusive filters stored in the same entry */
+		if (spec->efs_priority > saved_spec->efs_priority) {
+			/*
+			 * Insert a high priority filter over a lower priority
+			 * one. Only two priority levels are implemented, so
+			 * there must not already be an overridden filter.
+			 */
+			EFX_STATIC_ASSERT(EFX_FILTER_NPRI == 2);
+			EFSYS_ASSERT(saved_spec->efs_overridden_spec == NULL);
+			overridden = saved_spec;
+			*action = EF10_FILTER_ADD_REPLACE;
+		} else if (spec->efs_priority == saved_spec->efs_priority) {
+			/* Replace in-place or refresh an existing filter */
+			if (spec->efs_priority == EFX_FILTER_PRI_AUTO)
+				*action = EF10_FILTER_ADD_REFRESH;
+			else
+				*action = EF10_FILTER_ADD_REPLACE;
+		} else {
+			/*
+			 * Insert a lower priority filter, storing it in case
+			 * the higher priority filter is removed.
+			 *
+			 * Currently there are only two priority levels, so this
+			 * must be an AUTO filter.
+			 */
+			EFX_STATIC_ASSERT(EFX_FILTER_NPRI == 2);
+			EFSYS_ASSERT(spec->efs_priority == EFX_FILTER_PRI_AUTO);
+			if (saved_spec->efs_overridden_spec != NULL) {
+				*action = EF10_FILTER_ADD_REFRESH;
+			} else {
+				overridden = spec;
+				*action = EF10_FILTER_ADD_STORE;
+			}
+		}
+	}
+
+	*overridden_spec = overridden;
+}
+
+static	__checkReturn	efx_rc_t
+ef10_filter_add_execute_action(
+	__in		efx_nic_t *enp,
+	__in		efx_filter_spec_t *saved_spec,
+	__in		efx_filter_spec_t *spec,
+	__in		efx_filter_spec_t *overridden_spec,
+	__in		enum ef10_filter_add_action_e action,
+	__in		int ins_index)
+{
+	ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
+	efsys_lock_state_t state;
+	efx_rc_t rc;
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	if (action == EF10_FILTER_ADD_REFRESH) {
+		ef10_filter_set_entry_not_auto_old(eftp, ins_index);
+		goto out_unlock;
+	} else if (action == EF10_FILTER_ADD_STORE) {
+		EFSYS_ASSERT(overridden_spec != NULL);
+		saved_spec->efs_overridden_spec = overridden_spec;
+		goto out_unlock;
+	}
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	switch (action) {
+	case EF10_FILTER_ADD_REPLACE:
+		/*
+		 * On replacing the filter handle may change after a
+		 * successful replace operation.
+		 */
+		rc = efx_mcdi_filter_op_add(enp, spec,
+		    MC_CMD_FILTER_OP_IN_OP_REPLACE,
+		    &eftp->eft_entry[ins_index].efe_handle);
+		break;
+	case EF10_FILTER_ADD_NEW:
+		if (ef10_filter_is_exclusive(spec)) {
+			rc = efx_mcdi_filter_op_add(enp, spec,
+			    MC_CMD_FILTER_OP_IN_OP_INSERT,
+			    &eftp->eft_entry[ins_index].efe_handle);
+		} else {
+			rc = efx_mcdi_filter_op_add(enp, spec,
+			    MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE,
+			    &eftp->eft_entry[ins_index].efe_handle);
+		}
+		break;
+	default:
+		rc = EINVAL;
+		EFSYS_ASSERT(0);
+		break;
+	}
+	if (rc != 0)
+		goto fail1;
+
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	if (action == EF10_FILTER_ADD_REPLACE) {
+		/* Update the fields that may differ */
+		saved_spec->efs_priority = spec->efs_priority;
+		saved_spec->efs_flags = spec->efs_flags;
+		saved_spec->efs_rss_context = spec->efs_rss_context;
+		saved_spec->efs_dmaq_id = spec->efs_dmaq_id;
+
+		if (overridden_spec != NULL)
+			saved_spec->efs_overridden_spec = overridden_spec;
+	}
+
+out_unlock:
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
 /*
  * An arbitrary search limit for the software hash table. As per the linux net
  * driver.
@@ -600,22 +825,24 @@ static	__checkReturn	efx_rc_t
 ef10_filter_add_internal(
 	__in		efx_nic_t *enp,
 	__inout		efx_filter_spec_t *spec,
-	__in		boolean_t may_replace,
+	__in		efx_filter_replacement_policy_t policy,
 	__out_opt	uint32_t *filter_id)
 {
 	efx_rc_t rc;
 	ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
+	enum ef10_filter_add_action_e action;
+	efx_filter_spec_t *overridden_spec = NULL;
 	efx_filter_spec_t *saved_spec;
 	uint32_t hash;
 	unsigned int depth;
 	int ins_index;
-	boolean_t replacing = B_FALSE;
-	unsigned int i;
 	efsys_lock_state_t state;
 	boolean_t locked = B_FALSE;
 
 	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
+	EFSYS_ASSERT(spec->efs_overridden_spec == NULL);
+
 	hash = ef10_filter_hash(spec);
 
 	/*
@@ -628,145 +855,136 @@ ef10_filter_add_internal(
 	 * else a free slot to insert at.  If any of them are busy,
 	 * we have to wait and retry.
 	 */
-	for (;;) {
-		ins_index = -1;
-		depth = 1;
-		EFSYS_LOCK(enp->en_eslp, state);
-		locked = B_TRUE;
+retry:
+	EFSYS_LOCK(enp->en_eslp, state);
+	locked = B_TRUE;
+
+	ins_index = -1;
+
+	for (depth = 1; depth <= EF10_FILTER_SEARCH_LIMIT; depth++) {
+		unsigned int probe_index;
+		efx_filter_spec_t *probe_spec;
 
-		for (;;) {
-			i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
-			saved_spec = ef10_filter_entry_spec(eftp, i);
-
-			if (!saved_spec) {
-				if (ins_index < 0) {
-					ins_index = i;
-				}
-			} else if (ef10_filter_equal(spec, saved_spec)) {
-				if (ef10_filter_entry_is_busy(eftp, i))
-					break;
-				if (saved_spec->efs_priority
-					    == EFX_FILTER_PRI_AUTO) {
-					ins_index = i;
-					goto found;
-				} else if (ef10_filter_is_exclusive(spec)) {
-					if (may_replace) {
-						ins_index = i;
-						goto found;
-					} else {
-						rc = EEXIST;
-						goto fail1;
-					}
-				}
-
-				/* Leave existing */
+		probe_index = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
+		probe_spec = ef10_filter_entry_spec(eftp, probe_index);
+
+		if (probe_spec == NULL) {
+			if (ins_index < 0)
+				ins_index = probe_index;
+		} else if (ef10_filter_equal(spec, probe_spec)) {
+			boolean_t found;
+
+			if (ef10_filter_entry_is_busy(eftp, probe_index)) {
+				EFSYS_UNLOCK(enp->en_eslp, state);
+				locked = B_FALSE;
+				goto retry;
 			}
 
-			/*
-			 * Once we reach the maximum search depth, use
-			 * the first suitable slot or return EBUSY if
-			 * there was none.
-			 */
-			if (depth == EF10_FILTER_SEARCH_LIMIT) {
-				if (ins_index < 0) {
-					rc = EBUSY;
-					goto fail2;
-				}
-				goto found;
+			rc = ef10_filter_add_lookup_equal_spec(spec,
+			    probe_spec, policy, &found);
+			if (rc != 0)
+				goto fail1;
+
+			if (found != B_FALSE) {
+				ins_index = probe_index;
+				break;
 			}
-			depth++;
 		}
-		EFSYS_UNLOCK(enp->en_eslp, state);
-		locked = B_FALSE;
 	}
 
-found:
 	/*
-	 * Create a software table entry if necessary, and mark it
-	 * busy.  We might yet fail to insert, but any attempt to
-	 * insert a conflicting filter while we're waiting for the
-	 * firmware must find the busy entry.
+	 * Once we reach the maximum search depth, use the first suitable slot
+	 * or return EBUSY if there was none.
 	 */
-	saved_spec = ef10_filter_entry_spec(eftp, ins_index);
-	if (saved_spec) {
-		if (saved_spec->efs_priority == EFX_FILTER_PRI_AUTO) {
-			/* This is a filter we are refreshing */
-			ef10_filter_set_entry_not_auto_old(eftp, ins_index);
-			goto out_unlock;
-
-		}
-		replacing = B_TRUE;
-	} else {
-		EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), saved_spec);
-		if (!saved_spec) {
-			rc = ENOMEM;
-			goto fail3;
-		}
-		*saved_spec = *spec;
-		ef10_filter_set_entry(eftp, ins_index, saved_spec);
+	if (ins_index < 0) {
+		rc = EBUSY;
+		goto fail2;
 	}
+
+	/*
+	 * Mark software table entry busy. We might yet fail to insert,
+	 * but any attempt to insert a conflicting filter while we're
+	 * waiting for the firmware must find the busy entry.
+	 */
 	ef10_filter_set_entry_busy(eftp, ins_index);
 
-	EFSYS_UNLOCK(enp->en_eslp, state);
-	locked = B_FALSE;
+	saved_spec = ef10_filter_entry_spec(eftp, ins_index);
+	ef10_filter_add_select_action(saved_spec, spec, &action,
+	    &overridden_spec);
 
 	/*
-	 * On replacing the filter handle may change after after a successful
-	 * replace operation.
+	 * Allocate a new filter if found entry is empty or
+	 * a filter should be overridden.
 	 */
-	if (replacing) {
-		rc = efx_mcdi_filter_op_add(enp, spec,
-		    MC_CMD_FILTER_OP_IN_OP_REPLACE,
-		    &eftp->eft_entry[ins_index].efe_handle);
-	} else if (ef10_filter_is_exclusive(spec)) {
-		rc = efx_mcdi_filter_op_add(enp, spec,
-		    MC_CMD_FILTER_OP_IN_OP_INSERT,
-		    &eftp->eft_entry[ins_index].efe_handle);
-	} else {
-		rc = efx_mcdi_filter_op_add(enp, spec,
-		    MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE,
-		    &eftp->eft_entry[ins_index].efe_handle);
-	}
-
-	if (rc != 0)
-		goto fail4;
+	if (overridden_spec != NULL || saved_spec == NULL) {
+		efx_filter_spec_t *new_spec;
 
-	EFSYS_LOCK(enp->en_eslp, state);
-	locked = B_TRUE;
+		EFSYS_UNLOCK(enp->en_eslp, state);
+		locked = B_FALSE;
 
-	if (replacing) {
-		/* Update the fields that may differ */
-		saved_spec->efs_priority = spec->efs_priority;
-		saved_spec->efs_flags = spec->efs_flags;
-		saved_spec->efs_rss_context = spec->efs_rss_context;
-		saved_spec->efs_dmaq_id = spec->efs_dmaq_id;
-	}
+		EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*new_spec), new_spec);
+		if (new_spec == NULL) {
+			rc = ENOMEM;
+			overridden_spec = NULL;
+			goto fail3;
+		}
 
-	ef10_filter_set_entry_not_busy(eftp, ins_index);
+		EFSYS_LOCK(enp->en_eslp, state);
+		locked = B_TRUE;
 
-out_unlock:
+		if (saved_spec == NULL) {
+			*new_spec = *spec;
+			ef10_filter_set_entry(eftp, ins_index, new_spec);
+		} else {
+			*new_spec = *overridden_spec;
+			overridden_spec = new_spec;
+		}
+	}
 
 	EFSYS_UNLOCK(enp->en_eslp, state);
 	locked = B_FALSE;
 
+	rc = ef10_filter_add_execute_action(enp, saved_spec, spec,
+	    overridden_spec, action, ins_index);
+	if (rc != 0)
+		goto fail4;
+
 	if (filter_id)
 		*filter_id = ins_index;
 
+	EFSYS_LOCK(enp->en_eslp, state);
+	ef10_filter_set_entry_not_busy(eftp, ins_index);
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
 	return (0);
 
 fail4:
 	EFSYS_PROBE(fail4);
 
-	if (!replacing) {
-		EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), saved_spec);
-		saved_spec = NULL;
+	EFSYS_ASSERT(locked == B_FALSE);
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	if (action == EF10_FILTER_ADD_NEW) {
+		EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec),
+		    ef10_filter_entry_spec(eftp, ins_index));
+		ef10_filter_set_entry(eftp, ins_index, NULL);
 	}
-	ef10_filter_set_entry_not_busy(eftp, ins_index);
-	ef10_filter_set_entry(eftp, ins_index, NULL);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
+	if (overridden_spec != NULL)
+		EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), overridden_spec);
 
 fail3:
 	EFSYS_PROBE(fail3);
 
+	EFSYS_ASSERT(locked == B_FALSE);
+	EFSYS_LOCK(enp->en_eslp, state);
+
+	ef10_filter_set_entry_not_busy(eftp, ins_index);
+
+	EFSYS_UNLOCK(enp->en_eslp, state);
+
 fail2:
 	EFSYS_PROBE(fail2);
 
@@ -783,11 +1001,11 @@ ef10_filter_add_internal(
 ef10_filter_add(
 	__in		efx_nic_t *enp,
 	__inout		efx_filter_spec_t *spec,
-	__in		boolean_t may_replace)
+	__in		enum efx_filter_replacement_policy_e policy)
 {
 	efx_rc_t rc;
 
-	rc = ef10_filter_add_internal(enp, spec, may_replace, NULL);
+	rc = ef10_filter_add_internal(enp, spec, policy, NULL);
 	if (rc != 0)
 		goto fail1;
 
@@ -799,11 +1017,15 @@ ef10_filter_add(
 	return (rc);
 }
 
-
+/*
+ * Delete a filter by index from the filter table with priority
+ * that is not higher than specified.
+ */
 static	__checkReturn	efx_rc_t
 ef10_filter_delete_internal(
 	__in		efx_nic_t *enp,
-	__in		uint32_t filter_id)
+	__in		uint32_t filter_id,
+	__in		efx_filter_priority_t priority)
 {
 	efx_rc_t rc;
 	ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
@@ -825,7 +1047,8 @@ ef10_filter_delete_internal(
 		EFSYS_LOCK(enp->en_eslp, state);
 	}
 	if ((spec = ef10_filter_entry_spec(table, filter_idx)) != NULL) {
-		ef10_filter_set_entry_busy(table, filter_idx);
+		if (spec->efs_priority <= priority)
+			ef10_filter_set_entry_busy(table, filter_idx);
 	}
 	EFSYS_UNLOCK(enp->en_eslp, state);
 
@@ -834,31 +1057,53 @@ ef10_filter_delete_internal(
 		goto fail1;
 	}
 
-	/*
-	 * Try to remove the hardware filter. This may fail if the MC has
-	 * rebooted (which frees all hardware filter resources).
-	 */
-	if (ef10_filter_is_exclusive(spec)) {
-		rc = efx_mcdi_filter_op_delete(enp,
-		    MC_CMD_FILTER_OP_IN_OP_REMOVE,
-		    &table->eft_entry[filter_idx].efe_handle);
+	if (spec->efs_priority > priority) {
+		/*
+		 * Applied filter stays, but overridden filter is removed since
+		 * next user request to delete the applied filter should not
+		 * restore outdated filter.
+		 */
+		if (spec->efs_overridden_spec != NULL) {
+			EFSYS_ASSERT(spec->efs_overridden_spec->efs_overridden_spec ==
+			    NULL);
+			EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec),
+			    spec->efs_overridden_spec);
+			spec->efs_overridden_spec = NULL;
+		}
 	} else {
-		rc = efx_mcdi_filter_op_delete(enp,
-		    MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE,
-		    &table->eft_entry[filter_idx].efe_handle);
-	}
+		/*
+		 * Try to remove the hardware filter or replace it with the
+		 * saved automatic filter. This may fail if the MC has
+		 * rebooted (which frees all hardware filter resources).
+		 */
+		if (spec->efs_overridden_spec != NULL) {
+			rc = efx_mcdi_filter_op_add(enp,
+			    spec->efs_overridden_spec,
+			    MC_CMD_FILTER_OP_IN_OP_REPLACE,
+			    &table->eft_entry[filter_idx].efe_handle);
+		} else if (ef10_filter_is_exclusive(spec)) {
+			rc = efx_mcdi_filter_op_delete(enp,
+			    MC_CMD_FILTER_OP_IN_OP_REMOVE,
+			    &table->eft_entry[filter_idx].efe_handle);
+		} else {
+			rc = efx_mcdi_filter_op_delete(enp,
+			    MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE,
+			    &table->eft_entry[filter_idx].efe_handle);
+		}
 
-	/* Free the software table entry */
-	EFSYS_LOCK(enp->en_eslp, state);
-	ef10_filter_set_entry_not_busy(table, filter_idx);
-	ef10_filter_set_entry(table, filter_idx, NULL);
-	EFSYS_UNLOCK(enp->en_eslp, state);
+		/* Free the software table entry */
+		EFSYS_LOCK(enp->en_eslp, state);
+		ef10_filter_set_entry_not_busy(table, filter_idx);
+		ef10_filter_set_entry(table, filter_idx,
+		    spec->efs_overridden_spec);
+		EFSYS_UNLOCK(enp->en_eslp, state);
 
-	EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
+		EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
 
-	/* Check result of hardware filter removal */
-	if (rc != 0)
-		goto fail2;
+		/* Check result of hardware filter removal */
+		if (rc != 0)
+			goto fail2;
+	}
 
 	return (0);
 
@@ -871,6 +1116,25 @@ ef10_filter_delete_internal(
 	return (rc);
 }
 
+static			void
+ef10_filter_delete_auto(
+	__in		efx_nic_t *enp,
+	__in		uint32_t filter_id)
+{
+	ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
+	uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS;
+
+	/*
+	 * AUTO_OLD flag is cleared since the auto filter that is to be removed
+	 * may not be the filter at the specified index itself, but the filter
+	 * that is overridden by it.
+	 */
+	ef10_filter_set_entry_not_auto_old(table, filter_idx);
+
+	(void) ef10_filter_delete_internal(enp, filter_idx,
+	    EFX_FILTER_PRI_AUTO);
+}
+
 	__checkReturn	efx_rc_t
 ef10_filter_delete(
 	__in		efx_nic_t *enp,
@@ -897,7 +1161,8 @@ ef10_filter_delete(
 		i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
 		saved_spec = ef10_filter_entry_spec(table, i);
 		if (saved_spec && ef10_filter_equal(spec, saved_spec) &&
-		    ef10_filter_same_dest(spec, saved_spec)) {
+		    ef10_filter_same_dest(spec, saved_spec) &&
+		    saved_spec->efs_priority == EFX_FILTER_PRI_MANUAL) {
 			break;
 		}
 		if (depth == EF10_FILTER_SEARCH_LIMIT) {
@@ -910,7 +1175,7 @@ ef10_filter_delete(
 	EFSYS_UNLOCK(enp->en_eslp, state);
 	locked = B_FALSE;
 
-	rc = ef10_filter_delete_internal(enp, i);
+	rc = ef10_filter_delete_internal(enp, i, EFX_FILTER_PRI_MANUAL);
 	if (rc != 0)
 		goto fail2;
 
@@ -1135,7 +1400,7 @@ ef10_filter_insert_unicast(
 	if (rc != 0)
 		goto fail1;
 
-	rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
+	rc = ef10_filter_add_internal(enp, &spec, EFX_FILTER_REPLACEMENT_NEVER,
 	    &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]);
 	if (rc != 0)
 		goto fail2;
@@ -1169,7 +1434,7 @@ ef10_filter_insert_all_unicast(
 	rc = efx_filter_spec_set_uc_def(&spec);
 	if (rc != 0)
 		goto fail1;
-	rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
+	rc = ef10_filter_add_internal(enp, &spec, EFX_FILTER_REPLACEMENT_NEVER,
 	    &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]);
 	if (rc != 0)
 		goto fail2;
@@ -1239,8 +1504,8 @@ ef10_filter_insert_multicast_list(
 			}
 		}
 
-		rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
-					    &filter_index);
+		rc = ef10_filter_add_internal(enp, &spec,
+		    EFX_FILTER_REPLACEMENT_NEVER, &filter_index);
 
 		if (rc == 0) {
 			eftp->eft_mulcst_filter_indexes[filter_count] =
@@ -1267,8 +1532,8 @@ ef10_filter_insert_multicast_list(
 			goto rollback;
 		}
 
-		rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
-					    &filter_index);
+		rc = ef10_filter_add_internal(enp, &spec,
+		    EFX_FILTER_REPLACEMENT_NEVER, &filter_index);
 
 		if (rc == 0) {
 			eftp->eft_mulcst_filter_indexes[filter_count] =
@@ -1289,7 +1554,7 @@ ef10_filter_insert_multicast_list(
 	/* Remove any filters we have inserted */
 	i = filter_count;
 	while (i--) {
-		(void) ef10_filter_delete_internal(enp,
+		ef10_filter_delete_auto(enp,
 		    eftp->eft_mulcst_filter_indexes[i]);
 	}
 	eftp->eft_mulcst_filter_count = 0;
@@ -1317,7 +1582,7 @@ ef10_filter_insert_all_multicast(
 	if (rc != 0)
 		goto fail1;
 
-	rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
+	rc = ef10_filter_add_internal(enp, &spec, EFX_FILTER_REPLACEMENT_NEVER,
 	    &eftp->eft_mulcst_filter_indexes[0]);
 	if (rc != 0)
 		goto fail2;
@@ -1420,8 +1685,9 @@ ef10_filter_insert_encap_filters(
 		if (rc != 0)
 			goto fail1;
 
-		rc = ef10_filter_add_internal(enp, &spec, B_TRUE,
-			    &table->eft_encap_filter_indexes[
+		rc = ef10_filter_add_internal(enp, &spec,
+		    EFX_FILTER_REPLACEMENT_NEVER,
+		    &table->eft_encap_filter_indexes[
 				    table->eft_encap_filter_count]);
 		if (rc != 0) {
 			if (rc != EACCES)
@@ -1450,7 +1716,7 @@ ef10_filter_remove_old(
 
 	for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) {
 		if (ef10_filter_entry_is_auto_old(table, i)) {
-			(void) ef10_filter_delete_internal(enp, i);
+			ef10_filter_delete_auto(enp, i);
 		}
 	}
 }
@@ -1525,19 +1791,19 @@ ef10_filter_reconfigure(
 		 * has rebooted, which removes hardware filters).
 		 */
 		for (i = 0; i < table->eft_unicst_filter_count; i++) {
-			(void) ef10_filter_delete_internal(enp,
+			ef10_filter_delete_auto(enp,
 					table->eft_unicst_filter_indexes[i]);
 		}
 		table->eft_unicst_filter_count = 0;
 
 		for (i = 0; i < table->eft_mulcst_filter_count; i++) {
-			(void) ef10_filter_delete_internal(enp,
+			ef10_filter_delete_auto(enp,
 					table->eft_mulcst_filter_indexes[i]);
 		}
 		table->eft_mulcst_filter_count = 0;
 
 		for (i = 0; i < table->eft_encap_filter_count; i++) {
-			(void) ef10_filter_delete_internal(enp,
+			ef10_filter_delete_auto(enp,
 					table->eft_encap_filter_indexes[i]);
 		}
 		table->eft_encap_filter_count = 0;
diff --git a/dpdk/drivers/net/sfc/base/ef10_impl.h b/dpdk/drivers/net/sfc/base/ef10_impl.h
index 7a00047829..67abf3b853 100644
--- a/dpdk/drivers/net/sfc/base/ef10_impl.h
+++ b/dpdk/drivers/net/sfc/base/ef10_impl.h
@@ -1079,6 +1079,8 @@ ef10_rx_fini(
 
 #if EFSYS_OPT_FILTER
 
+enum efx_filter_replacement_policy_e;
+
 typedef struct ef10_filter_handle_s {
 	uint32_t	efh_lo;
 	uint32_t	efh_hi;
@@ -1148,7 +1150,7 @@ ef10_filter_restore(
 ef10_filter_add(
 	__in		efx_nic_t *enp,
 	__inout		efx_filter_spec_t *spec,
-	__in		boolean_t may_replace);
+	__in		enum efx_filter_replacement_policy_e policy);
 
 	__checkReturn	efx_rc_t
 ef10_filter_delete(
diff --git a/dpdk/drivers/net/sfc/base/ef10_nic.c b/dpdk/drivers/net/sfc/base/ef10_nic.c
index b25ce1908e..3eb4674c5e 100644
--- a/dpdk/drivers/net/sfc/base/ef10_nic.c
+++ b/dpdk/drivers/net/sfc/base/ef10_nic.c
@@ -2288,9 +2288,7 @@ ef10_nic_init(
 	efx_rc_t rc;
 	boolean_t alloc_vadaptor = B_TRUE;
 
-	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-	    enp->en_family == EFX_FAMILY_MEDFORD ||
-	    enp->en_family == EFX_FAMILY_MEDFORD2);
+	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
 	/* Enable reporting of some events (e.g. link change) */
 	if ((rc = efx_mcdi_log_ctrl(enp)) != 0)
diff --git a/dpdk/drivers/net/sfc/base/ef10_proxy.c b/dpdk/drivers/net/sfc/base/ef10_proxy.c
index 059b2f5f4d..619d98e472 100644
--- a/dpdk/drivers/net/sfc/base/ef10_proxy.c
+++ b/dpdk/drivers/net/sfc/base/ef10_proxy.c
@@ -13,9 +13,7 @@
 ef10_proxy_auth_init(
 	__in		efx_nic_t *enp)
 {
-	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-		enp->en_family == EFX_FAMILY_MEDFORD ||
-		enp->en_family == EFX_FAMILY_MEDFORD2);
+	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 
 	return (0);
 }
@@ -24,9 +22,7 @@ ef10_proxy_auth_init(
 ef10_proxy_auth_fini(
 	__in		efx_nic_t *enp)
 {
-	EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
-		enp->en_family == EFX_FAMILY_MEDFORD ||
-		enp->en_family == EFX_FAMILY_MEDFORD2);
+	EFSYS_ASSERT(EFX_FAMILY_IS_EF10(enp));
 }
 
 static	__checkReturn	efx_rc_t
diff --git a/dpdk/drivers/net/sfc/base/efx.h b/dpdk/drivers/net/sfc/base/efx.h
index 53ddaa987c..d94d3c02f7 100644
--- a/dpdk/drivers/net/sfc/base/efx.h
+++ b/dpdk/drivers/net/sfc/base/efx.h
@@ -2949,17 +2949,15 @@ typedef uint8_t efx_filter_flags_t;
 
 typedef uint32_t efx_filter_match_flags_t;
 
+/* Filter priority from lowest to highest */
 typedef enum efx_filter_priority_s {
-	EFX_FILTER_PRI_HINT = 0,	/* Performance hint */
-	EFX_FILTER_PRI_AUTO,		/* Automatic filter based on device
+	EFX_FILTER_PRI_AUTO = 0,	/* Automatic filter based on device
 					 * address list or hardware
 					 * requirements. This may only be used
 					 * by the filter implementation for
 					 * each NIC type. */
 	EFX_FILTER_PRI_MANUAL,		/* Manually configured filter */
-	EFX_FILTER_PRI_REQUIRED,	/* Required for correct behaviour of the
-					 * client (e.g. SR-IOV, HyperV VMQ etc.)
-					 */
+	EFX_FILTER_NPRI,
 } efx_filter_priority_t;
 
 /*
@@ -2974,6 +2972,11 @@ typedef struct efx_filter_spec_s {
 	uint16_t			efs_dmaq_id;
 	uint32_t			efs_rss_context;
 	uint32_t			efs_mark;
+	/*
+	 * Saved lower-priority filter. If it is set, it is restored on
+	 * filter delete operation.
+	 */
+	struct efx_filter_spec_s	*efs_overridden_spec;
 	/* Fields below here are hashed for software filter lookup */
 	uint16_t			efs_outer_vid;
 	uint16_t			efs_inner_vid;
diff --git a/dpdk/drivers/net/sfc/base/efx_evb.c b/dpdk/drivers/net/sfc/base/efx_evb.c
index dd64bc7854..5fa0d99809 100644
--- a/dpdk/drivers/net/sfc/base/efx_evb.c
+++ b/dpdk/drivers/net/sfc/base/efx_evb.c
@@ -28,7 +28,7 @@ static const efx_evb_ops_t	__efx_evb_dummy_ops = {
 };
 #endif /* EFSYS_OPT_SIENA */
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
 static const efx_evb_ops_t	__efx_evb_ef10_ops = {
 	ef10_evb_init,			/* eeo_init */
 	ef10_evb_fini,			/* eeo_fini */
@@ -44,7 +44,7 @@ static const efx_evb_ops_t	__efx_evb_ef10_ops = {
 	ef10_evb_vport_reconfigure,	/* eeo_vport_reconfigure */
 	ef10_evb_vport_stats,		/* eeo_vport_stats */
 };
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
 
 	__checkReturn	efx_rc_t
 efx_evb_init(
diff --git a/dpdk/drivers/net/sfc/base/efx_filter.c b/dpdk/drivers/net/sfc/base/efx_filter.c
index 7efb380641..9949d05bb3 100644
--- a/dpdk/drivers/net/sfc/base/efx_filter.c
+++ b/dpdk/drivers/net/sfc/base/efx_filter.c
@@ -28,7 +28,7 @@ static	__checkReturn	efx_rc_t
 siena_filter_add(
 	__in		efx_nic_t *enp,
 	__inout		efx_filter_spec_t *spec,
-	__in		boolean_t may_replace);
+	__in		efx_filter_replacement_policy_t policy);
 
 static	__checkReturn	efx_rc_t
 siena_filter_delete(
@@ -93,8 +93,16 @@ efx_filter_insert(
 		goto fail2;
 	}
 
-	return (efop->efo_add(enp, spec, B_FALSE));
+	if (spec->efs_priority == EFX_FILTER_PRI_AUTO) {
+		rc = EINVAL;
+		goto fail3;
+	}
 
+	return (efop->efo_add(enp, spec,
+	    EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY));
+
+fail3:
+	EFSYS_PROBE(fail3);
 fail2:
 	EFSYS_PROBE(fail2);
 fail1:
@@ -314,7 +322,7 @@ efx_filter_spec_init_tx(
 	EFSYS_ASSERT3P(etp, !=, NULL);
 
 	memset(spec, 0, sizeof (*spec));
-	spec->efs_priority = EFX_FILTER_PRI_REQUIRED;
+	spec->efs_priority = EFX_FILTER_PRI_MANUAL;
 	spec->efs_flags = EFX_FILTER_FLAG_TX;
 	spec->efs_dmaq_id = (uint16_t)etp->et_index;
 }
@@ -1437,7 +1445,7 @@ static	 __checkReturn	efx_rc_t
 siena_filter_add(
 	__in		efx_nic_t *enp,
 	__inout		efx_filter_spec_t *spec,
-	__in		boolean_t may_replace)
+	__in		efx_filter_replacement_policy_t policy)
 {
 	efx_rc_t rc;
 	siena_filter_spec_t sf_spec;
@@ -1478,9 +1486,17 @@ siena_filter_add(
 	saved_sf_spec = &sftp->sft_spec[filter_idx];
 
 	if (siena_filter_test_used(sftp, filter_idx)) {
-		if (may_replace == B_FALSE) {
+		/* All Siena filter are considered the same priority */
+		switch (policy) {
+		case EFX_FILTER_REPLACEMENT_NEVER:
+		case EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY:
 			rc = EEXIST;
 			goto fail4;
+		case EFX_FILTER_REPLACEMENT_HIGHER_OR_EQUAL_PRIORITY:
+			break;
+		default:
+			EFSYS_ASSERT(0);
+			break;
 		}
 	}
 	siena_filter_set_used(sftp, filter_idx);
diff --git a/dpdk/drivers/net/sfc/base/efx_impl.h b/dpdk/drivers/net/sfc/base/efx_impl.h
index 85d984f651..9755f4dfd2 100644
--- a/dpdk/drivers/net/sfc/base/efx_impl.h
+++ b/dpdk/drivers/net/sfc/base/efx_impl.h
@@ -246,12 +246,31 @@ typedef struct efx_phy_ops_s {
 } efx_phy_ops_t;
 
 #if EFSYS_OPT_FILTER
+
+/*
+ * Policy for replacing existing filter when inserting a new one.
+ * Note that all policies allow for storing the new lower priority
+ * filters as overridden by existing higher priority ones. It is needed
+ * to restore the lower priority filters on higher priority ones removal.
+ */
+typedef enum efx_filter_replacement_policy_e {
+	/* Cannot replace existing filter */
+	EFX_FILTER_REPLACEMENT_NEVER,
+	/* Higher priority filters can replace lower priotiry ones */
+	EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY,
+	/*
+	 * Higher priority filters can replace lower priority ones and
+	 * equal priority filters can replace each other.
+	 */
+	EFX_FILTER_REPLACEMENT_HIGHER_OR_EQUAL_PRIORITY,
+} efx_filter_replacement_policy_t;
+
 typedef struct efx_filter_ops_s {
 	efx_rc_t	(*efo_init)(efx_nic_t *);
 	void		(*efo_fini)(efx_nic_t *);
 	efx_rc_t	(*efo_restore)(efx_nic_t *);
 	efx_rc_t	(*efo_add)(efx_nic_t *, efx_filter_spec_t *,
-				   boolean_t may_replace);
+				   efx_filter_replacement_policy_t policy);
 	efx_rc_t	(*efo_delete)(efx_nic_t *, efx_filter_spec_t *);
 	efx_rc_t	(*efo_supported_filters)(efx_nic_t *, uint32_t *,
 				   size_t, size_t *);
diff --git a/dpdk/drivers/net/sfc/base/efx_proxy.c b/dpdk/drivers/net/sfc/base/efx_proxy.c
index 791105a5a0..ecf703b03d 100644
--- a/dpdk/drivers/net/sfc/base/efx_proxy.c
+++ b/dpdk/drivers/net/sfc/base/efx_proxy.c
@@ -23,7 +23,7 @@ static const efx_proxy_ops_t	__efx_proxy_dummy_ops = {
 };
 #endif /* EFSYS_OPT_SIENA */
 
-#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
+#if EFX_OPTS_EF10()
 static const efx_proxy_ops_t			__efx_proxy_ef10_ops = {
 	ef10_proxy_auth_init,			/* epo_init */
 	ef10_proxy_auth_fini,			/* epo_fini */
@@ -35,7 +35,7 @@ static const efx_proxy_ops_t			__efx_proxy_ef10_ops = {
 	ef10_proxy_auth_exec_cmd,		/* epo_exec_cmd */
 	ef10_proxy_auth_get_privilege_mask,	/* epo_get_privilege_mask */
 };
-#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
+#endif /* EFX_OPTS_EF10() */
 
 	__checkReturn	efx_rc_t
 efx_proxy_auth_init(
diff --git a/dpdk/drivers/net/sfc/base/efx_tunnel.c b/dpdk/drivers/net/sfc/base/efx_tunnel.c
index edb6be028f..c92c02cfa2 100644
--- a/dpdk/drivers/net/sfc/base/efx_tunnel.c
+++ b/dpdk/drivers/net/sfc/base/efx_tunnel.c
@@ -421,7 +421,7 @@ ef10_tunnel_reconfigure(
 {
 	efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
 	efx_rc_t rc;
-	boolean_t resetting;
+	boolean_t resetting = B_FALSE;
 	efsys_lock_state_t state;
 	efx_tunnel_cfg_t etc;
 
@@ -446,8 +446,14 @@ ef10_tunnel_reconfigure(
 		 */
 		rc = efx_mcdi_set_tunnel_encap_udp_ports(enp, &etc, B_FALSE,
 		    &resetting);
-		if (rc != 0)
-			goto fail2;
+		if (rc != 0) {
+			/*
+			 * Do not fail if the access is denied when no
+			 * tunnel encap UDP ports are configured.
+			 */
+			if (rc != EACCES || etc.etc_udp_entries_num != 0)
+				goto fail2;
+		}
 
 		/*
 		 * Although the caller should be able to handle MC reboot,
diff --git a/dpdk/drivers/net/sfc/sfc.c b/dpdk/drivers/net/sfc/sfc.c
index 141c767f09..da67acaa87 100644
--- a/dpdk/drivers/net/sfc/sfc.c
+++ b/dpdk/drivers/net/sfc/sfc.c
@@ -30,7 +30,7 @@ sfc_dma_alloc(const struct sfc_adapter *sa, const char *name, uint16_t id,
 {
 	const struct rte_memzone *mz;
 
-	sfc_log_init(sa, "name=%s id=%u len=%lu socket_id=%d",
+	sfc_log_init(sa, "name=%s id=%u len=%zu socket_id=%d",
 		     name, id, len, socket_id);
 
 	mz = rte_eth_dma_zone_reserve(sa->eth_dev, name, id, len,
@@ -241,8 +241,8 @@ sfc_estimate_resource_limits(struct sfc_adapter *sa)
 	return 0;
 
 fail_get_vi_pool:
-fail_nic_init:
 	efx_nic_fini(sa->nic);
+fail_nic_init:
 	return rc;
 }
 
@@ -684,6 +684,7 @@ sfc_rss_attach(struct sfc_adapter *sa)
 	efx_intr_fini(sa->nic);
 
 	rte_memcpy(rss->key, default_rss_key, sizeof(rss->key));
+	rss->dummy_rss_context = EFX_RSS_CONTEXT_DEFAULT;
 
 	return 0;
 
diff --git a/dpdk/drivers/net/sfc/sfc.h b/dpdk/drivers/net/sfc/sfc.h
index cc52228771..bce6beefaa 100644
--- a/dpdk/drivers/net/sfc/sfc.h
+++ b/dpdk/drivers/net/sfc/sfc.h
@@ -172,6 +172,8 @@ struct sfc_rss {
 	efx_rx_hash_type_t		hash_types;
 	unsigned int			tbl[EFX_RSS_TBL_SIZE];
 	uint8_t				key[EFX_RSS_KEY_SIZE];
+
+	uint32_t			dummy_rss_context;
 };
 
 /* Adapter private data shared by primary and secondary processes */
diff --git a/dpdk/drivers/net/sfc/sfc_ef10_tx.c b/dpdk/drivers/net/sfc/sfc_ef10_tx.c
index 43e3447805..b57c9afb71 100644
--- a/dpdk/drivers/net/sfc/sfc_ef10_tx.c
+++ b/dpdk/drivers/net/sfc/sfc_ef10_tx.c
@@ -477,6 +477,25 @@ sfc_ef10_xmit_tso_pkt(struct sfc_ef10_txq * const txq, struct rte_mbuf *m_seg,
 			needed_desc--;
 	}
 
+	/*
+	 * 8000-series EF10 hardware requires that innermost IP length
+	 * be greater than or equal to the value which each segment is
+	 * supposed to have; otherwise, TCP checksum will be incorrect.
+	 *
+	 * The same concern applies to outer UDP datagram length field.
+	 */
+	switch (m_seg->ol_flags & PKT_TX_TUNNEL_MASK) {
+	case PKT_TX_TUNNEL_VXLAN:
+		/* FALLTHROUGH */
+	case PKT_TX_TUNNEL_GENEVE:
+		sfc_tso_outer_udp_fix_len(first_m_seg, hdr_addr);
+		break;
+	default:
+		break;
+	}
+
+	sfc_tso_innermost_ip_fix_len(first_m_seg, hdr_addr, iph_off);
+
 	/*
 	 * Tx prepare has debug-only checks that offload flags are correctly
 	 * filled in in TSO mbuf. Use zero IPID if there is no IPv4 flag.
diff --git a/dpdk/drivers/net/sfc/sfc_ethdev.c b/dpdk/drivers/net/sfc/sfc_ethdev.c
index 454b8956a2..cc7eefb322 100644
--- a/dpdk/drivers/net/sfc/sfc_ethdev.c
+++ b/dpdk/drivers/net/sfc/sfc_ethdev.c
@@ -405,25 +405,37 @@ sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
 static int
 sfc_dev_promisc_enable(struct rte_eth_dev *dev)
 {
-	return sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_TRUE);
+	int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_TRUE);
+
+	SFC_ASSERT(rc >= 0);
+	return -rc;
 }
 
 static int
 sfc_dev_promisc_disable(struct rte_eth_dev *dev)
 {
-	return sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_FALSE);
+	int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_FALSE);
+
+	SFC_ASSERT(rc >= 0);
+	return -rc;
 }
 
 static int
 sfc_dev_allmulti_enable(struct rte_eth_dev *dev)
 {
-	return sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_TRUE);
+	int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_TRUE);
+
+	SFC_ASSERT(rc >= 0);
+	return -rc;
 }
 
 static int
 sfc_dev_allmulti_disable(struct rte_eth_dev *dev)
 {
-	return sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_FALSE);
+	int rc = sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_FALSE);
+
+	SFC_ASSERT(rc >= 0);
+	return -rc;
 }
 
 static int
@@ -596,10 +608,19 @@ sfc_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 			mac_stats[EFX_MAC_VADAPTER_TX_BROADCAST_BYTES];
 		stats->imissed = mac_stats[EFX_MAC_VADAPTER_RX_BAD_PACKETS];
 		stats->oerrors = mac_stats[EFX_MAC_VADAPTER_TX_BAD_PACKETS];
+
+		/* CRC is included in these stats, but shouldn't be */
+		stats->ibytes -= stats->ipackets * RTE_ETHER_CRC_LEN;
+		stats->obytes -= stats->opackets * RTE_ETHER_CRC_LEN;
 	} else {
 		stats->opackets = mac_stats[EFX_MAC_TX_PKTS];
 		stats->ibytes = mac_stats[EFX_MAC_RX_OCTETS];
 		stats->obytes = mac_stats[EFX_MAC_TX_OCTETS];
+
+		/* CRC is included in these stats, but shouldn't be */
+		stats->ibytes -= mac_stats[EFX_MAC_RX_PKTS] * RTE_ETHER_CRC_LEN;
+		stats->obytes -= mac_stats[EFX_MAC_TX_PKTS] * RTE_ETHER_CRC_LEN;
+
 		/*
 		 * Take into account stats which are whenever supported
 		 * on EF10. If some stat is not supported by current
@@ -972,7 +993,7 @@ sfc_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 	 * The driver does not use it, but other PMDs update jumbo frame
 	 * flag and max_rx_pkt_len when MTU is set.
 	 */
-	if (mtu > RTE_ETHER_MAX_LEN) {
+	if (mtu > RTE_ETHER_MTU) {
 		struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
 		rxmode->offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
 	}
@@ -1503,8 +1524,15 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
 	struct sfc_rss *rss = &sfc_sa2shared(sa)->rss;
 	unsigned int efx_hash_types;
+	uint32_t contexts[] = {EFX_RSS_CONTEXT_DEFAULT, rss->dummy_rss_context};
+	unsigned int n_contexts;
+	unsigned int mode_i = 0;
+	unsigned int key_i = 0;
+	unsigned int i = 0;
 	int rc = 0;
 
+	n_contexts = rss->dummy_rss_context == EFX_RSS_CONTEXT_DEFAULT ? 1 : 2;
+
 	if (sfc_sa2shared(sa)->isolated)
 		return -ENOTSUP;
 
@@ -1520,7 +1548,7 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
 
 	if ((rss_conf->rss_key != NULL) &&
 	    (rss_conf->rss_key_len != sizeof(rss->key))) {
-		sfc_err(sa, "RSS key size is wrong (should be %lu)",
+		sfc_err(sa, "RSS key size is wrong (should be %zu)",
 			sizeof(rss->key));
 		return -EINVAL;
 	}
@@ -1531,19 +1559,24 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
 	if (rc != 0)
 		goto fail_rx_hf_rte_to_efx;
 
-	rc = efx_rx_scale_mode_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT,
-				   rss->hash_alg, efx_hash_types, B_TRUE);
-	if (rc != 0)
-		goto fail_scale_mode_set;
+	for (mode_i = 0; mode_i < n_contexts; mode_i++) {
+		rc = efx_rx_scale_mode_set(sa->nic, contexts[mode_i],
+					   rss->hash_alg, efx_hash_types,
+					   B_TRUE);
+		if (rc != 0)
+			goto fail_scale_mode_set;
+	}
 
 	if (rss_conf->rss_key != NULL) {
 		if (sa->state == SFC_ADAPTER_STARTED) {
-			rc = efx_rx_scale_key_set(sa->nic,
-						  EFX_RSS_CONTEXT_DEFAULT,
-						  rss_conf->rss_key,
-						  sizeof(rss->key));
-			if (rc != 0)
-				goto fail_scale_key_set;
+			for (key_i = 0; key_i < n_contexts; key_i++) {
+				rc = efx_rx_scale_key_set(sa->nic,
+							  contexts[key_i],
+							  rss_conf->rss_key,
+							  sizeof(rss->key));
+				if (rc != 0)
+					goto fail_scale_key_set;
+			}
 		}
 
 		rte_memcpy(rss->key, rss_conf->rss_key, sizeof(rss->key));
@@ -1556,12 +1589,20 @@ sfc_dev_rss_hash_update(struct rte_eth_dev *dev,
 	return 0;
 
 fail_scale_key_set:
-	if (efx_rx_scale_mode_set(sa->nic, EFX_RSS_CONTEXT_DEFAULT,
-				  EFX_RX_HASHALG_TOEPLITZ,
-				  rss->hash_types, B_TRUE) != 0)
-		sfc_err(sa, "failed to restore RSS mode");
+	for (i = 0; i < key_i; i++) {
+		if (efx_rx_scale_key_set(sa->nic, contexts[i], rss->key,
+					 sizeof(rss->key)) != 0)
+			sfc_err(sa, "failed to restore RSS key");
+	}
 
 fail_scale_mode_set:
+	for (i = 0; i < mode_i; i++) {
+		if (efx_rx_scale_mode_set(sa->nic, contexts[i],
+					  EFX_RX_HASHALG_TOEPLITZ,
+					  rss->hash_types, B_TRUE) != 0)
+			sfc_err(sa, "failed to restore RSS mode");
+	}
+
 fail_rx_hf_rte_to_efx:
 	sfc_adapter_unlock(sa);
 	return -rc;
diff --git a/dpdk/drivers/net/sfc/sfc_flow.c b/dpdk/drivers/net/sfc/sfc_flow.c
index 8d636f6923..91aa2a687a 100644
--- a/dpdk/drivers/net/sfc/sfc_flow.c
+++ b/dpdk/drivers/net/sfc/sfc_flow.c
@@ -1132,6 +1132,7 @@ sfc_flow_parse_attr(const struct rte_flow_attr *attr,
 
 	flow->spec.template.efs_flags |= EFX_FILTER_FLAG_RX;
 	flow->spec.template.efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
+	flow->spec.template.efs_priority = EFX_FILTER_PRI_MANUAL;
 
 	return 0;
 }
@@ -1239,6 +1240,7 @@ sfc_flow_parse_queue(struct sfc_adapter *sa,
 		     struct rte_flow *flow)
 {
 	struct sfc_rxq *rxq;
+	struct sfc_rxq_info *rxq_info;
 
 	if (queue->index >= sfc_sa2shared(sa)->rxq_count)
 		return -EINVAL;
@@ -1246,6 +1248,10 @@ sfc_flow_parse_queue(struct sfc_adapter *sa,
 	rxq = &sa->rxq_ctrl[queue->index];
 	flow->spec.template.efs_dmaq_id = (uint16_t)rxq->hw_index;
 
+	rxq_info = &sfc_sa2shared(sa)->rxq_info[queue->index];
+	flow->spec.rss_hash_required = !!(rxq_info->rxq_flags &
+					    SFC_RXQ_FLAG_RSS_HASH);
+
 	return 0;
 }
 
@@ -1404,13 +1410,34 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 	struct sfc_rss *rss = &sas->rss;
 	struct sfc_flow_rss *flow_rss = &flow->rss_conf;
 	uint32_t efs_rss_context = EFX_RSS_CONTEXT_DEFAULT;
+	boolean_t create_context;
 	unsigned int i;
 	int rc = 0;
 
-	if (flow->rss) {
-		unsigned int rss_spread = MIN(flow_rss->rxq_hw_index_max -
-					      flow_rss->rxq_hw_index_min + 1,
-					      EFX_MAXRSS);
+	create_context = flow->rss || (flow->spec.rss_hash_required &&
+			rss->dummy_rss_context == EFX_RSS_CONTEXT_DEFAULT);
+
+	if (create_context) {
+		unsigned int rss_spread;
+		unsigned int rss_hash_types;
+		uint8_t *rss_key;
+
+		if (flow->rss) {
+			rss_spread = MIN(flow_rss->rxq_hw_index_max -
+					flow_rss->rxq_hw_index_min + 1,
+					EFX_MAXRSS);
+			rss_hash_types = flow_rss->rss_hash_types;
+			rss_key = flow_rss->rss_key;
+		} else {
+			/*
+			 * Initialize dummy RSS context parameters to have
+			 * valid RSS hash. Use default RSS hash function and
+			 * key.
+			 */
+			rss_spread = 1;
+			rss_hash_types = rss->hash_types;
+			rss_key = rss->key;
+		}
 
 		rc = efx_rx_scale_context_alloc(sa->nic,
 						EFX_RX_SCALE_EXCLUSIVE,
@@ -1421,16 +1448,19 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 
 		rc = efx_rx_scale_mode_set(sa->nic, efs_rss_context,
 					   rss->hash_alg,
-					   flow_rss->rss_hash_types, B_TRUE);
+					   rss_hash_types, B_TRUE);
 		if (rc != 0)
 			goto fail_scale_mode_set;
 
 		rc = efx_rx_scale_key_set(sa->nic, efs_rss_context,
-					  flow_rss->rss_key,
-					  sizeof(rss->key));
+					  rss_key, sizeof(rss->key));
 		if (rc != 0)
 			goto fail_scale_key_set;
+	} else {
+		efs_rss_context = rss->dummy_rss_context;
+	}
 
+	if (flow->rss || flow->spec.rss_hash_required) {
 		/*
 		 * At this point, fully elaborated filter specifications
 		 * have been produced from the template. To make sure that
@@ -1441,8 +1471,9 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 			efx_filter_spec_t *spec = &flow->spec.filters[i];
 
 			spec->efs_rss_context = efs_rss_context;
-			spec->efs_dmaq_id = flow_rss->rxq_hw_index_min;
 			spec->efs_flags |= EFX_FILTER_FLAG_RX_RSS;
+			if (flow->rss)
+				spec->efs_dmaq_id = flow_rss->rxq_hw_index_min;
 		}
 	}
 
@@ -1450,7 +1481,12 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 	if (rc != 0)
 		goto fail_filter_insert;
 
-	if (flow->rss) {
+	if (create_context) {
+		unsigned int dummy_tbl[RTE_DIM(flow_rss->rss_tbl)] = {0};
+		unsigned int *tbl;
+
+		tbl = flow->rss ? flow_rss->rss_tbl : dummy_tbl;
+
 		/*
 		 * Scale table is set after filter insertion because
 		 * the table entries are relative to the base RxQ ID
@@ -1460,10 +1496,13 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 		 * the table entries, and the operation will succeed
 		 */
 		rc = efx_rx_scale_tbl_set(sa->nic, efs_rss_context,
-					  flow_rss->rss_tbl,
-					  RTE_DIM(flow_rss->rss_tbl));
+					  tbl, RTE_DIM(flow_rss->rss_tbl));
 		if (rc != 0)
 			goto fail_scale_tbl_set;
+
+		/* Remember created dummy RSS context */
+		if (!flow->rss)
+			rss->dummy_rss_context = efs_rss_context;
 	}
 
 	return 0;
@@ -1474,7 +1513,7 @@ sfc_flow_filter_insert(struct sfc_adapter *sa,
 fail_filter_insert:
 fail_scale_key_set:
 fail_scale_mode_set:
-	if (efs_rss_context != EFX_RSS_CONTEXT_DEFAULT)
+	if (create_context)
 		efx_rx_scale_context_free(sa->nic, efs_rss_context);
 
 fail_scale_context_alloc:
@@ -2473,12 +2512,19 @@ sfc_flow_fini(struct sfc_adapter *sa)
 void
 sfc_flow_stop(struct sfc_adapter *sa)
 {
+	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+	struct sfc_rss *rss = &sas->rss;
 	struct rte_flow *flow;
 
 	SFC_ASSERT(sfc_adapter_is_locked(sa));
 
 	TAILQ_FOREACH(flow, &sa->filter.flow_list, entries)
 		sfc_flow_filter_remove(sa, flow);
+
+	if (rss->dummy_rss_context != EFX_RSS_CONTEXT_DEFAULT) {
+		efx_rx_scale_context_free(sa->nic, rss->dummy_rss_context);
+		rss->dummy_rss_context = EFX_RSS_CONTEXT_DEFAULT;
+	}
 }
 
 int
diff --git a/dpdk/drivers/net/sfc/sfc_flow.h b/dpdk/drivers/net/sfc/sfc_flow.h
index 71ec18cb95..f59db0a468 100644
--- a/dpdk/drivers/net/sfc/sfc_flow.h
+++ b/dpdk/drivers/net/sfc/sfc_flow.h
@@ -43,6 +43,8 @@ struct sfc_flow_spec {
 	efx_filter_spec_t filters[SF_FLOW_SPEC_NB_FILTERS_MAX];
 	/* number of complete specifications */
 	unsigned int count;
+	/* RSS hash toggle */
+	boolean_t rss_hash_required;
 };
 
 /* PMD-specific definition of the opaque type from rte_flow.h */
diff --git a/dpdk/drivers/net/sfc/sfc_rx.c b/dpdk/drivers/net/sfc/sfc_rx.c
index 74218296cd..9a1c368328 100644
--- a/dpdk/drivers/net/sfc/sfc_rx.c
+++ b/dpdk/drivers/net/sfc/sfc_rx.c
@@ -719,6 +719,7 @@ sfc_rx_default_rxq_set_filter(struct sfc_adapter *sa, struct sfc_rxq *rxq)
 		sfc_warn(sa, "promiscuous mode will be disabled");
 
 		port->promisc = B_FALSE;
+		sa->eth_dev->data->promiscuous = 0;
 		rc = sfc_set_rx_mode(sa);
 		if (rc != 0)
 			return rc;
@@ -732,6 +733,7 @@ sfc_rx_default_rxq_set_filter(struct sfc_adapter *sa, struct sfc_rxq *rxq)
 		sfc_warn(sa, "all-multicast mode will be disabled");
 
 		port->allmulti = B_FALSE;
+		sa->eth_dev->data->all_multicast = 0;
 		rc = sfc_set_rx_mode(sa);
 		if (rc != 0)
 			return rc;
@@ -820,10 +822,12 @@ sfc_rx_qstart(struct sfc_adapter *sa, unsigned int sw_index)
 	return 0;
 
 fail_mac_filter_default_rxq_set:
+	sfc_rx_qflush(sa, sw_index);
 	sa->priv.dp_rx->qstop(rxq_info->dp, &rxq->evq->read_ptr);
+	rxq_info->state = SFC_RXQ_INITIALIZED;
 
 fail_dp_qstart:
-	sfc_rx_qflush(sa, sw_index);
+	efx_rx_qdestroy(rxq->common);
 
 fail_rx_qcreate:
 fail_bad_contig_block_size:
@@ -1135,6 +1139,13 @@ sfc_rx_qinit(struct sfc_adapter *sa, unsigned int sw_index,
 	rxq_info->refill_threshold =
 		RTE_MAX(rx_free_thresh, SFC_RX_REFILL_BULK);
 	rxq_info->refill_mb_pool = mb_pool;
+
+	if (rss->hash_support == EFX_RX_HASH_AVAILABLE && rss->channels > 0 &&
+	    (offloads & DEV_RX_OFFLOAD_RSS_HASH))
+		rxq_info->rxq_flags = SFC_RXQ_FLAG_RSS_HASH;
+	else
+		rxq_info->rxq_flags = 0;
+
 	rxq->buf_size = buf_size;
 
 	rc = sfc_dma_alloc(sa, "rxq", sw_index,
@@ -1150,10 +1161,7 @@ sfc_rx_qinit(struct sfc_adapter *sa, unsigned int sw_index,
 	info.buf_size = buf_size;
 	info.batch_max = encp->enc_rx_batch_max;
 	info.prefix_size = encp->enc_rx_prefix_size;
-
-	if (rss->hash_support == EFX_RX_HASH_AVAILABLE && rss->channels > 0)
-		info.flags |= SFC_RXQ_FLAG_RSS_HASH;
-
+	info.flags = rxq_info->rxq_flags;
 	info.rxq_entries = rxq_info->entries;
 	info.rxq_hw_ring = rxq->mem.esm_base;
 	info.evq_hw_index = sfc_evq_index_by_rxq_sw_index(sa, sw_index);
@@ -1403,7 +1411,7 @@ sfc_rx_process_adv_conf_rss(struct sfc_adapter *sa,
 
 	if (conf->rss_key != NULL) {
 		if (conf->rss_key_len != sizeof(rss->key)) {
-			sfc_err(sa, "RSS key size is wrong (should be %lu)",
+			sfc_err(sa, "RSS key size is wrong (should be %zu)",
 				sizeof(rss->key));
 			return EINVAL;
 		}
@@ -1557,10 +1565,6 @@ sfc_rx_check_mode(struct sfc_adapter *sa, struct rte_eth_rxmode *rxmode)
 		rxmode->offloads |= DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM;
 	}
 
-	if ((offloads_supported & DEV_RX_OFFLOAD_RSS_HASH) &&
-	    (rxmode->mq_mode & ETH_MQ_RX_RSS_FLAG))
-		rxmode->offloads |= DEV_RX_OFFLOAD_RSS_HASH;
-
 	return rc;
 }
 
diff --git a/dpdk/drivers/net/sfc/sfc_rx.h b/dpdk/drivers/net/sfc/sfc_rx.h
index 42b16e2ee6..4c31cfbaa2 100644
--- a/dpdk/drivers/net/sfc/sfc_rx.h
+++ b/dpdk/drivers/net/sfc/sfc_rx.h
@@ -115,6 +115,7 @@ struct sfc_rxq_info {
 	boolean_t		deferred_started;
 	unsigned int		refill_threshold;
 	struct rte_mempool	*refill_mb_pool;
+	unsigned int		rxq_flags;
 };
 
 struct sfc_rxq_info *sfc_rxq_info_by_dp_rxq(const struct sfc_dp_rxq *dp_rxq);
diff --git a/dpdk/drivers/net/sfc/sfc_tso.c b/dpdk/drivers/net/sfc/sfc_tso.c
index 2e34fc0450..b1949004bb 100644
--- a/dpdk/drivers/net/sfc/sfc_tso.c
+++ b/dpdk/drivers/net/sfc/sfc_tso.c
@@ -140,6 +140,13 @@ sfc_efx_tso_do(struct sfc_efx_txq *txq, unsigned int idx,
 		tsoh = rte_pktmbuf_mtod(m, uint8_t *);
 	}
 
+	/*
+	 * 8000-series EF10 hardware requires that innermost IP length
+	 * be greater than or equal to the value which each segment is
+	 * supposed to have; otherwise, TCP checksum will be incorrect.
+	 */
+	sfc_tso_innermost_ip_fix_len(m, tsoh, nh_off);
+
 	/*
 	 * Handle IP header. Tx prepare has debug-only checks that offload flags
 	 * are correctly filled in in TSO mbuf. Use zero IPID if there is no
diff --git a/dpdk/drivers/net/sfc/sfc_tso.h b/dpdk/drivers/net/sfc/sfc_tso.h
index ef257519ac..3d1c3e46c3 100644
--- a/dpdk/drivers/net/sfc/sfc_tso.h
+++ b/dpdk/drivers/net/sfc/sfc_tso.h
@@ -38,6 +38,36 @@ sfc_tso_ip4_get_ipid(const uint8_t *pkt_hdrp, size_t ip_hdr_off)
 	return rte_be_to_cpu_16(ipid);
 }
 
+static inline void
+sfc_tso_outer_udp_fix_len(const struct rte_mbuf *m, uint8_t *tsoh)
+{
+	rte_be16_t len = rte_cpu_to_be_16(m->l2_len + m->l3_len + m->l4_len +
+					  m->tso_segsz);
+
+	rte_memcpy(tsoh + m->outer_l2_len + m->outer_l3_len +
+		   offsetof(struct rte_udp_hdr, dgram_len),
+		   &len, sizeof(len));
+}
+
+static inline void
+sfc_tso_innermost_ip_fix_len(const struct rte_mbuf *m, uint8_t *tsoh,
+			     size_t iph_ofst)
+{
+	size_t ip_payload_len = m->l4_len + m->tso_segsz;
+	size_t field_ofst;
+	rte_be16_t len;
+
+	if (m->ol_flags & PKT_TX_IPV4) {
+		field_ofst = offsetof(struct rte_ipv4_hdr, total_length);
+		len = rte_cpu_to_be_16(m->l3_len + ip_payload_len);
+	} else {
+		field_ofst = offsetof(struct rte_ipv6_hdr, payload_len);
+		len = rte_cpu_to_be_16(ip_payload_len);
+	}
+
+	rte_memcpy(tsoh + iph_ofst + field_ofst, &len, sizeof(len));
+}
+
 unsigned int sfc_tso_prepare_header(uint8_t *tsoh, size_t header_len,
 				    struct rte_mbuf **in_seg, size_t *in_off);
 
diff --git a/dpdk/drivers/net/softnic/parser.c b/dpdk/drivers/net/softnic/parser.c
index dc15ec8aa2..ebcb10268a 100644
--- a/dpdk/drivers/net/softnic/parser.c
+++ b/dpdk/drivers/net/softnic/parser.c
@@ -4,24 +4,6 @@
  * All rights reserved.
  */
 
-/* For inet_pton4() and inet_pton6() functions:
- *
- * Copyright (c) 1996 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -33,6 +15,8 @@
 #include <libgen.h>
 #include <unistd.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
 
 #include <rte_errno.h>
 
@@ -364,170 +348,6 @@ softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
 	return 0;
 }
 
-#define INADDRSZ 4
-#define IN6ADDRSZ 16
-
-/* int
- * inet_pton4(src, dst)
- *      like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- *      1 if `src' is a valid dotted quad, else 0.
- * notice:
- *      does not touch `dst' unless it's returning 1.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton4(const char *src, unsigned char *dst)
-{
-	static const char digits[] = "0123456789";
-	int saw_digit, octets, ch;
-	unsigned char tmp[INADDRSZ], *tp;
-
-	saw_digit = 0;
-	octets = 0;
-	*(tp = tmp) = 0;
-	while ((ch = *src++) != '\0') {
-		const char *pch;
-
-		pch = strchr(digits, ch);
-		if (pch != NULL) {
-			unsigned int new = *tp * 10 + (pch - digits);
-
-			if (new > 255)
-				return 0;
-			if (!saw_digit) {
-				if (++octets > 4)
-					return 0;
-				saw_digit = 1;
-			}
-			*tp = (unsigned char)new;
-		} else if (ch == '.' && saw_digit) {
-			if (octets == 4)
-				return 0;
-			*++tp = 0;
-			saw_digit = 0;
-		} else
-			return 0;
-	}
-	if (octets < 4)
-		return 0;
-
-	memcpy(dst, tmp, INADDRSZ);
-	return 1;
-}
-
-/* int
- * inet_pton6(src, dst)
- *      convert presentation level address to network order binary form.
- * return:
- *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- *      (1) does not touch `dst' unless it's returning 1.
- *      (2) :: in a full address is silently ignored.
- * credit:
- *      inspired by Mark Andrews.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton6(const char *src, unsigned char *dst)
-{
-	static const char xdigits_l[] = "0123456789abcdef",
-		xdigits_u[] = "0123456789ABCDEF";
-	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
-	const char *xdigits = 0, *curtok = 0;
-	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
-	unsigned int val = 0;
-	unsigned int dbloct_count = 0;
-
-	memset((tp = tmp), '\0', IN6ADDRSZ);
-	endp = tp + IN6ADDRSZ;
-	colonp = NULL;
-	/* Leading :: requires some special handling. */
-	if (*src == ':')
-		if (*++src != ':')
-			return 0;
-	curtok = src;
-	saw_xdigit = count_xdigit = 0;
-	val = 0;
-
-	while ((ch = *src++) != '\0') {
-		const char *pch;
-
-		pch = strchr((xdigits = xdigits_l), ch);
-		if (pch == NULL)
-			pch = strchr((xdigits = xdigits_u), ch);
-		if (pch != NULL) {
-			if (count_xdigit >= 4)
-				return 0;
-			val <<= 4;
-			val |= (pch - xdigits);
-			if (val > 0xffff)
-				return 0;
-			saw_xdigit = 1;
-			count_xdigit++;
-			continue;
-		}
-		if (ch == ':') {
-			curtok = src;
-			if (!saw_xdigit) {
-				if (colonp)
-					return 0;
-				colonp = tp;
-				continue;
-			} else if (*src == '\0') {
-				return 0;
-			}
-			if (tp + sizeof(int16_t) > endp)
-				return 0;
-			*tp++ = (unsigned char)((val >> 8) & 0xff);
-			*tp++ = (unsigned char)(val & 0xff);
-			saw_xdigit = 0;
-			count_xdigit = 0;
-			val = 0;
-			dbloct_count++;
-			continue;
-		}
-		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
-		    inet_pton4(curtok, tp) > 0) {
-			tp += INADDRSZ;
-			saw_xdigit = 0;
-			dbloct_count += 2;
-			break;  /* '\0' was seen by inet_pton4(). */
-		}
-		return 0;
-	}
-	if (saw_xdigit) {
-		if (tp + sizeof(int16_t) > endp)
-			return 0;
-		*tp++ = (unsigned char)((val >> 8) & 0xff);
-		*tp++ = (unsigned char)(val & 0xff);
-		dbloct_count++;
-	}
-	if (colonp != NULL) {
-		/* if we already have 8 double octets, having a colon means error */
-		if (dbloct_count == 8)
-			return 0;
-
-		/* Since some memmove()'s erroneously fail to handle
-		 * overlapping regions, we'll do the shift by hand.
-		 */
-		const int n = tp - colonp;
-		int i;
-
-		for (i = 1; i <= n; i++) {
-			endp[-i] = colonp[n - i];
-			colonp[n - i] = 0;
-		}
-		tp = endp;
-	}
-	if (tp != endp)
-		return 0;
-	memcpy(dst, tmp, IN6ADDRSZ);
-	return 1;
-}
-
 static struct rte_ether_addr *
 my_ether_aton(const char *a)
 {
@@ -577,7 +397,7 @@ softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
 	if (strlen(token) >= INET_ADDRSTRLEN)
 		return -EINVAL;
 
-	if (inet_pton4(token, (unsigned char *)ipv4) != 1)
+	if (inet_pton(AF_INET, token, ipv4) != 1)
 		return -EINVAL;
 
 	return 0;
@@ -589,7 +409,7 @@ softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
 	if (strlen(token) >= INET6_ADDRSTRLEN)
 		return -EINVAL;
 
-	if (inet_pton6(token, (unsigned char *)ipv6) != 1)
+	if (inet_pton(AF_INET6, token, ipv6) != 1)
 		return -EINVAL;
 
 	return 0;
diff --git a/dpdk/drivers/net/softnic/rte_eth_softnic_thread.c b/dpdk/drivers/net/softnic/rte_eth_softnic_thread.c
index d610b1617e..dcfb5eb82c 100644
--- a/dpdk/drivers/net/softnic/rte_eth_softnic_thread.c
+++ b/dpdk/drivers/net/softnic/rte_eth_softnic_thread.c
@@ -359,8 +359,6 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = thread_msg_send_recv(softnic, thread_id, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -444,8 +442,6 @@ softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = thread_msg_send_recv(softnic, thread_id, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -839,8 +835,6 @@ softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -888,8 +882,6 @@ softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -935,8 +927,6 @@ softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -990,8 +980,6 @@ softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1047,8 +1035,6 @@ softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1327,8 +1313,6 @@ softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1411,8 +1395,6 @@ softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1569,8 +1551,6 @@ softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1634,8 +1614,6 @@ softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1684,8 +1662,6 @@ softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1744,8 +1720,6 @@ softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1825,10 +1799,6 @@ softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL) {
-		free(mp);
-		return -1;
-	}
 
 	/* Read response */
 	status = rsp->status;
@@ -1884,8 +1854,6 @@ softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1947,8 +1915,6 @@ softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -2012,8 +1978,6 @@ softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -2077,8 +2041,6 @@ softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
diff --git a/dpdk/drivers/net/szedata2/meson.build b/dpdk/drivers/net/szedata2/meson.build
index b53fcbc591..77a5b0ed80 100644
--- a/dpdk/drivers/net/szedata2/meson.build
+++ b/dpdk/drivers/net/szedata2/meson.build
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2018 Intel Corporation
 
-dep = dependency('libsze2', required: false)
+dep = dependency('libsze2', required: false, method: 'pkg-config')
 build = dep.found()
 reason = 'missing dependency, "libsze2"'
 ext_deps += dep
diff --git a/dpdk/drivers/net/tap/rte_eth_tap.c b/dpdk/drivers/net/tap/rte_eth_tap.c
index a13d8d50d7..cfbd579cd6 100644
--- a/dpdk/drivers/net/tap/rte_eth_tap.c
+++ b/dpdk/drivers/net/tap/rte_eth_tap.c
@@ -18,8 +18,8 @@
 #include <rte_string_fns.h>
 #include <rte_ethdev.h>
 #include <rte_errno.h>
+#include <rte_cycles.h>
 
-#include <assert.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
@@ -339,6 +339,23 @@ tap_rx_offload_get_queue_capa(void)
 	       DEV_RX_OFFLOAD_TCP_CKSUM;
 }
 
+static void
+tap_rxq_pool_free(struct rte_mbuf *pool)
+{
+	struct rte_mbuf *mbuf = pool;
+	uint16_t nb_segs = 1;
+
+	if (mbuf == NULL)
+		return;
+
+	while (mbuf->next) {
+		mbuf = mbuf->next;
+		nb_segs++;
+	}
+	pool->nb_segs = nb_segs;
+	rte_pktmbuf_free(pool);
+}
+
 /* Callback to handle the rx burst of packets to the correct interface and
  * file descriptor(s) in a multi-queue setup.
  */
@@ -389,7 +406,7 @@ pmd_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 					goto end;
 
 				seg->next = NULL;
-				rte_pktmbuf_free(mbuf);
+				tap_rxq_pool_free(mbuf);
 
 				goto end;
 			}
@@ -521,7 +538,7 @@ tap_tx_l3_cksum(char *packet, uint64_t ol_flags, unsigned int l2_len,
 	}
 }
 
-static inline void
+static inline int
 tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
 			struct rte_mbuf **pmbufs,
 			uint16_t *num_packets, unsigned long *num_tx_bytes)
@@ -588,7 +605,7 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
 			seg_len = rte_pktmbuf_data_len(mbuf);
 			l234_hlen = mbuf->l2_len + mbuf->l3_len + mbuf->l4_len;
 			if (seg_len < l234_hlen)
-				break;
+				return -1;
 
 			/* To change checksums, work on a * copy of l2, l3
 			 * headers + l4 pseudo header
@@ -634,10 +651,12 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
 		/* copy the tx frame data */
 		n = writev(process_private->txq_fds[txq->queue_id], iovecs, j);
 		if (n <= 0)
-			break;
+			return -1;
+
 		(*num_packets)++;
 		(*num_tx_bytes) += rte_pktmbuf_pkt_len(mbuf);
 	}
+	return 0;
 }
 
 /* Callback to handle sending packets from the tap interface
@@ -663,16 +682,14 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 		uint16_t num_mbufs = 0;
 		uint16_t tso_segsz = 0;
 		int ret;
+		int num_tso_mbufs;
 		uint16_t hdrs_len;
-		int j;
 		uint64_t tso;
 
 		tso = mbuf_in->ol_flags & PKT_TX_TCP_SEG;
 		if (tso) {
 			struct rte_gso_ctx *gso_ctx = &txq->gso_ctx;
 
-			assert(gso_ctx != NULL);
-
 			/* TCP segmentation implies TCP checksum offload */
 			mbuf_in->ol_flags |= PKT_TX_TCP_CKSUM;
 
@@ -686,43 +703,51 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t nb_pkts)
 				break;
 			}
 			gso_ctx->gso_size = tso_segsz;
-			ret = rte_gso_segment(mbuf_in, /* packet to segment */
+			/* 'mbuf_in' packet to segment */
+			num_tso_mbufs = rte_gso_segment(mbuf_in,
 				gso_ctx, /* gso control block */
 				(struct rte_mbuf **)&gso_mbufs, /* out mbufs */
 				RTE_DIM(gso_mbufs)); /* max tso mbufs */
 
 			/* ret contains the number of new created mbufs */
-			if (ret < 0)
+			if (num_tso_mbufs < 0)
 				break;
 
 			mbuf = gso_mbufs;
-			num_mbufs = ret;
+			num_mbufs = num_tso_mbufs;
 		} else {
 			/* stats.errs will be incremented */
 			if (rte_pktmbuf_pkt_len(mbuf_in) > max_size)
 				break;
 
 			/* ret 0 indicates no new mbufs were created */
-			ret = 0;
+			num_tso_mbufs = 0;
 			mbuf = &mbuf_in;
 			num_mbufs = 1;
 		}
 
-		tap_write_mbufs(txq, num_mbufs, mbuf,
+		ret = tap_write_mbufs(txq, num_mbufs, mbuf,
 				&num_packets, &num_tx_bytes);
+		if (ret == -1) {
+			txq->stats.errs++;
+			/* free tso mbufs */
+			if (num_tso_mbufs > 0)
+				rte_pktmbuf_free_bulk(mbuf, num_tso_mbufs);
+			break;
+		}
 		num_tx++;
 		/* free original mbuf */
 		rte_pktmbuf_free(mbuf_in);
 		/* free tso mbufs */
-		for (j = 0; j < ret; j++)
-			rte_pktmbuf_free(mbuf[j]);
+		if (num_tso_mbufs > 0)
+			rte_pktmbuf_free_bulk(mbuf, num_tso_mbufs);
 	}
 
 	txq->stats.opackets += num_packets;
 	txq->stats.errs += nb_pkts - num_tx;
 	txq->stats.obytes += num_tx_bytes;
 
-	return num_packets;
+	return num_tx;
 }
 
 static const char *
@@ -778,7 +803,7 @@ tap_ioctl(struct pmd_internals *pmd, unsigned long request,
 	case SIOCSIFMTU:
 		break;
 	default:
-		RTE_LOG(WARNING, PMD, "%s: ioctl() called with wrong arg\n",
+		TAP_LOG(WARNING, "%s: ioctl() called with wrong arg",
 			pmd->name);
 		return -EINVAL;
 	}
@@ -1013,15 +1038,25 @@ tap_dev_close(struct rte_eth_dev *dev)
 	int i;
 	struct pmd_internals *internals = dev->data->dev_private;
 	struct pmd_process_private *process_private = dev->process_private;
+	struct rx_queue *rxq;
 
 	tap_link_set_down(dev);
-	tap_flow_flush(dev, NULL);
-	tap_flow_implicit_flush(internals, NULL);
+	if (internals->nlsk_fd != -1) {
+		tap_flow_flush(dev, NULL);
+		tap_flow_implicit_flush(internals, NULL);
+		tap_nl_final(internals->nlsk_fd);
+		internals->nlsk_fd = -1;
+	}
 
 	for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
 		if (process_private->rxq_fds[i] != -1) {
+			rxq = &internals->rxq[i];
 			close(process_private->rxq_fds[i]);
 			process_private->rxq_fds[i] = -1;
+			tap_rxq_pool_free(rxq->pool);
+			rte_free(rxq->iovecs);
+			rxq->pool = NULL;
+			rxq->iovecs = NULL;
 		}
 		if (process_private->txq_fds[i] != -1) {
 			close(process_private->txq_fds[i]);
@@ -1035,6 +1070,9 @@ tap_dev_close(struct rte_eth_dev *dev)
 				&internals->remote_initial_flags);
 	}
 
+	rte_mempool_free(internals->gso_ctx_mp);
+	internals->gso_ctx_mp = NULL;
+
 	if (internals->ka_fd != -1) {
 		close(internals->ka_fd);
 		internals->ka_fd = -1;
@@ -1054,10 +1092,10 @@ tap_rx_queue_release(void *queue)
 	if (!rxq)
 		return;
 	process_private = rte_eth_devices[rxq->in_port].process_private;
-	if (process_private->rxq_fds[rxq->queue_id] > 0) {
+	if (process_private->rxq_fds[rxq->queue_id] != -1) {
 		close(process_private->rxq_fds[rxq->queue_id]);
 		process_private->rxq_fds[rxq->queue_id] = -1;
-		rte_pktmbuf_free(rxq->pool);
+		tap_rxq_pool_free(rxq->pool);
 		rte_free(rxq->iovecs);
 		rxq->pool = NULL;
 		rxq->iovecs = NULL;
@@ -1074,7 +1112,7 @@ tap_tx_queue_release(void *queue)
 		return;
 	process_private = rte_eth_devices[txq->out_port].process_private;
 
-	if (process_private->txq_fds[txq->queue_id] > 0) {
+	if (process_private->txq_fds[txq->queue_id] != -1) {
 		close(process_private->txq_fds[txq->queue_id]);
 		process_private->txq_fds[txq->queue_id] = -1;
 	}
@@ -1282,33 +1320,40 @@ tap_gso_ctx_setup(struct rte_gso_ctx *gso_ctx, struct rte_eth_dev *dev)
 {
 	uint32_t gso_types;
 	char pool_name[64];
-
-	/*
-	 * Create private mbuf pool with TAP_GSO_MBUF_SEG_SIZE bytes
-	 * size per mbuf use this pool for both direct and indirect mbufs
-	 */
-
-	struct rte_mempool *mp;      /* Mempool for GSO packets */
+	struct pmd_internals *pmd = dev->data->dev_private;
+	int ret;
 
 	/* initialize GSO context */
 	gso_types = DEV_TX_OFFLOAD_TCP_TSO;
-	snprintf(pool_name, sizeof(pool_name), "mp_%s", dev->device->name);
-	mp = rte_mempool_lookup((const char *)pool_name);
-	if (!mp) {
-		mp = rte_pktmbuf_pool_create(pool_name, TAP_GSO_MBUFS_NUM,
-			TAP_GSO_MBUF_CACHE_SIZE, 0,
+	if (!pmd->gso_ctx_mp) {
+		/*
+		 * Create private mbuf pool with TAP_GSO_MBUF_SEG_SIZE
+		 * bytes size per mbuf use this pool for both direct and
+		 * indirect mbufs
+		 */
+		ret = snprintf(pool_name, sizeof(pool_name), "mp_%s",
+				dev->device->name);
+		if (ret < 0 || ret >= (int)sizeof(pool_name)) {
+			TAP_LOG(ERR,
+				"%s: failed to create mbuf pool name for device %s,"
+				"device name too long or output error, ret: %d\n",
+				pmd->name, dev->device->name, ret);
+			return -ENAMETOOLONG;
+		}
+		pmd->gso_ctx_mp = rte_pktmbuf_pool_create(pool_name,
+			TAP_GSO_MBUFS_NUM, TAP_GSO_MBUF_CACHE_SIZE, 0,
 			RTE_PKTMBUF_HEADROOM + TAP_GSO_MBUF_SEG_SIZE,
 			SOCKET_ID_ANY);
-		if (!mp) {
-			struct pmd_internals *pmd = dev->data->dev_private;
-			RTE_LOG(DEBUG, PMD, "%s: failed to create mbuf pool for device %s\n",
+		if (!pmd->gso_ctx_mp) {
+			TAP_LOG(ERR,
+				"%s: failed to create mbuf pool for device %s\n",
 				pmd->name, dev->device->name);
 			return -1;
 		}
 	}
 
-	gso_ctx->direct_pool = mp;
-	gso_ctx->indirect_pool = mp;
+	gso_ctx->direct_pool = pmd->gso_ctx_mp;
+	gso_ctx->indirect_pool = pmd->gso_ctx_mp;
 	gso_ctx->gso_types = gso_types;
 	gso_ctx->gso_size = 0; /* gso_size is set in tx_burst() per packet */
 	gso_ctx->flag = 0;
@@ -1465,7 +1510,7 @@ tap_rx_queue_setup(struct rte_eth_dev *dev,
 	return 0;
 
 error:
-	rte_pktmbuf_free(rxq->pool);
+	tap_rxq_pool_free(rxq->pool);
 	rxq->pool = NULL;
 	rte_free(rxq->iovecs);
 	rxq->iovecs = NULL;
@@ -1563,13 +1608,12 @@ static int
 tap_lsc_intr_handle_set(struct rte_eth_dev *dev, int set)
 {
 	struct pmd_internals *pmd = dev->data->dev_private;
+	int ret;
 
 	/* In any case, disable interrupt if the conf is no longer there. */
 	if (!dev->data->dev_conf.intr_conf.lsc) {
 		if (pmd->intr_handle.fd != -1) {
-			tap_nl_final(pmd->intr_handle.fd);
-			rte_intr_callback_unregister(&pmd->intr_handle,
-				tap_dev_intr_handler, dev);
+			goto clean;
 		}
 		return 0;
 	}
@@ -1580,9 +1624,26 @@ tap_lsc_intr_handle_set(struct rte_eth_dev *dev, int set)
 		return rte_intr_callback_register(
 			&pmd->intr_handle, tap_dev_intr_handler, dev);
 	}
+
+clean:
+	do {
+		ret = rte_intr_callback_unregister(&pmd->intr_handle,
+			tap_dev_intr_handler, dev);
+		if (ret >= 0) {
+			break;
+		} else if (ret == -EAGAIN) {
+			rte_delay_ms(100);
+		} else {
+			TAP_LOG(ERR, "intr callback unregister failed: %d",
+				     ret);
+			break;
+		}
+	} while (true);
+
 	tap_nl_final(pmd->intr_handle.fd);
-	return rte_intr_callback_unregister(&pmd->intr_handle,
-					    tap_dev_intr_handler, dev);
+	pmd->intr_handle.fd = -1;
+
+	return 0;
 }
 
 static int
@@ -1591,8 +1652,11 @@ tap_intr_handle_set(struct rte_eth_dev *dev, int set)
 	int err;
 
 	err = tap_lsc_intr_handle_set(dev, set);
-	if (err)
+	if (err < 0) {
+		if (!set)
+			tap_rx_intr_vec_set(dev, 0);
 		return err;
+	}
 	err = tap_rx_intr_vec_set(dev, set);
 	if (err && set)
 		tap_lsc_intr_handle_set(dev, 0);
@@ -1784,6 +1848,9 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
 	pmd->dev = dev;
 	strlcpy(pmd->name, tap_name, sizeof(pmd->name));
 	pmd->type = type;
+	pmd->ka_fd = -1;
+	pmd->nlsk_fd = -1;
+	pmd->gso_ctx_mp = NULL;
 
 	pmd->ioctl_sock = socket(AF_INET, SOCK_DGRAM, 0);
 	if (pmd->ioctl_sock == -1) {
@@ -1814,7 +1881,6 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
 	dev->intr_handle = &pmd->intr_handle;
 
 	/* Presetup the fds to -1 as being not valid */
-	pmd->ka_fd = -1;
 	for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
 		process_private->rxq_fds[i] = -1;
 		process_private->txq_fds[i] = -1;
@@ -1954,7 +2020,11 @@ eth_dev_tap_create(struct rte_vdev_device *vdev, const char *tap_name,
 	tap_flow_implicit_flush(pmd, NULL);
 
 error_exit:
-	if (pmd->ioctl_sock > 0)
+	if (pmd->nlsk_fd != -1)
+		close(pmd->nlsk_fd);
+	if (pmd->ka_fd != -1)
+		close(pmd->ka_fd);
+	if (pmd->ioctl_sock != -1)
 		close(pmd->ioctl_sock);
 	/* mac_addrs must not be freed alone because part of dev_private */
 	dev->data->mac_addrs = NULL;
@@ -2386,8 +2456,6 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 {
 	struct rte_eth_dev *eth_dev = NULL;
 	struct pmd_internals *internals;
-	struct pmd_process_private *process_private;
-	int i;
 
 	/* find the ethdev entry */
 	eth_dev = rte_eth_dev_allocated(rte_vdev_device_name(dev));
@@ -2400,28 +2468,12 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
 		return rte_eth_dev_release_port(eth_dev);
 
-	internals = eth_dev->data->dev_private;
-	process_private = eth_dev->process_private;
+	tap_dev_close(eth_dev);
 
+	internals = eth_dev->data->dev_private;
 	TAP_LOG(DEBUG, "Closing %s Ethernet device on numa %u",
 		tuntap_types[internals->type], rte_socket_id());
 
-	if (internals->nlsk_fd) {
-		tap_flow_flush(eth_dev, NULL);
-		tap_flow_implicit_flush(internals, NULL);
-		tap_nl_final(internals->nlsk_fd);
-	}
-	for (i = 0; i < RTE_PMD_TAP_MAX_QUEUES; i++) {
-		if (process_private->rxq_fds[i] != -1) {
-			close(process_private->rxq_fds[i]);
-			process_private->rxq_fds[i] = -1;
-		}
-		if (process_private->txq_fds[i] != -1) {
-			close(process_private->txq_fds[i]);
-			process_private->txq_fds[i] = -1;
-		}
-	}
-
 	close(internals->ioctl_sock);
 	rte_free(eth_dev->process_private);
 	if (tap_devices_count == 1)
@@ -2429,10 +2481,6 @@ rte_pmd_tap_remove(struct rte_vdev_device *dev)
 	tap_devices_count--;
 	rte_eth_dev_release_port(eth_dev);
 
-	if (internals->ka_fd != -1) {
-		close(internals->ka_fd);
-		internals->ka_fd = -1;
-	}
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/tap/rte_eth_tap.h b/dpdk/drivers/net/tap/rte_eth_tap.h
index 8d6d53dc0a..ba45de8409 100644
--- a/dpdk/drivers/net/tap/rte_eth_tap.h
+++ b/dpdk/drivers/net/tap/rte_eth_tap.h
@@ -91,6 +91,7 @@ struct pmd_internals {
 	struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX queues */
 	struct rte_intr_handle intr_handle;          /* LSC interrupt handle. */
 	int ka_fd;                        /* keep-alive file descriptor */
+	struct rte_mempool *gso_ctx_mp;     /* Mempool for GSO packets */
 };
 
 struct pmd_process_private {
diff --git a/dpdk/drivers/net/tap/tap_flow.c b/dpdk/drivers/net/tap/tap_flow.c
index 9d90361d99..1538349e9c 100644
--- a/dpdk/drivers/net/tap/tap_flow.c
+++ b/dpdk/drivers/net/tap/tap_flow.c
@@ -1380,7 +1380,7 @@ tap_flow_create(struct rte_eth_dev *dev,
 			NULL, "priority value too big");
 		goto fail;
 	}
-	flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
+	flow = rte_zmalloc(__func__, sizeof(struct rte_flow), 0);
 	if (!flow) {
 		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "cannot allocate memory for rte_flow");
@@ -1416,7 +1416,7 @@ tap_flow_create(struct rte_eth_dev *dev,
 	 * to the local pmd->if_index.
 	 */
 	if (pmd->remote_if_index) {
-		remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
+		remote_flow = rte_zmalloc(__func__, sizeof(struct rte_flow), 0);
 		if (!remote_flow) {
 			rte_flow_error_set(
 				error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
@@ -1693,7 +1693,7 @@ int tap_flow_implicit_create(struct pmd_internals *pmd,
 		}
 	};
 
-	remote_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
+	remote_flow = rte_zmalloc(__func__, sizeof(struct rte_flow), 0);
 	if (!remote_flow) {
 		TAP_LOG(ERR, "Cannot allocate memory for rte_flow");
 		goto fail;
@@ -1896,7 +1896,7 @@ static int rss_enable(struct pmd_internals *pmd,
 			return -ENOTSUP;
 		}
 
-		rss_flow = rte_malloc(__func__, sizeof(struct rte_flow), 0);
+		rss_flow = rte_zmalloc(__func__, sizeof(struct rte_flow), 0);
 		if (!rss_flow) {
 			TAP_LOG(ERR,
 				"Cannot allocate memory for rte_flow");
diff --git a/dpdk/drivers/net/tap/tap_intr.c b/dpdk/drivers/net/tap/tap_intr.c
index 7af0010e37..5cf4f173a0 100644
--- a/dpdk/drivers/net/tap/tap_intr.c
+++ b/dpdk/drivers/net/tap/tap_intr.c
@@ -7,7 +7,6 @@
  * Interrupts handling for tap driver.
  */
 
-#include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -72,7 +71,7 @@ tap_rx_intr_vec_install(struct rte_eth_dev *dev)
 		struct rx_queue *rxq = pmd->dev->data->rx_queues[i];
 
 		/* Skip queues that cannot request interrupts. */
-		if (!rxq || process_private->rxq_fds[i] <= 0) {
+		if (!rxq || process_private->rxq_fds[i] == -1) {
 			/* Use invalid intr_vec[] index to disable entry. */
 			intr_handle->intr_vec[i] =
 				RTE_INTR_VEC_RXTX_OFFSET +
diff --git a/dpdk/drivers/net/thunderx/base/nicvf_hw_defs.h b/dpdk/drivers/net/thunderx/base/nicvf_hw_defs.h
index b12c8ec50a..adc8ec943d 100644
--- a/dpdk/drivers/net/thunderx/base/nicvf_hw_defs.h
+++ b/dpdk/drivers/net/thunderx/base/nicvf_hw_defs.h
@@ -176,6 +176,7 @@
 #define NIC_HW_MAX_MTU                  (9190)
 #define NIC_HW_MAX_FRS                  (NIC_HW_MAX_MTU + NIC_HW_L2_OVERHEAD)
 #define NIC_HW_MAX_SEGS                 (12)
+#define NIC_HW_L2_MAX_LEN		(RTE_ETHER_MTU + NIC_HW_L2_OVERHEAD)
 
 /* Descriptor alignments */
 #define NICVF_RBDR_BASE_ALIGN_BYTES     (128) /* 7 bits */
diff --git a/dpdk/drivers/net/thunderx/nicvf_ethdev.c b/dpdk/drivers/net/thunderx/nicvf_ethdev.c
index 2cf0ffe13b..0fba26ac45 100644
--- a/dpdk/drivers/net/thunderx/nicvf_ethdev.c
+++ b/dpdk/drivers/net/thunderx/nicvf_ethdev.c
@@ -191,7 +191,7 @@ nicvf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 		(frame_size + 2 * VLAN_TAG_SIZE > buffsz * NIC_HW_MAX_SEGS))
 		return -EINVAL;
 
-	if (frame_size > RTE_ETHER_MAX_LEN)
+	if (frame_size > NIC_HW_L2_MAX_LEN)
 		rxmode->offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME;
 	else
 		rxmode->offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME;
@@ -496,9 +496,10 @@ nicvf_dev_reta_query(struct rte_eth_dev *dev,
 	int ret, i, j;
 
 	if (reta_size != NIC_MAX_RSS_IDR_TBL_SIZE) {
-		RTE_LOG(ERR, PMD, "The size of hash lookup table configured "
-			"(%d) doesn't match the number hardware can supported "
-			"(%d)", reta_size, NIC_MAX_RSS_IDR_TBL_SIZE);
+		PMD_DRV_LOG(ERR,
+			    "The size of hash lookup table configured "
+			    "(%u) doesn't match the number hardware can supported "
+			    "(%u)", reta_size, NIC_MAX_RSS_IDR_TBL_SIZE);
 		return -EINVAL;
 	}
 
@@ -526,9 +527,9 @@ nicvf_dev_reta_update(struct rte_eth_dev *dev,
 	int ret, i, j;
 
 	if (reta_size != NIC_MAX_RSS_IDR_TBL_SIZE) {
-		RTE_LOG(ERR, PMD, "The size of hash lookup table configured "
-			"(%d) doesn't match the number hardware can supported "
-			"(%d)", reta_size, NIC_MAX_RSS_IDR_TBL_SIZE);
+		PMD_DRV_LOG(ERR, "The size of hash lookup table configured "
+			"(%u) doesn't match the number hardware can supported "
+			"(%u)", reta_size, NIC_MAX_RSS_IDR_TBL_SIZE);
 		return -EINVAL;
 	}
 
@@ -569,8 +570,8 @@ nicvf_dev_rss_hash_update(struct rte_eth_dev *dev,
 
 	if (rss_conf->rss_key &&
 		rss_conf->rss_key_len != RSS_HASH_KEY_BYTE_SIZE) {
-		RTE_LOG(ERR, PMD, "Hash key size mismatch %d",
-				rss_conf->rss_key_len);
+		PMD_DRV_LOG(ERR, "Hash key size mismatch %u",
+			    rss_conf->rss_key_len);
 		return -EINVAL;
 	}
 
@@ -652,6 +653,7 @@ nicvf_qset_rbdr_alloc(struct rte_eth_dev *dev, struct nicvf *nic,
 				      NICVF_RBDR_BASE_ALIGN_BYTES, nic->node);
 	if (rz == NULL) {
 		PMD_INIT_LOG(ERR, "Failed to allocate mem for rbdr desc ring");
+		rte_free(rbdr);
 		return -ENOMEM;
 	}
 
diff --git a/dpdk/drivers/net/vdev_netvsc/vdev_netvsc.c b/dpdk/drivers/net/vdev_netvsc/vdev_netvsc.c
index be8f19c0c6..48081b9146 100644
--- a/dpdk/drivers/net/vdev_netvsc/vdev_netvsc.c
+++ b/dpdk/drivers/net/vdev_netvsc/vdev_netvsc.c
@@ -673,6 +673,7 @@ vdev_netvsc_vdev_probe(struct rte_vdev_device *dev)
 	int ret;
 
 	DRV_LOG(DEBUG, "invoked as \"%s\", using arguments \"%s\"", name, args);
+	rte_eal_alarm_cancel(vdev_netvsc_alarm, NULL);
 	if (!kvargs) {
 		DRV_LOG(ERR, "cannot parse arguments list");
 		goto error;
@@ -688,17 +689,13 @@ vdev_netvsc_vdev_probe(struct rte_vdev_device *dev)
 			 !strcmp(pair->key, VDEV_NETVSC_ARG_MAC))
 			++specified;
 	}
-	if (ignore) {
-		if (kvargs)
-			rte_kvargs_free(kvargs);
-		return 0;
-	}
+	if (ignore)
+		goto ignore;
 	if (specified > 1) {
 		DRV_LOG(ERR, "More than one way used to specify the netvsc"
 			" device.");
 		goto error;
 	}
-	rte_eal_alarm_cancel(vdev_netvsc_alarm, NULL);
 	/* Gather interfaces. */
 	ret = vdev_netvsc_foreach_iface(vdev_netvsc_netvsc_probe, 1, name,
 					kvargs, specified, &matched);
@@ -719,17 +716,19 @@ vdev_netvsc_vdev_probe(struct rte_vdev_device *dev)
 		}
 		DRV_LOG(WARNING, "non-netvsc device was probed as netvsc");
 	}
-	ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
-				vdev_netvsc_alarm, NULL);
-	if (ret < 0) {
-		DRV_LOG(ERR, "unable to schedule alarm callback: %s",
-			rte_strerror(-ret));
-		goto error;
-	}
 error:
+	++vdev_netvsc_ctx_inst;
+ignore:
 	if (kvargs)
 		rte_kvargs_free(kvargs);
-	++vdev_netvsc_ctx_inst;
+	/* Reset alarm if there are device context created */
+	if (vdev_netvsc_ctx_count) {
+		ret = rte_eal_alarm_set(VDEV_NETVSC_PROBE_MS * 1000,
+					vdev_netvsc_alarm, NULL);
+		if (ret < 0)
+			DRV_LOG(ERR, "unable to schedule alarm callback: %s",
+				rte_strerror(-ret));
+	}
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/vhost/rte_eth_vhost.c b/dpdk/drivers/net/vhost/rte_eth_vhost.c
index 46f01a7f46..323efb3c07 100644
--- a/dpdk/drivers/net/vhost/rte_eth_vhost.c
+++ b/dpdk/drivers/net/vhost/rte_eth_vhost.c
@@ -68,6 +68,9 @@ enum vhost_xstats_pkts {
 	VHOST_BROADCAST_PKT,
 	VHOST_MULTICAST_PKT,
 	VHOST_UNICAST_PKT,
+	VHOST_PKT,
+	VHOST_BYTE,
+	VHOST_MISSED_PKT,
 	VHOST_ERRORS_PKT,
 	VHOST_ERRORS_FRAGMENTED,
 	VHOST_ERRORS_JABBER,
@@ -97,6 +100,8 @@ struct pmd_internal {
 	rte_atomic32_t dev_attached;
 	char *dev_name;
 	char *iface_name;
+	uint64_t flags;
+	uint64_t disable_flags;
 	uint16_t max_queues;
 	int vid;
 	rte_atomic32_t started;
@@ -141,11 +146,11 @@ struct vhost_xstats_name_off {
 /* [rx]_is prepended to the name string here */
 static const struct vhost_xstats_name_off vhost_rxport_stat_strings[] = {
 	{"good_packets",
-	 offsetof(struct vhost_queue, stats.pkts)},
+	 offsetof(struct vhost_queue, stats.xstats[VHOST_PKT])},
 	{"total_bytes",
-	 offsetof(struct vhost_queue, stats.bytes)},
+	 offsetof(struct vhost_queue, stats.xstats[VHOST_BYTE])},
 	{"missed_pkts",
-	 offsetof(struct vhost_queue, stats.missed_pkts)},
+	 offsetof(struct vhost_queue, stats.xstats[VHOST_MISSED_PKT])},
 	{"broadcast_packets",
 	 offsetof(struct vhost_queue, stats.xstats[VHOST_BROADCAST_PKT])},
 	{"multicast_packets",
@@ -181,11 +186,11 @@ static const struct vhost_xstats_name_off vhost_rxport_stat_strings[] = {
 /* [tx]_ is prepended to the name string here */
 static const struct vhost_xstats_name_off vhost_txport_stat_strings[] = {
 	{"good_packets",
-	 offsetof(struct vhost_queue, stats.pkts)},
+	 offsetof(struct vhost_queue, stats.xstats[VHOST_PKT])},
 	{"total_bytes",
-	 offsetof(struct vhost_queue, stats.bytes)},
+	 offsetof(struct vhost_queue, stats.xstats[VHOST_BYTE])},
 	{"missed_pkts",
-	 offsetof(struct vhost_queue, stats.missed_pkts)},
+	 offsetof(struct vhost_queue, stats.xstats[VHOST_MISSED_PKT])},
 	{"broadcast_packets",
 	 offsetof(struct vhost_queue, stats.xstats[VHOST_BROADCAST_PKT])},
 	{"multicast_packets",
@@ -279,23 +284,6 @@ vhost_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 	if (n < nxstats)
 		return nxstats;
 
-	for (i = 0; i < dev->data->nb_rx_queues; i++) {
-		vq = dev->data->rx_queues[i];
-		if (!vq)
-			continue;
-		vq->stats.xstats[VHOST_UNICAST_PKT] = vq->stats.pkts
-				- (vq->stats.xstats[VHOST_BROADCAST_PKT]
-				+ vq->stats.xstats[VHOST_MULTICAST_PKT]);
-	}
-	for (i = 0; i < dev->data->nb_tx_queues; i++) {
-		vq = dev->data->tx_queues[i];
-		if (!vq)
-			continue;
-		vq->stats.xstats[VHOST_UNICAST_PKT] = vq->stats.pkts
-				+ vq->stats.missed_pkts
-				- (vq->stats.xstats[VHOST_BROADCAST_PKT]
-				+ vq->stats.xstats[VHOST_MULTICAST_PKT]);
-	}
 	for (t = 0; t < VHOST_NB_XSTATS_RXPORT; t++) {
 		xstats[count].value = 0;
 		for (i = 0; i < dev->data->nb_rx_queues; i++) {
@@ -326,7 +314,7 @@ vhost_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 }
 
 static inline void
-vhost_count_multicast_broadcast(struct vhost_queue *vq,
+vhost_count_xcast_packets(struct vhost_queue *vq,
 				struct rte_mbuf *mbuf)
 {
 	struct rte_ether_addr *ea = NULL;
@@ -338,20 +326,27 @@ vhost_count_multicast_broadcast(struct vhost_queue *vq,
 			pstats->xstats[VHOST_BROADCAST_PKT]++;
 		else
 			pstats->xstats[VHOST_MULTICAST_PKT]++;
+	} else {
+		pstats->xstats[VHOST_UNICAST_PKT]++;
 	}
 }
 
 static void
-vhost_update_packet_xstats(struct vhost_queue *vq,
-			   struct rte_mbuf **bufs,
-			   uint16_t count)
+vhost_update_packet_xstats(struct vhost_queue *vq, struct rte_mbuf **bufs,
+			   uint16_t count, uint64_t nb_bytes,
+			   uint64_t nb_missed)
 {
 	uint32_t pkt_len = 0;
 	uint64_t i = 0;
 	uint64_t index;
 	struct vhost_stats *pstats = &vq->stats;
 
+	pstats->xstats[VHOST_BYTE] += nb_bytes;
+	pstats->xstats[VHOST_MISSED_PKT] += nb_missed;
+	pstats->xstats[VHOST_UNICAST_PKT] += nb_missed;
+
 	for (i = 0; i < count ; i++) {
+		pstats->xstats[VHOST_PKT]++;
 		pkt_len = bufs[i]->pkt_len;
 		if (pkt_len == 64) {
 			pstats->xstats[VHOST_64_PKT]++;
@@ -367,7 +362,7 @@ vhost_update_packet_xstats(struct vhost_queue *vq,
 			else if (pkt_len > 1522)
 				pstats->xstats[VHOST_1523_TO_MAX_PKT]++;
 		}
-		vhost_count_multicast_broadcast(vq, bufs[i]);
+		vhost_count_xcast_packets(vq, bufs[i]);
 	}
 }
 
@@ -377,6 +372,7 @@ eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 	struct vhost_queue *r = q;
 	uint16_t i, nb_rx = 0;
 	uint16_t nb_receive = nb_bufs;
+	uint64_t nb_bytes = 0;
 
 	if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0))
 		return 0;
@@ -411,10 +407,11 @@ eth_vhost_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 		if (r->internal->vlan_strip)
 			rte_vlan_strip(bufs[i]);
 
-		r->stats.bytes += bufs[i]->pkt_len;
+		nb_bytes += bufs[i]->pkt_len;
 	}
 
-	vhost_update_packet_xstats(r, bufs, nb_rx);
+	r->stats.bytes += nb_bytes;
+	vhost_update_packet_xstats(r, bufs, nb_rx, nb_bytes, 0);
 
 out:
 	rte_atomic32_set(&r->while_queuing, 0);
@@ -428,6 +425,8 @@ eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 	struct vhost_queue *r = q;
 	uint16_t i, nb_tx = 0;
 	uint16_t nb_send = 0;
+	uint64_t nb_bytes = 0;
+	uint64_t nb_missed = 0;
 
 	if (unlikely(rte_atomic32_read(&r->allow_queuing) == 0))
 		return 0;
@@ -468,20 +467,23 @@ eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 			break;
 	}
 
+	for (i = 0; likely(i < nb_tx); i++)
+		nb_bytes += bufs[i]->pkt_len;
+
+	nb_missed = nb_bufs - nb_tx;
+
 	r->stats.pkts += nb_tx;
+	r->stats.bytes += nb_bytes;
 	r->stats.missed_pkts += nb_bufs - nb_tx;
 
-	for (i = 0; likely(i < nb_tx); i++)
-		r->stats.bytes += bufs[i]->pkt_len;
-
-	vhost_update_packet_xstats(r, bufs, nb_tx);
+	vhost_update_packet_xstats(r, bufs, nb_tx, nb_bytes, nb_missed);
 
-	/* According to RFC2863 page42 section ifHCOutMulticastPkts and
-	 * ifHCOutBroadcastPkts, the counters "multicast" and "broadcast"
-	 * are increased when packets are not transmitted successfully.
+	/* According to RFC2863, ifHCOutUcastPkts, ifHCOutMulticastPkts and
+	 * ifHCOutBroadcastPkts counters are increased when packets are not
+	 * transmitted successfully.
 	 */
 	for (i = nb_tx; i < nb_bufs; i++)
-		vhost_count_multicast_broadcast(r, bufs[i]);
+		vhost_count_xcast_packets(r, bufs[i]);
 
 	for (i = 0; likely(i < nb_tx); i++)
 		rte_pktmbuf_free(bufs[i]);
@@ -491,17 +493,6 @@ eth_vhost_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 	return nb_tx;
 }
 
-static int
-eth_dev_configure(struct rte_eth_dev *dev __rte_unused)
-{
-	struct pmd_internal *internal = dev->data->dev_private;
-	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
-
-	internal->vlan_strip = !!(rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP);
-
-	return 0;
-}
-
 static inline struct internal_list *
 find_internal_resource(char *ifname)
 {
@@ -877,6 +868,74 @@ static struct vhost_device_ops vhost_ops = {
 	.vring_state_changed = vring_state_changed,
 };
 
+static int
+vhost_driver_setup(struct rte_eth_dev *eth_dev)
+{
+	struct pmd_internal *internal = eth_dev->data->dev_private;
+	struct internal_list *list = NULL;
+	struct rte_vhost_vring_state *vring_state = NULL;
+	unsigned int numa_node = eth_dev->device->numa_node;
+	const char *name = eth_dev->device->name;
+
+	/* Don't try to setup again if it has already been done. */
+	list = find_internal_resource(internal->iface_name);
+	if (list)
+		return 0;
+
+	list = rte_zmalloc_socket(name, sizeof(*list), 0, numa_node);
+	if (list == NULL)
+		return -1;
+
+	vring_state = rte_zmalloc_socket(name, sizeof(*vring_state),
+					 0, numa_node);
+	if (vring_state == NULL)
+		goto free_list;
+
+	list->eth_dev = eth_dev;
+	pthread_mutex_lock(&internal_list_lock);
+	TAILQ_INSERT_TAIL(&internal_list, list, next);
+	pthread_mutex_unlock(&internal_list_lock);
+
+	rte_spinlock_init(&vring_state->lock);
+	vring_states[eth_dev->data->port_id] = vring_state;
+
+	if (rte_vhost_driver_register(internal->iface_name, internal->flags))
+		goto list_remove;
+
+	if (internal->disable_flags) {
+		if (rte_vhost_driver_disable_features(internal->iface_name,
+						      internal->disable_flags))
+			goto drv_unreg;
+	}
+
+	if (rte_vhost_driver_callback_register(internal->iface_name,
+					       &vhost_ops) < 0) {
+		VHOST_LOG(ERR, "Can't register callbacks\n");
+		goto drv_unreg;
+	}
+
+	if (rte_vhost_driver_start(internal->iface_name) < 0) {
+		VHOST_LOG(ERR, "Failed to start driver for %s\n",
+			  internal->iface_name);
+		goto drv_unreg;
+	}
+
+	return 0;
+
+drv_unreg:
+	rte_vhost_driver_unregister(internal->iface_name);
+list_remove:
+	vring_states[eth_dev->data->port_id] = NULL;
+	pthread_mutex_lock(&internal_list_lock);
+	TAILQ_REMOVE(&internal_list, list, next);
+	pthread_mutex_unlock(&internal_list_lock);
+	rte_free(vring_state);
+free_list:
+	rte_free(list);
+
+	return -1;
+}
+
 int
 rte_eth_vhost_get_queue_event(uint16_t port_id,
 		struct rte_eth_vhost_queue_event *event)
@@ -943,6 +1002,24 @@ rte_eth_vhost_get_vid_from_port_id(uint16_t port_id)
 	return vid;
 }
 
+static int
+eth_dev_configure(struct rte_eth_dev *dev)
+{
+	struct pmd_internal *internal = dev->data->dev_private;
+	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
+
+	/* NOTE: the same process has to operate a vhost interface
+	 * from beginning to end (from eth_dev configure to eth_dev close).
+	 * It is user's responsibility at the moment.
+	 */
+	if (vhost_driver_setup(dev) < 0)
+		return -1;
+
+	internal->vlan_strip = !!(rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP);
+
+	return 0;
+}
+
 static int
 eth_dev_start(struct rte_eth_dev *eth_dev)
 {
@@ -989,16 +1066,14 @@ eth_dev_close(struct rte_eth_dev *dev)
 
 	eth_dev_stop(dev);
 
-	rte_vhost_driver_unregister(internal->iface_name);
-
 	list = find_internal_resource(internal->iface_name);
-	if (!list)
-		return;
-
-	pthread_mutex_lock(&internal_list_lock);
-	TAILQ_REMOVE(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
-	rte_free(list);
+	if (list) {
+		rte_vhost_driver_unregister(internal->iface_name);
+		pthread_mutex_lock(&internal_list_lock);
+		TAILQ_REMOVE(&internal_list, list, next);
+		pthread_mutex_unlock(&internal_list_lock);
+		rte_free(list);
+	}
 
 	if (dev->data->rx_queues)
 		for (i = 0; i < dev->data->nb_rx_queues; i++)
@@ -1009,7 +1084,7 @@ eth_dev_close(struct rte_eth_dev *dev)
 			rte_free(dev->data->tx_queues[i]);
 
 	free(internal->dev_name);
-	free(internal->iface_name);
+	rte_free(internal->iface_name);
 	rte_free(internal);
 
 	dev->data->dev_private = NULL;
@@ -1219,16 +1294,10 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	struct pmd_internal *internal = NULL;
 	struct rte_eth_dev *eth_dev = NULL;
 	struct rte_ether_addr *eth_addr = NULL;
-	struct rte_vhost_vring_state *vring_state = NULL;
-	struct internal_list *list = NULL;
 
 	VHOST_LOG(INFO, "Creating VHOST-USER backend on numa socket %u\n",
 		numa_node);
 
-	list = rte_zmalloc_socket(name, sizeof(*list), 0, numa_node);
-	if (list == NULL)
-		goto error;
-
 	/* reserve an ethdev entry */
 	eth_dev = rte_eth_vdev_allocate(dev, sizeof(*internal));
 	if (eth_dev == NULL)
@@ -1242,11 +1311,6 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	*eth_addr = base_eth_addr;
 	eth_addr->addr_bytes[5] = eth_dev->data->port_id;
 
-	vring_state = rte_zmalloc_socket(name,
-			sizeof(*vring_state), 0, numa_node);
-	if (vring_state == NULL)
-		goto error;
-
 	/* now put it all together
 	 * - store queue data in internal,
 	 * - point eth_dev_data to internals
@@ -1256,22 +1320,18 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	internal->dev_name = strdup(name);
 	if (internal->dev_name == NULL)
 		goto error;
-	internal->iface_name = strdup(iface_name);
+	internal->iface_name = rte_malloc_socket(name, strlen(iface_name) + 1,
+						 0, numa_node);
 	if (internal->iface_name == NULL)
 		goto error;
-
-	list->eth_dev = eth_dev;
-	pthread_mutex_lock(&internal_list_lock);
-	TAILQ_INSERT_TAIL(&internal_list, list, next);
-	pthread_mutex_unlock(&internal_list_lock);
-
-	rte_spinlock_init(&vring_state->lock);
-	vring_states[eth_dev->data->port_id] = vring_state;
+	strcpy(internal->iface_name, iface_name);
 
 	data->nb_rx_queues = queues;
 	data->nb_tx_queues = queues;
 	internal->max_queues = queues;
 	internal->vid = -1;
+	internal->flags = flags;
+	internal->disable_flags = disable_flags;
 	data->dev_link = pmd_link;
 	data->dev_flags = RTE_ETH_DEV_INTR_LSC | RTE_ETH_DEV_CLOSE_REMOVE;
 
@@ -1281,37 +1341,15 @@ eth_dev_vhost_create(struct rte_vdev_device *dev, char *iface_name,
 	eth_dev->rx_pkt_burst = eth_vhost_rx;
 	eth_dev->tx_pkt_burst = eth_vhost_tx;
 
-	if (rte_vhost_driver_register(iface_name, flags))
-		goto error;
-
-	if (disable_flags) {
-		if (rte_vhost_driver_disable_features(iface_name,
-					disable_flags))
-			goto error;
-	}
-
-	if (rte_vhost_driver_callback_register(iface_name, &vhost_ops) < 0) {
-		VHOST_LOG(ERR, "Can't register callbacks\n");
-		goto error;
-	}
-
-	if (rte_vhost_driver_start(iface_name) < 0) {
-		VHOST_LOG(ERR, "Failed to start driver for %s\n",
-			iface_name);
-		goto error;
-	}
-
 	rte_eth_dev_probing_finish(eth_dev);
-	return data->port_id;
+	return 0;
 
 error:
 	if (internal) {
-		free(internal->iface_name);
+		rte_free(internal->iface_name);
 		free(internal->dev_name);
 	}
-	rte_free(vring_state);
 	rte_eth_dev_release_port(eth_dev);
-	rte_free(list);
 
 	return -1;
 }
@@ -1369,8 +1407,11 @@ rte_pmd_vhost_probe(struct rte_vdev_device *dev)
 			VHOST_LOG(ERR, "Failed to probe %s\n", name);
 			return -1;
 		}
-		/* TODO: request info from primary to set up Rx and Tx */
+		eth_dev->rx_pkt_burst = eth_vhost_rx;
+		eth_dev->tx_pkt_burst = eth_vhost_tx;
 		eth_dev->dev_ops = &ops;
+		if (dev->device.numa_node == SOCKET_ID_ANY)
+			dev->device.numa_node = rte_socket_id();
 		eth_dev->device = &dev->device;
 		rte_eth_dev_probing_finish(eth_dev);
 		return 0;
@@ -1455,8 +1496,10 @@ rte_pmd_vhost_probe(struct rte_vdev_device *dev)
 	if (dev->device.numa_node == SOCKET_ID_ANY)
 		dev->device.numa_node = rte_socket_id();
 
-	eth_dev_vhost_create(dev, iface_name, queues, dev->device.numa_node,
-		flags, disable_flags);
+	ret = eth_dev_vhost_create(dev, iface_name, queues,
+				   dev->device.numa_node, flags, disable_flags);
+	if (ret == -1)
+		VHOST_LOG(ERR, "Failed to create %s\n", name);
 
 out_free:
 	rte_kvargs_free(kvlist);
diff --git a/dpdk/drivers/net/virtio/virtio_ethdev.c b/dpdk/drivers/net/virtio/virtio_ethdev.c
index 044eb10a70..8a107ebf9e 100644
--- a/dpdk/drivers/net/virtio/virtio_ethdev.c
+++ b/dpdk/drivers/net/virtio/virtio_ethdev.c
@@ -466,7 +466,7 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)
 	}
 
 	if (!vtpci_packed_queue(hw) && !rte_is_power_of_2(vq_size)) {
-		PMD_INIT_LOG(ERR, "split virtqueue size is not powerof 2");
+		PMD_INIT_LOG(ERR, "split virtqueue size is not power of 2");
 		return -EINVAL;
 	}
 
@@ -588,8 +588,8 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)
 		hw->cvq = cvq;
 	}
 
-	/* For virtio_user case (that is when hw->dev is NULL), we use
-	 * virtual address. And we need properly set _offset_, please see
+	/* For virtio_user case (that is when hw->virtio_user_dev is not NULL),
+	 * we use virtual address. And we need properly set _offset_, please see
 	 * VIRTIO_MBUF_DATA_DMA_ADDR in virtqueue.h for more information.
 	 */
 	if (!hw->virtio_user_dev)
@@ -610,10 +610,9 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)
 		txr = hdr_mz->addr;
 		memset(txr, 0, vq_size * sizeof(*txr));
 		for (i = 0; i < vq_size; i++) {
-			struct vring_desc *start_dp = txr[i].tx_indir;
-
 			/* first indirect descriptor is always the tx header */
 			if (!vtpci_packed_queue(hw)) {
+				struct vring_desc *start_dp = txr[i].tx_indir;
 				vring_desc_init_split(start_dp,
 						      RTE_DIM(txr[i].tx_indir));
 				start_dp->addr = txvq->virtio_net_hdr_mem
@@ -622,6 +621,16 @@ virtio_init_queue(struct rte_eth_dev *dev, uint16_t vtpci_queue_idx)
 						   tx_hdr);
 				start_dp->len = hw->vtnet_hdr_size;
 				start_dp->flags = VRING_DESC_F_NEXT;
+			} else {
+				struct vring_packed_desc *start_dp =
+					txr[i].tx_packed_indir;
+				vring_desc_init_indirect_packed(start_dp,
+				      RTE_DIM(txr[i].tx_packed_indir));
+				start_dp->addr = txvq->virtio_net_hdr_mem
+					+ i * sizeof(*txr)
+					+ offsetof(struct virtio_tx_region,
+						   tx_hdr);
+				start_dp->len = hw->vtnet_hdr_size;
 			}
 		}
 	}
@@ -1913,6 +1922,8 @@ eth_virtio_dev_init(struct rte_eth_dev *eth_dev)
 			goto err_vtpci_init;
 	}
 
+	rte_spinlock_init(&hw->state_lock);
+
 	/* reset device and negotiate default features */
 	ret = virtio_init_device(eth_dev, VIRTIO_PMD_DEFAULT_GUEST_FEATURES);
 	if (ret < 0)
@@ -2155,8 +2166,6 @@ virtio_dev_configure(struct rte_eth_dev *dev)
 			return -EBUSY;
 		}
 
-	rte_spinlock_init(&hw->state_lock);
-
 	hw->use_simple_rx = 1;
 
 	if (vtpci_with_feature(hw, VIRTIO_F_IN_ORDER)) {
diff --git a/dpdk/drivers/net/virtio/virtio_rxtx.c b/dpdk/drivers/net/virtio/virtio_rxtx.c
index 752faa0f6e..5211736d29 100644
--- a/dpdk/drivers/net/virtio/virtio_rxtx.c
+++ b/dpdk/drivers/net/virtio/virtio_rxtx.c
@@ -1085,7 +1085,7 @@ virtio_dev_tx_queue_setup(struct rte_eth_dev *dev,
 			RTE_MIN(vq->vq_nentries / 4, DEFAULT_TX_FREE_THRESH);
 
 	if (tx_free_thresh >= (vq->vq_nentries - 3)) {
-		RTE_LOG(ERR, PMD, "tx_free_thresh must be less than the "
+		PMD_DRV_LOG(ERR, "tx_free_thresh must be less than the "
 			"number of TX entries minus 3 (%u)."
 			" (tx_free_thresh=%u port=%u queue=%u)\n",
 			vq->vq_nentries - 3,
@@ -1133,7 +1133,7 @@ virtio_discard_rxbuf(struct virtqueue *vq, struct rte_mbuf *m)
 		error = virtqueue_enqueue_recv_refill(vq, &m, 1);
 
 	if (unlikely(error)) {
-		RTE_LOG(ERR, PMD, "cannot requeue discarded mbuf");
+		PMD_DRV_LOG(ERR, "cannot requeue discarded mbuf");
 		rte_pktmbuf_free(m);
 	}
 }
@@ -1145,7 +1145,7 @@ virtio_discard_rxbuf_inorder(struct virtqueue *vq, struct rte_mbuf *m)
 
 	error = virtqueue_enqueue_refill_inorder(vq, &m, 1);
 	if (unlikely(error)) {
-		RTE_LOG(ERR, PMD, "cannot requeue discarded mbuf");
+		PMD_DRV_LOG(ERR, "cannot requeue discarded mbuf");
 		rte_pktmbuf_free(m);
 	}
 }
@@ -1184,9 +1184,10 @@ virtio_rx_offload(struct rte_mbuf *m, struct virtio_net_hdr *hdr)
 			 */
 			uint16_t csum = 0, off;
 
-			rte_raw_cksum_mbuf(m, hdr->csum_start,
+			if (rte_raw_cksum_mbuf(m, hdr->csum_start,
 				rte_pktmbuf_pkt_len(m) - hdr->csum_start,
-				&csum);
+				&csum) < 0)
+				return -EINVAL;
 			if (likely(csum != 0xffff))
 				csum = ~csum;
 			off = hdr->csum_offset + hdr->csum_start;
diff --git a/dpdk/drivers/net/virtio/virtio_rxtx_simple_altivec.c b/dpdk/drivers/net/virtio/virtio_rxtx_simple_altivec.c
index 47225f4121..003b6ec3f6 100644
--- a/dpdk/drivers/net/virtio/virtio_rxtx_simple_altivec.c
+++ b/dpdk/drivers/net/virtio/virtio_rxtx_simple_altivec.c
@@ -9,8 +9,7 @@
 #include <string.h>
 #include <errno.h>
 
-#include <altivec.h>
-
+#include <rte_altivec.h>
 #include <rte_byteorder.h>
 #include <rte_branch_prediction.h>
 #include <rte_cycles.h>
diff --git a/dpdk/drivers/net/virtio/virtio_user/vhost_kernel.c b/dpdk/drivers/net/virtio/virtio_user/vhost_kernel.c
index 5c81e8dd9f..2c805077af 100644
--- a/dpdk/drivers/net/virtio/virtio_user/vhost_kernel.c
+++ b/dpdk/drivers/net/virtio/virtio_user/vhost_kernel.c
@@ -330,16 +330,34 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
 
 	vhostfd = dev->vhostfds[pair_idx];
 
+	if (dev->qp_enabled[pair_idx] == enable)
+		return 0;
+
 	if (!enable) {
-		if (dev->tapfds[pair_idx] >= 0) {
-			close(dev->tapfds[pair_idx]);
-			dev->tapfds[pair_idx] = -1;
+		tapfd = dev->tapfds[pair_idx];
+		if (vhost_kernel_set_backend(vhostfd, -1) < 0) {
+			PMD_DRV_LOG(ERR, "fail to set backend for vhost kernel");
+			return -1;
 		}
-		return vhost_kernel_set_backend(vhostfd, -1);
-	} else if (dev->tapfds[pair_idx] >= 0) {
+		if (req_mq && vhost_kernel_tap_set_queue(tapfd, false) < 0) {
+			PMD_DRV_LOG(ERR, "fail to disable tap for vhost kernel");
+			return -1;
+		}
+		dev->qp_enabled[pair_idx] = false;
 		return 0;
 	}
 
+	if (dev->tapfds[pair_idx] >= 0) {
+		tapfd = dev->tapfds[pair_idx];
+		if (vhost_kernel_tap_set_offload(tapfd, dev->features) == -1)
+			return -1;
+		if (req_mq && vhost_kernel_tap_set_queue(tapfd, true) < 0) {
+			PMD_DRV_LOG(ERR, "fail to enable tap for vhost kernel");
+			return -1;
+		}
+		goto set_backend;
+	}
+
 	if ((dev->features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) ||
 	    (dev->features & (1ULL << VIRTIO_F_VERSION_1)))
 		hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf);
@@ -353,13 +371,15 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
 		return -1;
 	}
 
+	dev->tapfds[pair_idx] = tapfd;
+
+set_backend:
 	if (vhost_kernel_set_backend(vhostfd, tapfd) < 0) {
 		PMD_DRV_LOG(ERR, "fail to set backend for vhost kernel");
-		close(tapfd);
 		return -1;
 	}
 
-	dev->tapfds[pair_idx] = tapfd;
+	dev->qp_enabled[pair_idx] = true;
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.c b/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.c
index 76bf75423e..79b8446f8e 100644
--- a/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.c
+++ b/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.c
@@ -18,7 +18,7 @@
 #include "../virtio_logs.h"
 #include "../virtio_pci.h"
 
-static int
+int
 vhost_kernel_tap_set_offload(int fd, uint64_t features)
 {
 	unsigned int offload = 0;
@@ -37,26 +37,34 @@ vhost_kernel_tap_set_offload(int fd, uint64_t features)
 			offload |= TUN_F_UFO;
 	}
 
-	if (offload != 0) {
-		/* Check if our kernel supports TUNSETOFFLOAD */
-		if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) {
-			PMD_DRV_LOG(ERR, "Kernel does't support TUNSETOFFLOAD\n");
-			return -ENOTSUP;
-		}
+	/* Check if our kernel supports TUNSETOFFLOAD */
+	if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) {
+		PMD_DRV_LOG(ERR, "Kernel doesn't support TUNSETOFFLOAD\n");
+		return -ENOTSUP;
+	}
 
+	if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
+		offload &= ~TUN_F_UFO;
 		if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
-			offload &= ~TUN_F_UFO;
-			if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) {
-				PMD_DRV_LOG(ERR, "TUNSETOFFLOAD ioctl() failed: %s\n",
-					strerror(errno));
-				return -1;
-			}
+			PMD_DRV_LOG(ERR, "TUNSETOFFLOAD ioctl() failed: %s\n",
+				strerror(errno));
+			return -1;
 		}
 	}
 
 	return 0;
 }
 
+int
+vhost_kernel_tap_set_queue(int fd, bool attach)
+{
+	struct ifreq ifr = {
+		.ifr_flags = attach ? IFF_ATTACH_QUEUE : IFF_DETACH_QUEUE,
+	};
+
+	return ioctl(fd, TUNSETQUEUE, &ifr);
+}
+
 int
 vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
 			 const char *mac, uint64_t features)
@@ -66,6 +74,7 @@ vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
 	int sndbuf = INT_MAX;
 	struct ifreq ifr;
 	int tapfd;
+	int ret;
 
 	/* TODO:
 	 * 1. verify we can get/set vnet_hdr_len, tap_probe_vnet_hdr_len
@@ -119,7 +128,10 @@ vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
 		goto error;
 	}
 
-	fcntl(tapfd, F_SETFL, O_NONBLOCK);
+	if (fcntl(tapfd, F_SETFL, O_NONBLOCK) < 0) {
+		PMD_DRV_LOG(ERR, "fcntl tapfd failed: %s", strerror(errno));
+		goto error;
+	}
 
 	if (ioctl(tapfd, TUNSETVNETHDRSZ, &hdr_size) < 0) {
 		PMD_DRV_LOG(ERR, "TUNSETVNETHDRSZ failed: %s", strerror(errno));
@@ -131,7 +143,9 @@ vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
 		goto error;
 	}
 
-	vhost_kernel_tap_set_offload(tapfd, features);
+	ret = vhost_kernel_tap_set_offload(tapfd, features);
+	if (ret < 0 && ret != -ENOTSUP)
+		goto error;
 
 	memset(&ifr, 0, sizeof(ifr));
 	ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
diff --git a/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.h b/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.h
index e0e95b4f59..5c4447b296 100644
--- a/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.h
+++ b/dpdk/drivers/net/virtio/virtio_user/vhost_kernel_tap.h
@@ -2,6 +2,10 @@
  * Copyright(c) 2016 Intel Corporation
  */
 
+#ifndef _VHOST_KERNEL_TAP_H
+#define _VHOST_KERNEL_TAP_H
+
+#include <stdbool.h>
 #include <sys/ioctl.h>
 
 /* TUN ioctls */
@@ -37,3 +41,7 @@
 
 int vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
 			 const char *mac, uint64_t features);
+int vhost_kernel_tap_set_offload(int fd, uint64_t features);
+int vhost_kernel_tap_set_queue(int fd, bool attach);
+
+#endif
diff --git a/dpdk/drivers/net/virtio/virtio_user/vhost_user.c b/dpdk/drivers/net/virtio/virtio_user/vhost_user.c
index a4b5c25cd3..d8e083ba8b 100644
--- a/dpdk/drivers/net/virtio/virtio_user/vhost_user.c
+++ b/dpdk/drivers/net/virtio/virtio_user/vhost_user.c
@@ -456,6 +456,9 @@ vhost_user_enable_queue_pair(struct virtio_user_dev *dev,
 {
 	int i;
 
+	if (dev->qp_enabled[pair_idx] == enable)
+		return 0;
+
 	for (i = 0; i < 2; ++i) {
 		struct vhost_vring_state state = {
 			.index = pair_idx * 2 + i,
@@ -466,6 +469,7 @@ vhost_user_enable_queue_pair(struct virtio_user_dev *dev,
 			return -1;
 	}
 
+	dev->qp_enabled[pair_idx] = enable;
 	return 0;
 }
 
diff --git a/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.c b/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.c
index ea016e85d8..ad5d2f3bf8 100644
--- a/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.c
+++ b/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.c
@@ -263,6 +263,7 @@ virtio_user_dev_init_notify(struct virtio_user_dev *dev)
 		}
 		kickfd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
 		if (kickfd < 0) {
+			close(callfd);
 			PMD_DRV_LOG(ERR, "kickfd error, %s", strerror(errno));
 			break;
 		}
@@ -271,7 +272,7 @@ virtio_user_dev_init_notify(struct virtio_user_dev *dev)
 	}
 
 	if (i < VIRTIO_MAX_VIRTQUEUES) {
-		for (j = 0; j <= i; ++j) {
+		for (j = 0; j < i; ++j) {
 			close(dev->callfds[j]);
 			close(dev->kickfds[j]);
 		}
@@ -537,7 +538,8 @@ virtio_user_dev_uninit(struct virtio_user_dev *dev)
 		close(dev->kickfds[i]);
 	}
 
-	close(dev->vhostfd);
+	if (dev->vhostfd >= 0)
+		close(dev->vhostfd);
 
 	if (dev->is_server && dev->listenfd >= 0) {
 		close(dev->listenfd);
@@ -545,8 +547,11 @@ virtio_user_dev_uninit(struct virtio_user_dev *dev)
 	}
 
 	if (dev->vhostfds) {
-		for (i = 0; i < dev->max_queue_pairs; ++i)
+		for (i = 0; i < dev->max_queue_pairs; ++i) {
 			close(dev->vhostfds[i]);
+			if (dev->tapfds[i] >= 0)
+				close(dev->tapfds[i]);
+		}
 		free(dev->vhostfds);
 		free(dev->tapfds);
 	}
diff --git a/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.h b/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.h
index ad86837717..8937124d92 100644
--- a/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.h
+++ b/dpdk/drivers/net/virtio/virtio_user/virtio_user_dev.h
@@ -41,6 +41,7 @@ struct virtio_user_dev {
 	uint64_t	frontend_features; /* enabled frontend features */
 	uint64_t	unsupported_features; /* unsupported features mask */
 	uint8_t		status;
+	uint16_t	net_status;
 	uint16_t	port_id;
 	uint8_t		mac_addr[RTE_ETHER_ADDR_LEN];
 	char		path[PATH_MAX];
@@ -49,6 +50,7 @@ struct virtio_user_dev {
 		struct vring_packed	packed_vrings[VIRTIO_MAX_VIRTQUEUES];
 	};
 	struct virtio_user_queue packed_queues[VIRTIO_MAX_VIRTQUEUES];
+	bool		qp_enabled[VIRTIO_MAX_VIRTQUEUE_PAIRS];
 
 	struct virtio_user_backend_ops *ops;
 	pthread_mutex_t	mutex;
diff --git a/dpdk/drivers/net/virtio/virtio_user_ethdev.c b/dpdk/drivers/net/virtio/virtio_user_ethdev.c
index 3fc1725736..4a35fa1c95 100644
--- a/dpdk/drivers/net/virtio/virtio_user_ethdev.c
+++ b/dpdk/drivers/net/virtio/virtio_user_ethdev.c
@@ -13,6 +13,7 @@
 #include <rte_ethdev_vdev.h>
 #include <rte_bus_vdev.h>
 #include <rte_alarm.h>
+#include <rte_cycles.h>
 
 #include "virtio_ethdev.h"
 #include "virtio_logs.h"
@@ -25,12 +26,48 @@
 #define virtio_user_get_dev(hw) \
 	((struct virtio_user_dev *)(hw)->virtio_user_dev)
 
+static void
+virtio_user_reset_queues_packed(struct rte_eth_dev *dev)
+{
+	struct virtio_hw *hw = dev->data->dev_private;
+	struct virtnet_rx *rxvq;
+	struct virtnet_tx *txvq;
+	uint16_t i;
+
+	/* Add lock to avoid queue contention. */
+	rte_spinlock_lock(&hw->state_lock);
+	hw->started = 0;
+
+	/*
+	 * Waitting for datapath to complete before resetting queues.
+	 * 1 ms should be enough for the ongoing Tx/Rx function to finish.
+	 */
+	rte_delay_ms(1);
+
+	/* Vring reset for each Tx queue and Rx queue. */
+	for (i = 0; i < dev->data->nb_rx_queues; i++) {
+		rxvq = dev->data->rx_queues[i];
+		virtqueue_rxvq_reset_packed(rxvq->vq);
+		virtio_dev_rx_queue_setup_finish(dev, i);
+	}
+
+	for (i = 0; i < dev->data->nb_tx_queues; i++) {
+		txvq = dev->data->tx_queues[i];
+		virtqueue_txvq_reset_packed(txvq->vq);
+	}
+
+	hw->started = 1;
+	rte_spinlock_unlock(&hw->state_lock);
+}
+
+
 static int
 virtio_user_server_reconnect(struct virtio_user_dev *dev)
 {
 	int ret;
 	int connectfd;
 	struct rte_eth_dev *eth_dev = &rte_eth_devices[dev->port_id];
+	struct virtio_hw *hw = eth_dev->data->dev_private;
 
 	connectfd = accept(dev->listenfd, NULL, NULL);
 	if (connectfd < 0)
@@ -51,6 +88,14 @@ virtio_user_server_reconnect(struct virtio_user_dev *dev)
 
 	dev->features &= dev->device_features;
 
+	/* For packed ring, resetting queues is required in reconnection. */
+	if (vtpci_packed_queue(hw) &&
+	   (vtpci_get_status(hw) & VIRTIO_CONFIG_STATUS_DRIVER_OK)) {
+		PMD_INIT_LOG(NOTICE, "Packets on the fly will be dropped"
+				" when packed ring reconnecting.");
+		virtio_user_reset_queues_packed(eth_dev);
+	}
+
 	ret = virtio_user_start_device(dev);
 	if (ret < 0)
 		return -1;
@@ -140,7 +185,7 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
 			}
 			r = recv(dev->vhostfd, buf, 128, MSG_PEEK);
 			if (r == 0 || (r < 0 && errno != EAGAIN)) {
-				dev->status &= (~VIRTIO_NET_S_LINK_UP);
+				dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
 				PMD_DRV_LOG(ERR, "virtio-user port %u is down",
 					    hw->port_id);
 
@@ -152,7 +197,7 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
 						  virtio_user_delayed_handler,
 						  (void *)hw);
 			} else {
-				dev->status |= VIRTIO_NET_S_LINK_UP;
+				dev->net_status |= VIRTIO_NET_S_LINK_UP;
 			}
 			if (fcntl(dev->vhostfd, F_SETFL,
 					flags & ~O_NONBLOCK) == -1) {
@@ -160,12 +205,12 @@ virtio_user_read_dev_config(struct virtio_hw *hw, size_t offset,
 				return;
 			}
 		} else if (dev->is_server) {
-			dev->status &= (~VIRTIO_NET_S_LINK_UP);
+			dev->net_status &= (~VIRTIO_NET_S_LINK_UP);
 			if (virtio_user_server_reconnect(dev) >= 0)
-				dev->status |= VIRTIO_NET_S_LINK_UP;
+				dev->net_status |= VIRTIO_NET_S_LINK_UP;
 		}
 
-		*(uint16_t *)dst = dev->status;
+		*(uint16_t *)dst = dev->net_status;
 	}
 
 	if (offset == offsetof(struct virtio_net_config, max_virtqueue_pairs))
@@ -433,12 +478,17 @@ static int
 get_integer_arg(const char *key __rte_unused,
 		const char *value, void *extra_args)
 {
+	uint64_t integer = 0;
 	if (!value || !extra_args)
 		return -EINVAL;
-
-	*(uint64_t *)extra_args = strtoull(value, NULL, 0);
-
-	return 0;
+	errno = 0;
+	integer = strtoull(value, NULL, 0);
+	/* extra_args keeps default value, it should be replaced
+	 * only in case of successful parsing of the 'value' arg
+	 */
+	if (errno == 0)
+		*(uint64_t *)extra_args = integer;
+	return -errno;
 }
 
 static struct rte_eth_dev *
@@ -517,7 +567,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 		const char *name = rte_vdev_device_name(dev);
 		eth_dev = rte_eth_dev_attach_secondary(name);
 		if (!eth_dev) {
-			RTE_LOG(ERR, PMD, "Failed to probe %s\n", name);
+			PMD_INIT_LOG(ERR, "Failed to probe %s", name);
 			return -1;
 		}
 
@@ -669,7 +719,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
 		goto end;
 	}
 
-	/* previously called by rte_pci_probe() for physical dev */
+	/* previously called by pci probing for physical dev */
 	if (eth_virtio_dev_init(eth_dev) < 0) {
 		PMD_INIT_LOG(ERR, "eth_virtio_dev_init fails");
 		virtio_user_eth_dev_free(eth_dev);
diff --git a/dpdk/drivers/net/virtio/virtqueue.c b/dpdk/drivers/net/virtio/virtqueue.c
index 5ff1e3587e..02c8b9fc54 100644
--- a/dpdk/drivers/net/virtio/virtqueue.c
+++ b/dpdk/drivers/net/virtio/virtqueue.c
@@ -141,3 +141,76 @@ virtqueue_rxvq_flush(struct virtqueue *vq)
 	else
 		virtqueue_rxvq_flush_split(vq);
 }
+
+int
+virtqueue_rxvq_reset_packed(struct virtqueue *vq)
+{
+	int size = vq->vq_nentries;
+	struct vq_desc_extra *dxp;
+	struct virtnet_rx *rxvq;
+	uint16_t desc_idx;
+
+	vq->vq_used_cons_idx = 0;
+	vq->vq_desc_head_idx = 0;
+	vq->vq_avail_idx = 0;
+	vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
+	vq->vq_free_cnt = vq->vq_nentries;
+
+	vq->vq_packed.used_wrap_counter = 1;
+	vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL;
+	vq->vq_packed.event_flags_shadow = 0;
+	vq->vq_packed.cached_flags |= VRING_DESC_F_WRITE;
+
+	rxvq = &vq->rxq;
+	memset(rxvq->mz->addr, 0, rxvq->mz->len);
+
+	for (desc_idx = 0; desc_idx < vq->vq_nentries; desc_idx++) {
+		dxp = &vq->vq_descx[desc_idx];
+		if (dxp->cookie != NULL) {
+			rte_pktmbuf_free(dxp->cookie);
+			dxp->cookie = NULL;
+		}
+	}
+
+	vring_desc_init_packed(vq, size);
+
+	virtqueue_disable_intr(vq);
+	return 0;
+}
+
+int
+virtqueue_txvq_reset_packed(struct virtqueue *vq)
+{
+	int size = vq->vq_nentries;
+	struct vq_desc_extra *dxp;
+	struct virtnet_tx *txvq;
+	uint16_t desc_idx;
+
+	vq->vq_used_cons_idx = 0;
+	vq->vq_desc_head_idx = 0;
+	vq->vq_avail_idx = 0;
+	vq->vq_desc_tail_idx = (uint16_t)(vq->vq_nentries - 1);
+	vq->vq_free_cnt = vq->vq_nentries;
+
+	vq->vq_packed.used_wrap_counter = 1;
+	vq->vq_packed.cached_flags = VRING_PACKED_DESC_F_AVAIL;
+	vq->vq_packed.event_flags_shadow = 0;
+
+	txvq = &vq->txq;
+	memset(txvq->mz->addr, 0, txvq->mz->len);
+	memset(txvq->virtio_net_hdr_mz->addr, 0,
+		txvq->virtio_net_hdr_mz->len);
+
+	for (desc_idx = 0; desc_idx < vq->vq_nentries; desc_idx++) {
+		dxp = &vq->vq_descx[desc_idx];
+		if (dxp->cookie != NULL) {
+			rte_pktmbuf_free(dxp->cookie);
+			dxp->cookie = NULL;
+		}
+	}
+
+	vring_desc_init_packed(vq, size);
+
+	virtqueue_disable_intr(vq);
+	return 0;
+}
diff --git a/dpdk/drivers/net/virtio/virtqueue.h b/dpdk/drivers/net/virtio/virtqueue.h
index 8d7f197b13..e901249601 100644
--- a/dpdk/drivers/net/virtio/virtqueue.h
+++ b/dpdk/drivers/net/virtio/virtqueue.h
@@ -324,8 +324,11 @@ struct virtio_net_hdr_mrg_rxbuf {
 #define VIRTIO_MAX_TX_INDIRECT 8
 struct virtio_tx_region {
 	struct virtio_net_hdr_mrg_rxbuf tx_hdr;
-	struct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT]
-		__attribute__((__aligned__(16)));
+	union {
+		struct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT];
+		struct vring_packed_desc
+			tx_packed_indir[VIRTIO_MAX_TX_INDIRECT];
+	} __attribute__((__aligned__(16)));
 };
 
 static inline int
@@ -363,6 +366,16 @@ vring_desc_init_split(struct vring_desc *dp, uint16_t n)
 	dp[i].next = VQ_RING_DESC_CHAIN_END;
 }
 
+static inline void
+vring_desc_init_indirect_packed(struct vring_packed_desc *dp, int n)
+{
+	int i;
+	for (i = 0; i < n; i++) {
+		dp[i].id = (uint16_t)i;
+		dp[i].flags = VRING_DESC_F_WRITE;
+	}
+}
+
 /**
  * Tell the backend not to interrupt us. Implementation for packed virtqueues.
  */
@@ -443,6 +456,10 @@ struct rte_mbuf *virtqueue_detach_unused(struct virtqueue *vq);
 /* Flush the elements in the used ring. */
 void virtqueue_rxvq_flush(struct virtqueue *vq);
 
+int virtqueue_rxvq_reset_packed(struct virtqueue *vq);
+
+int virtqueue_txvq_reset_packed(struct virtqueue *vq);
+
 static inline int
 virtqueue_full(const struct virtqueue *vq)
 {
diff --git a/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c b/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 6e6efa9603..705e9760f4 100644
--- a/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -771,7 +771,8 @@ vmxnet3_dev_start(struct rte_eth_dev *dev)
 		PMD_INIT_LOG(DEBUG, "Failed to setup memory region\n");
 	}
 
-	if (VMXNET3_VERSION_GE_4(hw)) {
+	if (VMXNET3_VERSION_GE_4(hw) &&
+	    dev->data->dev_conf.rxmode.mq_mode == ETH_MQ_RX_RSS) {
 		/* Check for additional RSS  */
 		ret = vmxnet3_v4_rss_configure(dev);
 		if (ret != VMXNET3_SUCCESS) {
diff --git a/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.h b/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.h
index 8c2b6f8771..dd685b02b7 100644
--- a/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.h
+++ b/dpdk/drivers/net/vmxnet3/vmxnet3_ethdev.h
@@ -38,6 +38,10 @@
 	ETH_RSS_NONFRAG_IPV4_UDP | \
 	ETH_RSS_NONFRAG_IPV6_UDP)
 
+#define VMXNET3_MANDATORY_V4_RSS ( \
+	ETH_RSS_NONFRAG_IPV4_TCP | \
+	ETH_RSS_NONFRAG_IPV6_TCP)
+
 /* RSS configuration structure - shared with device through GPA */
 typedef struct VMXNET3_RSSConf {
 	uint16_t   hashType;
diff --git a/dpdk/drivers/net/vmxnet3/vmxnet3_rxtx.c b/dpdk/drivers/net/vmxnet3/vmxnet3_rxtx.c
index 7794d74214..73e270f30f 100644
--- a/dpdk/drivers/net/vmxnet3/vmxnet3_rxtx.c
+++ b/dpdk/drivers/net/vmxnet3/vmxnet3_rxtx.c
@@ -950,13 +950,17 @@ vmxnet3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 			RTE_ASSERT(rxd->btype == VMXNET3_RXD_BTYPE_BODY);
 
-			if (rxm->data_len) {
+			if (likely(start && rxm->data_len > 0)) {
 				start->pkt_len += rxm->data_len;
 				start->nb_segs++;
 
 				rxq->last_seg->next = rxm;
 				rxq->last_seg = rxm;
 			} else {
+				PMD_RX_LOG(ERR, "Error received empty or out of order frame.");
+				rxq->stats.drop_total++;
+				rxq->stats.drop_err++;
+
 				rte_pktmbuf_free_seg(rxm);
 			}
 		}
@@ -1311,6 +1315,14 @@ vmxnet3_v4_rss_configure(struct rte_eth_dev *dev)
 
 	cmdInfo->setRSSFields = 0;
 	port_rss_conf = &dev->data->dev_conf.rx_adv_conf.rss_conf;
+
+	if ((port_rss_conf->rss_hf & VMXNET3_MANDATORY_V4_RSS) !=
+	    VMXNET3_MANDATORY_V4_RSS) {
+		PMD_INIT_LOG(WARNING, "RSS: IPv4/6 TCP is required for vmxnet3 v4 RSS,"
+			     "automatically setting it");
+		port_rss_conf->rss_hf |= VMXNET3_MANDATORY_V4_RSS;
+	}
+
 	rss_hf = port_rss_conf->rss_hf &
 		(VMXNET3_V4_RSS_MASK | VMXNET3_RSS_OFFLOAD_ALL);
 
diff --git a/dpdk/drivers/raw/dpaa2_qdma/dpaa2_qdma.c b/dpdk/drivers/raw/dpaa2_qdma/dpaa2_qdma.c
index c905954004..b31d7aacb3 100644
--- a/dpdk/drivers/raw/dpaa2_qdma/dpaa2_qdma.c
+++ b/dpdk/drivers/raw/dpaa2_qdma/dpaa2_qdma.c
@@ -455,9 +455,10 @@ rte_qdma_reset(void)
 	/* In case there are pending jobs on any VQ, return -EBUSY */
 	for (i = 0; i < qdma_dev.max_vqs; i++) {
 		if (qdma_vqs[i].in_use && (qdma_vqs[i].num_enqueues !=
-		    qdma_vqs[i].num_dequeues))
+		    qdma_vqs[i].num_dequeues)) {
 			DPAA2_QDMA_ERR("Jobs are still pending on VQ: %d", i);
 			return -EBUSY;
+		}
 	}
 
 	/* Reset HW queues */
diff --git a/dpdk/drivers/raw/ifpga/base/ifpga_fme.c b/dpdk/drivers/raw/ifpga/base/ifpga_fme.c
index c31a94cf80..9057087b55 100644
--- a/dpdk/drivers/raw/ifpga/base/ifpga_fme.c
+++ b/dpdk/drivers/raw/ifpga/base/ifpga_fme.c
@@ -979,28 +979,32 @@ struct ifpga_feature_ops fme_spi_master_ops = {
 static int nios_spi_wait_init_done(struct altera_spi_device *dev)
 {
 	u32 val = 0;
-	unsigned long timeout = msecs_to_timer_cycles(10000);
+	unsigned long timeout = rte_get_timer_cycles() +
+			msecs_to_timer_cycles(10000);
 	unsigned long ticks;
 	int major_version;
+	int fecmode = FEC_MODE_NO;
 
 	if (spi_reg_read(dev, NIOS_VERSION, &val))
 		return -EIO;
 
-	major_version = (val >> NIOS_VERSION_MAJOR_SHIFT) &
-		NIOS_VERSION_MAJOR;
-	dev_debug(dev, "A10 NIOS FW version %d\n", major_version);
+	major_version =
+		(val & NIOS_VERSION_MAJOR) >> NIOS_VERSION_MAJOR_SHIFT;
+	dev_info(dev, "A10 NIOS FW version %d\n", major_version);
 
 	if (major_version >= 3) {
 		/* read NIOS_INIT to check if PKVL INIT done or not */
 		if (spi_reg_read(dev, NIOS_INIT, &val))
 			return -EIO;
 
+		dev_debug(dev, "read NIOS_INIT: 0x%x\n", val);
+
 		/* check if PKVLs are initialized already */
 		if (val & NIOS_INIT_DONE || val & NIOS_INIT_START)
 			goto nios_init_done;
 
 		/* start to config the default FEC mode */
-		val = NIOS_INIT_START;
+		val = fecmode | NIOS_INIT_START;
 
 		if (spi_reg_write(dev, NIOS_INIT, val))
 			return -EIO;
@@ -1010,14 +1014,23 @@ static int nios_spi_wait_init_done(struct altera_spi_device *dev)
 	do {
 		if (spi_reg_read(dev, NIOS_INIT, &val))
 			return -EIO;
-		if (val)
+		if (val & NIOS_INIT_DONE)
 			break;
 
 		ticks = rte_get_timer_cycles();
 		if (time_after(ticks, timeout))
 			return -ETIMEDOUT;
 		msleep(100);
-	} while (!val);
+	} while (1);
+
+	/* get the fecmode */
+	if (spi_reg_read(dev, NIOS_INIT, &val))
+		return -EIO;
+	dev_debug(dev, "read NIOS_INIT: 0x%x\n", val);
+	fecmode = (val & REQ_FEC_MODE) >> REQ_FEC_MODE_SHIFT;
+	dev_info(dev, "fecmode: 0x%x, %s\n", fecmode,
+			(fecmode == FEC_MODE_KR) ? "kr" :
+			((fecmode == FEC_MODE_RS) ? "rs" : "no"));
 
 	return 0;
 }
diff --git a/dpdk/drivers/raw/ifpga/base/opae_spi.h b/dpdk/drivers/raw/ifpga/base/opae_spi.h
index d20a4c3edd..73a2276739 100644
--- a/dpdk/drivers/raw/ifpga/base/opae_spi.h
+++ b/dpdk/drivers/raw/ifpga/base/opae_spi.h
@@ -153,6 +153,7 @@ int spi_reg_read(struct altera_spi_device *dev, u32 reg, u32 *val);
 
 #define NIOS_INIT		0x1000
 #define REQ_FEC_MODE		GENMASK(23, 8)
+#define REQ_FEC_MODE_SHIFT      8
 #define FEC_MODE_NO		0x0
 #define FEC_MODE_KR		0x5555
 #define FEC_MODE_RS		0xaaaa
diff --git a/dpdk/drivers/raw/ifpga/base/opae_spi_transaction.c b/dpdk/drivers/raw/ifpga/base/opae_spi_transaction.c
index 013efee3e6..d13d2fbc83 100644
--- a/dpdk/drivers/raw/ifpga/base/opae_spi_transaction.c
+++ b/dpdk/drivers/raw/ifpga/base/opae_spi_transaction.c
@@ -166,7 +166,7 @@ static int byte_to_core_convert(struct spi_transaction_dev *dev,
 		current_byte = send_data[i];
 		switch (current_byte) {
 		case SPI_BYTE_IDLE:
-			*p++ = SPI_BYTE_IDLE;
+			*p++ = SPI_BYTE_ESC;
 			*p++ = xor_20(current_byte);
 			break;
 		case SPI_BYTE_ESC:
diff --git a/dpdk/drivers/raw/ifpga/ifpga_rawdev.c b/dpdk/drivers/raw/ifpga/ifpga_rawdev.c
index b8701e155b..0c5392d082 100644
--- a/dpdk/drivers/raw/ifpga/ifpga_rawdev.c
+++ b/dpdk/drivers/raw/ifpga/ifpga_rawdev.c
@@ -237,8 +237,9 @@ static int ifpga_rawdev_fill_info(struct ifpga_rawdev *ifpga_dev,
 	memset(link, 0, sizeof(link));
 	memset(link1, 0, sizeof(link1));
 	ret = readlink(path, link, (sizeof(link)-1));
-	if (ret == -1)
+	if ((ret < 0) || ((unsigned int)ret > (sizeof(link)-1)))
 		return -1;
+	link[ret] = 0;   /* terminate string with null character */
 	strlcpy(link1, link, sizeof(link1));
 	memset(ifpga_dev->parent_bdf, 0, 16);
 	point = strlen(link);
@@ -779,7 +780,7 @@ rte_fpga_do_pr(struct rte_rawdev *rawdev, int port_id,
 	int file_fd;
 	int ret = 0;
 	ssize_t buffer_size;
-	void *buffer;
+	void *buffer, *buf_to_free;
 	u64 pr_error;
 
 	if (!file_name)
@@ -811,6 +812,7 @@ rte_fpga_do_pr(struct rte_rawdev *rawdev, int port_id,
 		ret = -ENOMEM;
 		goto close_fd;
 	}
+	buf_to_free = buffer;
 
 	/*read the raw data*/
 	if (buffer_size != read(file_fd, (void *)buffer, buffer_size)) {
@@ -828,8 +830,8 @@ rte_fpga_do_pr(struct rte_rawdev *rawdev, int port_id,
 	}
 
 free_buffer:
-	if (buffer)
-		rte_free(buffer);
+	if (buf_to_free)
+		rte_free(buf_to_free);
 close_fd:
 	close(file_fd);
 	file_fd = 0;
@@ -1336,17 +1338,18 @@ int
 ifpga_unregister_msix_irq(enum ifpga_irq_type type,
 		int vec_start, rte_intr_callback_fn handler, void *arg)
 {
-	struct rte_intr_handle intr_handle;
+	struct rte_intr_handle *intr_handle;
 
 	if (type == IFPGA_FME_IRQ)
-		intr_handle = ifpga_irq_handle[0];
+		intr_handle = &ifpga_irq_handle[0];
 	else if (type == IFPGA_AFU_IRQ)
-		intr_handle = ifpga_irq_handle[vec_start + 1];
+		intr_handle = &ifpga_irq_handle[vec_start + 1];
+	else
+		return 0;
 
-	rte_intr_efd_disable(&intr_handle);
+	rte_intr_efd_disable(intr_handle);
 
-	return rte_intr_callback_unregister(&intr_handle,
-			handler, arg);
+	return rte_intr_callback_unregister(intr_handle, handler, arg);
 }
 
 int
@@ -1356,7 +1359,7 @@ ifpga_register_msix_irq(struct rte_rawdev *dev, int port_id,
 		void *arg)
 {
 	int ret;
-	struct rte_intr_handle intr_handle;
+	struct rte_intr_handle *intr_handle;
 	struct opae_adapter *adapter;
 	struct opae_manager *mgr;
 	struct opae_accelerator *acc;
@@ -1370,26 +1373,29 @@ ifpga_register_msix_irq(struct rte_rawdev *dev, int port_id,
 		return -ENODEV;
 
 	if (type == IFPGA_FME_IRQ) {
-		intr_handle = ifpga_irq_handle[0];
+		intr_handle = &ifpga_irq_handle[0];
 		count = 1;
-	} else if (type == IFPGA_AFU_IRQ)
-		intr_handle = ifpga_irq_handle[vec_start + 1];
+	} else if (type == IFPGA_AFU_IRQ) {
+		intr_handle = &ifpga_irq_handle[vec_start + 1];
+	} else {
+		return -EINVAL;
+	}
 
-	intr_handle.type = RTE_INTR_HANDLE_VFIO_MSIX;
+	intr_handle->type = RTE_INTR_HANDLE_VFIO_MSIX;
 
-	ret = rte_intr_efd_enable(&intr_handle, count);
+	ret = rte_intr_efd_enable(intr_handle, count);
 	if (ret)
 		return -ENODEV;
 
-	intr_handle.fd = intr_handle.efds[0];
+	intr_handle->fd = intr_handle->efds[0];
 
 	IFPGA_RAWDEV_PMD_DEBUG("register %s irq, vfio_fd=%d, fd=%d\n",
-			name, intr_handle.vfio_dev_fd,
-			intr_handle.fd);
+			name, intr_handle->vfio_dev_fd,
+			intr_handle->fd);
 
 	if (type == IFPGA_FME_IRQ) {
 		struct fpga_fme_err_irq_set err_irq_set;
-		err_irq_set.evtfd = intr_handle.efds[0];
+		err_irq_set.evtfd = intr_handle->efds[0];
 
 		ret = opae_manager_ifpga_set_err_irq(mgr, &err_irq_set);
 		if (ret)
@@ -1399,13 +1405,14 @@ ifpga_register_msix_irq(struct rte_rawdev *dev, int port_id,
 		if (!acc)
 			return -EINVAL;
 
-		ret = opae_acc_set_irq(acc, vec_start, count, intr_handle.efds);
+		ret = opae_acc_set_irq(acc, vec_start, count,
+				intr_handle->efds);
 		if (ret)
 			return -EINVAL;
 	}
 
 	/* register interrupt handler using DPDK API */
-	ret = rte_intr_callback_register(&intr_handle,
+	ret = rte_intr_callback_register(intr_handle,
 			handler, (void *)arg);
 	if (ret)
 		return -EINVAL;
@@ -1558,7 +1565,7 @@ ifpga_rawdev_destroy(struct rte_pci_device *pci_dev)
 		return -ENODEV;
 
 	if (ifpga_unregister_msix_irq(IFPGA_FME_IRQ, 0,
-				fme_interrupt_handler, mgr))
+				fme_interrupt_handler, mgr) < 0)
 		return -EINVAL;
 
 	opae_adapter_data_free(adapter->data);
diff --git a/dpdk/drivers/raw/ifpga/meson.build b/dpdk/drivers/raw/ifpga/meson.build
index 206136ff48..c267373e5e 100644
--- a/dpdk/drivers/raw/ifpga/meson.build
+++ b/dpdk/drivers/raw/ifpga/meson.build
@@ -1,11 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2018 Intel Corporation
 
-dep = dependency('libfdt', required: false)
-if not dep.found()
-	dep = cc.find_library('libfdt', required: false)
-endif
-if not dep.found()
+if has_libfdt == 0
 	build = false
 	reason = 'missing dependency, "libfdt"'
 endif
@@ -15,8 +11,7 @@ if build
 	objs = [base_objs]
 
 	deps += ['ethdev', 'rawdev', 'pci', 'bus_pci', 'kvargs',
-		'bus_vdev', 'bus_ifpga', 'net', 'i40e', 'ipn3ke']
-	ext_deps += dep
+		'bus_vdev', 'bus_ifpga', 'net', 'pmd_i40e', 'pmd_ipn3ke']
 
 	sources = files('ifpga_rawdev.c')
 
diff --git a/dpdk/drivers/raw/ioat/ioat_rawdev.c b/dpdk/drivers/raw/ioat/ioat_rawdev.c
index af8414b34c..a9b762330a 100644
--- a/dpdk/drivers/raw/ioat/ioat_rawdev.c
+++ b/dpdk/drivers/raw/ioat/ioat_rawdev.c
@@ -198,6 +198,12 @@ ioat_xstats_reset(struct rte_rawdev *dev, const uint32_t *ids, uint32_t nb_ids)
 	return 0;
 }
 
+static int
+ioat_dev_close(struct rte_rawdev *dev __rte_unused)
+{
+	return 0;
+}
+
 extern int ioat_rawdev_test(uint16_t dev_id);
 
 static int
@@ -207,6 +213,7 @@ ioat_rawdev_create(const char *name, struct rte_pci_device *dev)
 			.dev_configure = ioat_dev_configure,
 			.dev_start = ioat_dev_start,
 			.dev_stop = ioat_dev_stop,
+			.dev_close = ioat_dev_close,
 			.dev_info_get = ioat_dev_info_get,
 			.xstats_get = ioat_xstats_get,
 			.xstats_get_names = ioat_xstats_get_names,
diff --git a/dpdk/drivers/raw/ntb/ntb.c b/dpdk/drivers/raw/ntb/ntb.c
index ad7f6abfd3..dd0b72f8c5 100644
--- a/dpdk/drivers/raw/ntb/ntb.c
+++ b/dpdk/drivers/raw/ntb/ntb.c
@@ -683,8 +683,8 @@ ntb_enqueue_bufs(struct rte_rawdev *dev,
 			   sizeof(struct ntb_used) * nb1);
 		rte_memcpy(txq->tx_used_ring, tx_used + nb1,
 			   sizeof(struct ntb_used) * nb2);
-		*txq->used_cnt = txq->last_used;
 		rte_wmb();
+		*txq->used_cnt = txq->last_used;
 
 		/* update queue stats */
 		hw->ntb_xstats[NTB_TX_BYTES_ID + off] += bytes;
@@ -789,8 +789,8 @@ ntb_dequeue_bufs(struct rte_rawdev *dev,
 			   sizeof(struct ntb_desc) * nb1);
 		rte_memcpy(rxq->rx_desc_ring, rx_desc + nb1,
 			   sizeof(struct ntb_desc) * nb2);
-		*rxq->avail_cnt = rxq->last_avail;
 		rte_wmb();
+		*rxq->avail_cnt = rxq->last_avail;
 
 		/* update queue stats */
 		off = NTB_XSTATS_NUM * ((size_t)context + 1);
diff --git a/dpdk/drivers/raw/skeleton/skeleton_rawdev.c b/dpdk/drivers/raw/skeleton/skeleton_rawdev.c
index 586183a5b8..1daf0fecd2 100644
--- a/dpdk/drivers/raw/skeleton/skeleton_rawdev.c
+++ b/dpdk/drivers/raw/skeleton/skeleton_rawdev.c
@@ -189,9 +189,11 @@ static int skeleton_rawdev_close(struct rte_rawdev *dev)
 		}
 		break;
 	case SKELETON_FW_READY:
+		SKELETON_PMD_DEBUG("Device already in stopped state");
+		break;
 	case SKELETON_FW_ERROR:
 	default:
-		SKELETON_PMD_DEBUG("Device already in stopped state");
+		SKELETON_PMD_DEBUG("Device in impossible state");
 		ret = -EINVAL;
 		break;
 	}
diff --git a/dpdk/drivers/raw/skeleton/skeleton_rawdev_test.c b/dpdk/drivers/raw/skeleton/skeleton_rawdev_test.c
index 9ecfdee818..1190e28bb7 100644
--- a/dpdk/drivers/raw/skeleton/skeleton_rawdev_test.c
+++ b/dpdk/drivers/raw/skeleton/skeleton_rawdev_test.c
@@ -42,6 +42,12 @@ static int
 testsuite_setup(void)
 {
 	uint8_t count;
+
+	total = 0;
+	passed = 0;
+	failed = 0;
+	unsupported = 0;
+
 	count = rte_rawdev_count();
 	if (!count) {
 		SKELDEV_TEST_INFO("\tNo existing rawdev; "
diff --git a/dpdk/examples/bbdev_app/Makefile b/dpdk/examples/bbdev_app/Makefile
index ead3f016b8..3c8eb75a4e 100644
--- a/dpdk/examples/bbdev_app/Makefile
+++ b/dpdk/examples/bbdev_app/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/bbdev_app/main.c b/dpdk/examples/bbdev_app/main.c
index fb38dc3a72..68a46050c0 100644
--- a/dpdk/examples/bbdev_app/main.c
+++ b/dpdk/examples/bbdev_app/main.c
@@ -659,6 +659,8 @@ print_stats(struct stats_lcore_params *stats_lcore)
 		print_lcore_stats(stats_lcore->lconf[l_id].lcore_stats, l_id);
 	}
 
+	fflush(stdout);
+
 	free(xstats);
 	free(xstats_names);
 }
diff --git a/dpdk/examples/bond/Makefile b/dpdk/examples/bond/Makefile
index 2030ca410a..4e4289e151 100644
--- a/dpdk/examples/bond/Makefile
+++ b/dpdk/examples/bond/Makefile
@@ -24,7 +24,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/cmdline/Makefile b/dpdk/examples/cmdline/Makefile
index 0b6b54540a..9418b50b87 100644
--- a/dpdk/examples/cmdline/Makefile
+++ b/dpdk/examples/cmdline/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/distributor/Makefile b/dpdk/examples/distributor/Makefile
index 4192d8a4ae..5253780793a 100644
--- a/dpdk/examples/distributor/Makefile
+++ b/dpdk/examples/distributor/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/ethtool/lib/rte_ethtool.c b/dpdk/examples/ethtool/lib/rte_ethtool.c
index 667d7eaf27..db8150efd5 100644
--- a/dpdk/examples/ethtool/lib/rte_ethtool.c
+++ b/dpdk/examples/ethtool/lib/rte_ethtool.c
@@ -402,7 +402,9 @@ rte_ethtool_net_set_rx_mode(uint16_t port_id)
 	}
 
 	/* Enable Rx vlan filter, VF unspport status is discard */
-	rte_eth_dev_set_vlan_offload(port_id, ETH_VLAN_FILTER_MASK);
+	ret = rte_eth_dev_set_vlan_offload(port_id, ETH_VLAN_FILTER_MASK);
+	if (ret != 0)
+		return ret;
 
 	return 0;
 }
diff --git a/dpdk/examples/eventdev_pipeline/Makefile b/dpdk/examples/eventdev_pipeline/Makefile
index 96cd244378..95a8d0884a 100644
--- a/dpdk/examples/eventdev_pipeline/Makefile
+++ b/dpdk/examples/eventdev_pipeline/Makefile
@@ -24,7 +24,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/eventdev_pipeline/main.c b/dpdk/examples/eventdev_pipeline/main.c
index d3ff1bbe4f..a3eeb50a75 100644
--- a/dpdk/examples/eventdev_pipeline/main.c
+++ b/dpdk/examples/eventdev_pipeline/main.c
@@ -10,6 +10,8 @@
 
 #include "pipeline_common.h"
 
+struct fastpath_data *fdata;
+
 struct config_data cdata = {
 	.num_packets = (1L << 25), /* do ~32M packets */
 	.num_fids = 512,
@@ -20,6 +22,32 @@ struct config_data cdata = {
 	.worker_cq_depth = 16
 };
 
+static void
+dump_core_info(unsigned int lcore_id, struct worker_data *data,
+		unsigned int worker_idx)
+{
+	if (fdata->rx_core[lcore_id])
+		printf(
+			"[%s()] lcore %d executing NIC Rx\n",
+			__func__, lcore_id);
+
+	if (fdata->tx_core[lcore_id])
+		printf(
+			"[%s()] lcore %d executing NIC Tx\n",
+			__func__, lcore_id);
+
+	if (fdata->sched_core[lcore_id])
+		printf(
+			"[%s()] lcore %d executing scheduler\n",
+			__func__, lcore_id);
+
+	if (fdata->worker_core[lcore_id])
+		printf(
+			"[%s()] lcore %d executing worker, using eventdev port %u\n",
+			__func__, lcore_id,
+			data[worker_idx].port_id);
+}
+
 static bool
 core_in_use(unsigned int lcore_id) {
 	return (fdata->rx_core[lcore_id] || fdata->sched_core[lcore_id] ||
@@ -79,7 +107,7 @@ parse_coremask(const char *coremask)
 		val = xdigit2val(c);
 		for (j = 0; j < BITS_HEX && idx < MAX_NUM_CORE; j++, idx++) {
 			if ((1 << j) & val) {
-				mask |= (1UL << idx);
+				mask |= (1ULL << idx);
 				count++;
 			}
 		}
@@ -230,15 +258,22 @@ parse_app_args(int argc, char **argv)
 		usage();
 
 	for (i = 0; i < MAX_NUM_CORE; i++) {
-		fdata->rx_core[i] = !!(rx_lcore_mask & (1UL << i));
-		fdata->tx_core[i] = !!(tx_lcore_mask & (1UL << i));
-		fdata->sched_core[i] = !!(sched_lcore_mask & (1UL << i));
-		fdata->worker_core[i] = !!(worker_lcore_mask & (1UL << i));
+		fdata->rx_core[i] = !!(rx_lcore_mask & (1ULL << i));
+		fdata->tx_core[i] = !!(tx_lcore_mask & (1ULL << i));
+		fdata->sched_core[i] = !!(sched_lcore_mask & (1ULL << i));
+		fdata->worker_core[i] = !!(worker_lcore_mask & (1ULL << i));
 
 		if (fdata->worker_core[i])
 			cdata.num_workers++;
-		if (core_in_use(i))
+		if (core_in_use(i)) {
+			if (!rte_lcore_is_enabled(i)) {
+				printf("lcore %d is not enabled in lcore list\n",
+					i);
+				rte_exit(EXIT_FAILURE,
+					"check lcore params failed\n");
+			}
 			cdata.active_cores++;
+		}
 	}
 }
 
@@ -278,7 +313,6 @@ static void
 signal_handler(int signum)
 {
 	static uint8_t once;
-	uint16_t portid;
 
 	if (fdata->done)
 		rte_exit(1, "Exiting on signal %d\n", signum);
@@ -289,22 +323,6 @@ signal_handler(int signum)
 			rte_event_dev_dump(0, stdout);
 		once = 1;
 		fdata->done = 1;
-		rte_smp_wmb();
-
-		RTE_ETH_FOREACH_DEV(portid) {
-			rte_event_eth_rx_adapter_stop(portid);
-			rte_event_eth_tx_adapter_stop(portid);
-			rte_eth_dev_stop(portid);
-		}
-
-		rte_eal_mp_wait_lcore();
-
-		RTE_ETH_FOREACH_DEV(portid) {
-			rte_eth_dev_close(portid);
-		}
-
-		rte_event_dev_stop(0);
-		rte_event_dev_close(0);
 	}
 	if (signum == SIGTSTP)
 		rte_event_dev_dump(0, stdout);
@@ -409,25 +427,7 @@ main(int argc, char **argv)
 			!fdata->sched_core[lcore_id])
 			continue;
 
-		if (fdata->rx_core[lcore_id])
-			printf(
-				"[%s()] lcore %d executing NIC Rx\n",
-				__func__, lcore_id);
-
-		if (fdata->tx_core[lcore_id])
-			printf(
-				"[%s()] lcore %d executing NIC Tx\n",
-				__func__, lcore_id);
-
-		if (fdata->sched_core[lcore_id])
-			printf("[%s()] lcore %d executing scheduler\n",
-					__func__, lcore_id);
-
-		if (fdata->worker_core[lcore_id])
-			printf(
-				"[%s()] lcore %d executing worker, using eventdev port %u\n",
-				__func__, lcore_id,
-				worker_data[worker_idx].port_id);
+		dump_core_info(lcore_id, worker_data, worker_idx);
 
 		err = rte_eal_remote_launch(fdata->cap.worker,
 				&worker_data[worker_idx], lcore_id);
@@ -442,8 +442,13 @@ main(int argc, char **argv)
 
 	lcore_id = rte_lcore_id();
 
-	if (core_in_use(lcore_id))
-		fdata->cap.worker(&worker_data[worker_idx++]);
+	if (core_in_use(lcore_id)) {
+		dump_core_info(lcore_id, worker_data, worker_idx);
+		fdata->cap.worker(&worker_data[worker_idx]);
+
+		if (fdata->worker_core[lcore_id])
+			worker_idx++;
+	}
 
 	rte_eal_mp_wait_lcore();
 
@@ -467,5 +472,17 @@ main(int argc, char **argv)
 
 	}
 
+	RTE_ETH_FOREACH_DEV(portid) {
+		rte_event_eth_rx_adapter_stop(portid);
+		rte_event_eth_tx_adapter_stop(portid);
+		rte_eth_dev_stop(portid);
+		rte_eth_dev_close(portid);
+	}
+
+	rte_event_dev_stop(0);
+	rte_event_dev_close(0);
+
+	rte_eal_cleanup();
+
 	return 0;
 }
diff --git a/dpdk/examples/eventdev_pipeline/pipeline_common.h b/dpdk/examples/eventdev_pipeline/pipeline_common.h
index 8e30393d09..6a4287602e 100644
--- a/dpdk/examples/eventdev_pipeline/pipeline_common.h
+++ b/dpdk/examples/eventdev_pipeline/pipeline_common.h
@@ -51,10 +51,10 @@ struct fastpath_data {
 	bool rx_single;
 	bool tx_single;
 	bool sched_single;
-	unsigned int rx_core[MAX_NUM_CORE];
-	unsigned int tx_core[MAX_NUM_CORE];
-	unsigned int sched_core[MAX_NUM_CORE];
-	unsigned int worker_core[MAX_NUM_CORE];
+	uint64_t rx_core[MAX_NUM_CORE];
+	uint64_t tx_core[MAX_NUM_CORE];
+	uint64_t sched_core[MAX_NUM_CORE];
+	uint64_t worker_core[MAX_NUM_CORE];
 	struct setup_data cap;
 } __rte_cache_aligned;
 
@@ -93,8 +93,8 @@ struct port_link {
 	uint8_t priority;
 };
 
-struct fastpath_data *fdata;
-struct config_data cdata;
+extern struct fastpath_data *fdata;
+extern struct config_data cdata;
 
 static __rte_always_inline void
 exchange_mac(struct rte_mbuf *m)
diff --git a/dpdk/examples/fips_validation/Makefile b/dpdk/examples/fips_validation/Makefile
index 1385e8cc8c..5bcf1872c4 100644
--- a/dpdk/examples/fips_validation/Makefile
+++ b/dpdk/examples/fips_validation/Makefile
@@ -31,7 +31,9 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/fips_validation/fips_validation.c b/dpdk/examples/fips_validation/fips_validation.c
index 07ffa62e9e..701d87dc4d 100644
--- a/dpdk/examples/fips_validation/fips_validation.c
+++ b/dpdk/examples/fips_validation/fips_validation.c
@@ -92,6 +92,15 @@ fips_test_fetch_one_block(void)
 	return -ENOMEM;
 }
 
+static void
+fips_test_parse_version(void)
+{
+	int len = strlen(info.vec[0]);
+	char *ptr = info.vec[0];
+
+	info.version = strtof(ptr + len - 4, NULL);
+}
+
 static int
 fips_test_parse_header(void)
 {
@@ -106,6 +115,9 @@ fips_test_parse_header(void)
 	if (ret < 0)
 		return ret;
 
+	if (info.nb_vec_lines)
+		fips_test_parse_version();
+
 	for (i = 0; i < info.nb_vec_lines; i++) {
 		if (!algo_parsed) {
 			if (strstr(info.vec[i], "AESVS")) {
@@ -144,6 +156,24 @@ fips_test_parse_header(void)
 				ret = parse_test_tdes_init();
 				if (ret < 0)
 					return 0;
+			} else if (strstr(info.vec[i], "PERMUTATION")) {
+				algo_parsed = 1;
+				info.algo = FIPS_TEST_ALGO_TDES;
+				ret = parse_test_tdes_init();
+				if (ret < 0)
+					return 0;
+			} else if (strstr(info.vec[i], "VARIABLE")) {
+				algo_parsed = 1;
+				info.algo = FIPS_TEST_ALGO_TDES;
+				ret = parse_test_tdes_init();
+				if (ret < 0)
+					return 0;
+			} else if (strstr(info.vec[i], "SUBSTITUTION")) {
+				algo_parsed = 1;
+				info.algo = FIPS_TEST_ALGO_TDES;
+				ret = parse_test_tdes_init();
+				if (ret < 0)
+					return 0;
 			} else if (strstr(info.vec[i], "SHA-")) {
 				algo_parsed = 1;
 				info.algo = FIPS_TEST_ALGO_SHA;
@@ -257,7 +287,11 @@ fips_test_init(const char *req_file_path, const char *rsp_file_path,
 
 	fips_test_clear();
 
-	strcpy(info.file_name, req_file_path);
+	if (rte_strscpy(info.file_name, req_file_path,
+				sizeof(info.file_name)) < 0) {
+		RTE_LOG(ERR, USER1, "Path %s too long\n", req_file_path);
+		return -EINVAL;
+	}
 	info.algo = FIPS_TEST_ALGO_MAX;
 	if (parse_file_type(req_file_path) < 0) {
 		RTE_LOG(ERR, USER1, "File %s type not supported\n",
@@ -283,7 +317,11 @@ fips_test_init(const char *req_file_path, const char *rsp_file_path,
 		return -ENOMEM;
 	}
 
-	strlcpy(info.device_name, device_name, sizeof(info.device_name));
+	if (rte_strscpy(info.device_name, device_name,
+				sizeof(info.device_name)) < 0) {
+		RTE_LOG(ERR, USER1, "Device name %s too long\n", device_name);
+		return -EINVAL;
+	}
 
 	if (fips_test_parse_header() < 0) {
 		RTE_LOG(ERR, USER1, "Failed parsing header\n");
@@ -316,11 +354,15 @@ int
 fips_test_parse_one_case(void)
 {
 	uint32_t i, j = 0;
-	uint32_t is_interim = 0;
+	uint32_t is_interim;
+	uint32_t interim_cnt = 0;
 	int ret;
 
+	info.vec_start_off = 0;
+
 	if (info.interim_callbacks) {
 		for (i = 0; i < info.nb_vec_lines; i++) {
+			is_interim = 0;
 			for (j = 0; info.interim_callbacks[j].key != NULL; j++)
 				if (strstr(info.vec[i],
 					info.interim_callbacks[j].key)) {
@@ -333,17 +375,31 @@ fips_test_parse_one_case(void)
 					if (ret < 0)
 						return ret;
 				}
+
+			if (is_interim)
+				interim_cnt += 1;
 		}
 	}
 
-	if (is_interim) {
-		for (i = 0; i < info.nb_vec_lines; i++)
-			fprintf(info.fp_wr, "%s\n", info.vec[i]);
-		fprintf(info.fp_wr, "\n");
-		return 1;
+	if (interim_cnt) {
+		if (info.version == 21.4f) {
+			for (i = 0; i < interim_cnt; i++)
+				fprintf(info.fp_wr, "%s\n", info.vec[i]);
+			fprintf(info.fp_wr, "\n");
+
+			if (info.nb_vec_lines == interim_cnt)
+				return 1;
+		} else {
+			for (i = 0; i < info.nb_vec_lines; i++)
+				fprintf(info.fp_wr, "%s\n", info.vec[i]);
+			fprintf(info.fp_wr, "\n");
+			return 1;
+		}
 	}
 
-	for (i = 0; i < info.nb_vec_lines; i++) {
+	info.vec_start_off = interim_cnt;
+
+	for (i = info.vec_start_off; i < info.nb_vec_lines; i++) {
 		for (j = 0; info.callbacks[j].key != NULL; j++)
 			if (strstr(info.vec[i], info.callbacks[j].key)) {
 				ret = info.callbacks[j].cb(
@@ -363,7 +419,7 @@ fips_test_write_one_case(void)
 {
 	uint32_t i;
 
-	for (i = 0; i < info.nb_vec_lines; i++)
+	for (i = info.vec_start_off; i < info.nb_vec_lines; i++)
 		fprintf(info.fp_wr, "%s\n", info.vec[i]);
 }
 
@@ -607,9 +663,16 @@ update_info_vec(uint32_t count)
 
 	cb = &info.writeback_callbacks[0];
 
-	snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count);
+	if ((info.version == 21.4f) && (!(strstr(info.vec[0], cb->key)))) {
+		fprintf(info.fp_wr, "%s%u\n", cb->key, count);
+		i = 0;
+	} else {
+		snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key,
+				count);
+		i = 1;
+	}
 
-	for (i = 1; i < info.nb_vec_lines; i++) {
+	for (; i < info.nb_vec_lines; i++) {
 		for (j = 1; info.writeback_callbacks[j].key != NULL; j++) {
 			cb = &info.writeback_callbacks[j];
 			if (strstr(info.vec[i], cb->key)) {
diff --git a/dpdk/examples/fips_validation/fips_validation.h b/dpdk/examples/fips_validation/fips_validation.h
index d487fb0058..295624b1b5 100644
--- a/dpdk/examples/fips_validation/fips_validation.h
+++ b/dpdk/examples/fips_validation/fips_validation.h
@@ -14,6 +14,7 @@
 #define MAX_NB_TESTS		10240
 #define MAX_BUF_SIZE		2048
 #define MAX_STRING_SIZE		64
+#define MAX_FILE_NAME_SIZE	256
 #define MAX_DIGEST_SIZE		64
 
 #define POSITIVE_TEST		0
@@ -160,9 +161,11 @@ struct fips_test_interim_info {
 	enum fips_test_algorithms algo;
 	char *one_line_text;
 	char *vec[MAX_LINE_PER_VECTOR];
+	uint32_t vec_start_off;
 	uint32_t nb_vec_lines;
 	char device_name[MAX_STRING_SIZE];
-	char file_name[MAX_STRING_SIZE];
+	char file_name[MAX_FILE_NAME_SIZE];
+	float version;
 
 	union {
 		struct aesavs_interim_data aes_data;
diff --git a/dpdk/examples/fips_validation/fips_validation_gcm.c b/dpdk/examples/fips_validation/fips_validation_gcm.c
index ea48ddf707..47576e9a38 100644
--- a/dpdk/examples/fips_validation/fips_validation_gcm.c
+++ b/dpdk/examples/fips_validation/fips_validation_gcm.c
@@ -46,6 +46,10 @@ struct fips_test_callback gcm_interim_vectors[] = {
 		{KEYLEN_STR, parser_read_uint32_bit_val, &vec.aead.key},
 		{IVLEN_STR, parser_read_uint32_bit_val, &vec.iv},
 		{PTLEN_STR, parser_read_uint32_bit_val, &vec.pt},
+		{PTLEN_STR, parser_read_uint32_bit_val, &vec.ct},
+		/**< The NIST test vectors use 'PTlen' to denote input text
+		 *  length in case of decrypt & encrypt operations.
+		 */
 		{AADLEN_STR, parser_read_uint32_bit_val, &vec.aead.aad},
 		{TAGLEN_STR, parser_read_uint32_bit_val,
 				&vec.aead.digest},
diff --git a/dpdk/examples/fips_validation/fips_validation_tdes.c b/dpdk/examples/fips_validation/fips_validation_tdes.c
index 5b6737643a..f4c738c789 100644
--- a/dpdk/examples/fips_validation/fips_validation_tdes.c
+++ b/dpdk/examples/fips_validation/fips_validation_tdes.c
@@ -59,9 +59,7 @@ static int
 parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val);
 
 static int
-parse_tdes_interim(const char *key,
-		__attribute__((__unused__)) char *text,
-		struct fips_val *val);
+parse_tdes_interim(const char *key, char *text, struct fips_val *val);
 
 struct fips_test_callback tdes_tests_vectors[] = {
 		{KEYS_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key},
@@ -77,6 +75,7 @@ struct fips_test_callback tdes_tests_vectors[] = {
 struct fips_test_callback tdes_tests_interim_vectors[] = {
 		{ENC_STR, parse_tdes_interim, NULL},
 		{DEC_STR, parse_tdes_interim, NULL},
+		{NK_STR, parse_tdes_interim, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -94,21 +93,23 @@ struct fips_test_callback tdes_writeback_callbacks[] = {
 };
 
 static int
-parse_tdes_interim(const char *key,
-		__attribute__((__unused__)) char *text,
+parse_tdes_interim(const char *key, char *text,
 		__attribute__((__unused__)) struct fips_val *val)
 {
 	if (strstr(key, ENC_STR))
 		info.op = FIPS_TEST_ENC_AUTH_GEN;
 	else if (strstr(key, DEC_STR))
 		info.op = FIPS_TEST_DEC_AUTH_VERIF;
-	else if (strstr(NK_STR, "NumKeys = 1"))
-		info.interim_info.tdes_data.nb_keys = 1;
-	else if (strstr(NK_STR, "NumKeys = 2"))
-		info.interim_info.tdes_data.nb_keys = 2;
-	else if (strstr(NK_STR, "NumKeys = 3"))
-		info.interim_info.tdes_data.nb_keys = 3;
-	else
+	else if (strstr(key, NK_STR)) {
+		if (strcmp(text, "NumKeys = 1") == 0)
+			info.interim_info.tdes_data.nb_keys = 1;
+		else if (strcmp(text, "NumKeys = 2") == 0)
+			info.interim_info.tdes_data.nb_keys = 2;
+		else if (strcmp(text, "NumKeys = 3") == 0)
+			info.interim_info.tdes_data.nb_keys = 3;
+		else
+			return -EINVAL;
+	} else
 		return -EINVAL;
 
 	return 0;
diff --git a/dpdk/examples/fips_validation/main.c b/dpdk/examples/fips_validation/main.c
index 9a2c8da619..eadfdb4bac 100644
--- a/dpdk/examples/fips_validation/main.c
+++ b/dpdk/examples/fips_validation/main.c
@@ -1030,6 +1030,11 @@ fips_mct_tdes_test(void)
 	int test_mode = info.interim_info.tdes_data.test_mode;
 
 	for (i = 0; i < TDES_EXTERN_ITER; i++) {
+		if ((i == 0) && (info.version == 21.4f)) {
+			if (!(strstr(info.vec[0], "COUNT")))
+				fprintf(info.fp_wr, "%s%u\n", "COUNT = ", 0);
+		}
+
 		if (i != 0)
 			update_info_vec(i);
 
diff --git a/dpdk/examples/flow_classify/Makefile b/dpdk/examples/flow_classify/Makefile
index 6864941b3e..161d576b60 100644
--- a/dpdk/examples/flow_classify/Makefile
+++ b/dpdk/examples/flow_classify/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/flow_filtering/Makefile b/dpdk/examples/flow_filtering/Makefile
index 6c51c0b7a0..0ce20d3485 100644
--- a/dpdk/examples/flow_filtering/Makefile
+++ b/dpdk/examples/flow_filtering/Makefile
@@ -20,7 +20,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/helloworld/Makefile b/dpdk/examples/helloworld/Makefile
index 16d82b02f0..9a07f89efc 100644
--- a/dpdk/examples/helloworld/Makefile
+++ b/dpdk/examples/helloworld/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/ioat/Makefile b/dpdk/examples/ioat/Makefile
index ef63f5d689..dd4930136e 100644
--- a/dpdk/examples/ioat/Makefile
+++ b/dpdk/examples/ioat/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/ioat/ioatfwd.c b/dpdk/examples/ioat/ioatfwd.c
index e9117718fe..7971442b5d 100644
--- a/dpdk/examples/ioat/ioatfwd.c
+++ b/dpdk/examples/ioat/ioatfwd.c
@@ -168,7 +168,7 @@ print_stats(char *prgname)
 	struct rte_rawdev_xstats_name *names_xstats;
 	uint64_t *xstats;
 	unsigned int *ids_xstats, nb_xstats;
-	char status_string[120]; /* to print at the top of the output */
+	char status_string[255]; /* to print at the top of the output */
 	int status_strlen;
 	int ret;
 
@@ -194,7 +194,7 @@ print_stats(char *prgname)
 		"Rx Queues = %d, ", nb_queues);
 	status_strlen += snprintf(status_string + status_strlen,
 		sizeof(status_string) - status_strlen,
-		"Ring Size = %d\n", ring_size);
+		"Ring Size = %d", ring_size);
 
 	/* Allocate memory for xstats names and values */
 	ret = rte_rawdev_xstats_names_get(
@@ -251,7 +251,7 @@ print_stats(char *prgname)
 
 		memset(&delta_ts, 0, sizeof(struct total_statistics));
 
-		printf("%s", status_string);
+		printf("%s\n", status_string);
 
 		for (i = 0; i < cfg.nb_ports; i++) {
 			port_id = cfg.ports[i].rxtx_port;
@@ -294,6 +294,8 @@ print_stats(char *prgname)
 		printf("\n");
 		print_total_stats(&delta_ts);
 
+		fflush(stdout);
+
 		ts.total_packets_tx += delta_ts.total_packets_tx;
 		ts.total_packets_rx += delta_ts.total_packets_rx;
 		ts.total_packets_dropped += delta_ts.total_packets_dropped;
@@ -460,7 +462,7 @@ ioat_tx_port(struct rxtx_port_config *tx_config)
 				MAX_PKT_BURST, NULL);
 		}
 
-		if (nb_dq <= 0)
+		if ((int32_t) nb_dq <= 0)
 			return;
 
 		if (copy_mode == COPY_MODE_IOAT_NUM)
@@ -697,7 +699,7 @@ check_link_status(uint32_t port_mask)
 {
 	uint16_t portid;
 	struct rte_eth_link link;
-	int retval = 0;
+	int ret, link_status = 0;
 
 	printf("\nChecking link status\n");
 	RTE_ETH_FOREACH_DEV(portid) {
@@ -705,7 +707,12 @@ check_link_status(uint32_t port_mask)
 			continue;
 
 		memset(&link, 0, sizeof(link));
-		rte_eth_link_get(portid, &link);
+		ret = rte_eth_link_get(portid, &link);
+		if (ret < 0) {
+			printf("Port %u link get failed: err=%d\n",
+					portid, ret);
+			continue;
+		}
 
 		/* Print link status */
 		if (link.link_status) {
@@ -713,12 +720,12 @@ check_link_status(uint32_t port_mask)
 				"Port %d Link Up. Speed %u Mbps - %s\n",
 				portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-				("full-duplex") : ("half-duplex\n"));
-			retval = 1;
+				("full-duplex") : ("half-duplex"));
+			link_status = 1;
 		} else
 			printf("Port %d Link Down\n", portid);
 	}
-	return retval;
+	return link_status;
 }
 
 static void
@@ -824,7 +831,11 @@ port_init(uint16_t portid, struct rte_mempool *mbuf_pool, uint16_t nb_queues)
 	/* Init port */
 	printf("Initializing port %u... ", portid);
 	fflush(stdout);
-	rte_eth_dev_info_get(portid, &dev_info);
+	ret = rte_eth_dev_info_get(portid, &dev_info);
+	if (ret < 0)
+		rte_exit(EXIT_FAILURE, "Cannot get device info: %s, port=%u\n",
+			rte_strerror(-ret), portid);
+
 	local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
 		dev_info.flow_type_rss_offloads;
 	if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
diff --git a/dpdk/examples/ip_fragmentation/Makefile b/dpdk/examples/ip_fragmentation/Makefile
index ede0c4f02b..d200cc627d 100644
--- a/dpdk/examples/ip_fragmentation/Makefile
+++ b/dpdk/examples/ip_fragmentation/Makefile
@@ -23,7 +23,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/ip_fragmentation/main.c b/dpdk/examples/ip_fragmentation/main.c
index 104612339c..90e4d1ea4a 100644
--- a/dpdk/examples/ip_fragmentation/main.c
+++ b/dpdk/examples/ip_fragmentation/main.c
@@ -617,7 +617,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up .Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
@@ -646,7 +646,7 @@ check_all_ports_link_status(uint32_t port_mask)
 	}
 }
 
-/* Check L3 packet type detection capablity of the NIC port */
+/* Check L3 packet type detection capability of the NIC port */
 static int
 check_ptype(int portid)
 {
diff --git a/dpdk/examples/ip_pipeline/Makefile b/dpdk/examples/ip_pipeline/Makefile
index 3a0193818f..b8e086267b 100644
--- a/dpdk/examples/ip_pipeline/Makefile
+++ b/dpdk/examples/ip_pipeline/Makefile
@@ -35,9 +35,9 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
-CFLAGS += -I.
+CFLAGS += -I. -DALLOW_EXPERIMENTAL_API -D_GNU_SOURCE
 
 OBJS := $(patsubst %.c,build/%.o,$(SRCS-y))
 
diff --git a/dpdk/examples/ip_pipeline/parser.c b/dpdk/examples/ip_pipeline/parser.c
index 3fffeb5867..f043d6bf4f 100644
--- a/dpdk/examples/ip_pipeline/parser.c
+++ b/dpdk/examples/ip_pipeline/parser.c
@@ -4,25 +4,6 @@
  * All rights reserved.
  */
 
-/*
- * For inet_pton4() and inet_pton6() functions:
- *
- * Copyright (c) 1996 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -34,6 +15,8 @@
 #include <libgen.h>
 #include <unistd.h>
 #include <sys/wait.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
 
 #include <rte_errno.h>
 #include <rte_string_fns.h>
@@ -348,171 +331,6 @@ parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
 	return 0;
 }
 
-#define INADDRSZ 4
-#define IN6ADDRSZ 16
-
-/* int
- * inet_pton4(src, dst)
- *      like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- *      1 if `src' is a valid dotted quad, else 0.
- * notice:
- *      does not touch `dst' unless it's returning 1.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton4(const char *src, unsigned char *dst)
-{
-	static const char digits[] = "0123456789";
-	int saw_digit, octets, ch;
-	unsigned char tmp[INADDRSZ], *tp;
-
-	saw_digit = 0;
-	octets = 0;
-	*(tp = tmp) = 0;
-	while ((ch = *src++) != '\0') {
-		const char *pch;
-
-		pch = strchr(digits, ch);
-		if (pch != NULL) {
-			unsigned int new = *tp * 10 + (pch - digits);
-
-			if (new > 255)
-				return 0;
-			if (!saw_digit) {
-				if (++octets > 4)
-					return 0;
-				saw_digit = 1;
-			}
-			*tp = (unsigned char)new;
-		} else if (ch == '.' && saw_digit) {
-			if (octets == 4)
-				return 0;
-			*++tp = 0;
-			saw_digit = 0;
-		} else
-			return 0;
-	}
-	if (octets < 4)
-		return 0;
-
-	memcpy(dst, tmp, INADDRSZ);
-	return 1;
-}
-
-/* int
- * inet_pton6(src, dst)
- *      convert presentation level address to network order binary form.
- * return:
- *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- *      (1) does not touch `dst' unless it's returning 1.
- *      (2) :: in a full address is silently ignored.
- * credit:
- *      inspired by Mark Andrews.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton6(const char *src, unsigned char *dst)
-{
-	static const char xdigits_l[] = "0123456789abcdef",
-		xdigits_u[] = "0123456789ABCDEF";
-	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
-	const char *xdigits = 0, *curtok = 0;
-	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
-	unsigned int val = 0;
-	unsigned dbloct_count = 0;
-
-	memset((tp = tmp), '\0', IN6ADDRSZ);
-	endp = tp + IN6ADDRSZ;
-	colonp = NULL;
-	/* Leading :: requires some special handling. */
-	if (*src == ':')
-		if (*++src != ':')
-			return 0;
-	curtok = src;
-	saw_xdigit = count_xdigit = 0;
-	val = 0;
-
-	while ((ch = *src++) != '\0') {
-		const char *pch;
-
-		pch = strchr((xdigits = xdigits_l), ch);
-		if (pch == NULL)
-			pch = strchr((xdigits = xdigits_u), ch);
-		if (pch != NULL) {
-			if (count_xdigit >= 4)
-				return 0;
-			val <<= 4;
-			val |= (pch - xdigits);
-			if (val > 0xffff)
-				return 0;
-			saw_xdigit = 1;
-			count_xdigit++;
-			continue;
-		}
-		if (ch == ':') {
-			curtok = src;
-			if (!saw_xdigit) {
-				if (colonp)
-					return 0;
-				colonp = tp;
-				continue;
-			} else if (*src == '\0') {
-				return 0;
-			}
-			if (tp + sizeof(int16_t) > endp)
-				return 0;
-			*tp++ = (unsigned char) ((val >> 8) & 0xff);
-			*tp++ = (unsigned char) (val & 0xff);
-			saw_xdigit = 0;
-			count_xdigit = 0;
-			val = 0;
-			dbloct_count++;
-			continue;
-		}
-		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
-		    inet_pton4(curtok, tp) > 0) {
-			tp += INADDRSZ;
-			saw_xdigit = 0;
-			dbloct_count += 2;
-			break;  /* '\0' was seen by inet_pton4(). */
-		}
-		return 0;
-	}
-	if (saw_xdigit) {
-		if (tp + sizeof(int16_t) > endp)
-			return 0;
-		*tp++ = (unsigned char) ((val >> 8) & 0xff);
-		*tp++ = (unsigned char) (val & 0xff);
-		dbloct_count++;
-	}
-	if (colonp != NULL) {
-		/* if we already have 8 double octets, having a colon means error */
-		if (dbloct_count == 8)
-			return 0;
-
-		/*
-		 * Since some memmove()'s erroneously fail to handle
-		 * overlapping regions, we'll do the shift by hand.
-		 */
-		const int n = tp - colonp;
-		int i;
-
-		for (i = 1; i <= n; i++) {
-			endp[-i] = colonp[n - i];
-			colonp[n - i] = 0;
-		}
-		tp = endp;
-	}
-	if (tp != endp)
-		return 0;
-	memcpy(dst, tmp, IN6ADDRSZ);
-	return 1;
-}
-
 static struct rte_ether_addr *
 my_ether_aton(const char *a)
 {
@@ -562,7 +380,7 @@ parse_ipv4_addr(const char *token, struct in_addr *ipv4)
 	if (strlen(token) >= INET_ADDRSTRLEN)
 		return -EINVAL;
 
-	if (inet_pton4(token, (unsigned char *)ipv4) != 1)
+	if (inet_pton(AF_INET, token, ipv4) != 1)
 		return -EINVAL;
 
 	return 0;
@@ -574,7 +392,7 @@ parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
 	if (strlen(token) >= INET6_ADDRSTRLEN)
 		return -EINVAL;
 
-	if (inet_pton6(token, (unsigned char *)ipv6) != 1)
+	if (inet_pton(AF_INET6, token, ipv6) != 1)
 		return -EINVAL;
 
 	return 0;
diff --git a/dpdk/examples/ip_pipeline/thread.c b/dpdk/examples/ip_pipeline/thread.c
index 272fbbeed1..adb83167cd 100644
--- a/dpdk/examples/ip_pipeline/thread.c
+++ b/dpdk/examples/ip_pipeline/thread.c
@@ -325,8 +325,6 @@ thread_pipeline_enable(uint32_t thread_id,
 
 	/* Send request and wait for response */
 	rsp = thread_msg_send_recv(thread_id, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -412,8 +410,6 @@ thread_pipeline_disable(uint32_t thread_id,
 
 	/* Send request and wait for response */
 	rsp = thread_msg_send_recv(thread_id, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -815,8 +811,6 @@ pipeline_port_in_stats_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -863,8 +857,6 @@ pipeline_port_in_enable(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -909,8 +901,6 @@ pipeline_port_in_disable(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -963,8 +953,6 @@ pipeline_port_out_stats_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1019,8 +1007,6 @@ pipeline_table_stats_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1436,10 +1422,6 @@ pipeline_table_rule_add(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL) {
-		free(rule);
-		return -1;
-	}
 
 	/* Read response */
 	status = rsp->status;
@@ -1538,10 +1520,6 @@ pipeline_table_rule_add_default(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL) {
-		free(rule);
-		return -1;
-	}
 
 	/* Read response */
 	status = rsp->status;
@@ -1655,10 +1633,6 @@ pipeline_table_rule_add_bulk(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL) {
-		table_rule_list_free(list);
-		return -ENOMEM;
-	}
 
 	/* Read response */
 	status = rsp->status;
@@ -1733,8 +1707,6 @@ pipeline_table_rule_delete(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1790,8 +1762,6 @@ pipeline_table_rule_delete_default(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1857,8 +1827,6 @@ pipeline_table_rule_stats_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1915,8 +1883,6 @@ pipeline_table_mtr_profile_add(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -1967,8 +1933,6 @@ pipeline_table_mtr_profile_delete(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -2037,8 +2001,6 @@ pipeline_table_rule_mtr_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -2096,8 +2058,6 @@ pipeline_table_dscp_table_update(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -2164,8 +2124,6 @@ pipeline_table_rule_ttl_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
@@ -2229,8 +2187,6 @@ pipeline_table_rule_time_read(const char *pipeline_name,
 
 	/* Send request and wait for response */
 	rsp = pipeline_msg_send_recv(p, req);
-	if (rsp == NULL)
-		return -1;
 
 	/* Read response */
 	status = rsp->status;
diff --git a/dpdk/examples/ip_reassembly/Makefile b/dpdk/examples/ip_reassembly/Makefile
index 3f2888b338..c7424da2b7 100644
--- a/dpdk/examples/ip_reassembly/Makefile
+++ b/dpdk/examples/ip_reassembly/Makefile
@@ -23,7 +23,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/ip_reassembly/main.c b/dpdk/examples/ip_reassembly/main.c
index d59e6d02ff..29b34d0710 100644
--- a/dpdk/examples/ip_reassembly/main.c
+++ b/dpdk/examples/ip_reassembly/main.c
@@ -736,7 +736,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/ipsec-secgw/Makefile b/dpdk/examples/ipsec-secgw/Makefile
index a4977f61f8..38c456daa2 100644
--- a/dpdk/examples/ipsec-secgw/Makefile
+++ b/dpdk/examples/ipsec-secgw/Makefile
@@ -33,7 +33,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/ipsec-secgw/ipsec-secgw.c b/dpdk/examples/ipsec-secgw/ipsec-secgw.c
index 3b5aaf6832..1493be9025 100644
--- a/dpdk/examples/ipsec-secgw/ipsec-secgw.c
+++ b/dpdk/examples/ipsec-secgw/ipsec-secgw.c
@@ -1668,7 +1668,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up - speed %u Mbps -%s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/ipsec-secgw/ipsec_process.c b/dpdk/examples/ipsec-secgw/ipsec_process.c
index 2eb5c8b345..37f406d46c 100644
--- a/dpdk/examples/ipsec-secgw/ipsec_process.c
+++ b/dpdk/examples/ipsec-secgw/ipsec_process.c
@@ -125,6 +125,7 @@ sa_group(void *sa_ptr[], struct rte_mbuf *pkts[],
 	void * const nosa = &spi;
 
 	sa = nosa;
+	grp[0].m = pkts;
 	for (i = 0, n = 0; i != num; i++) {
 
 		if (sa != sa_ptr[i]) {
diff --git a/dpdk/examples/ipsec-secgw/parser.c b/dpdk/examples/ipsec-secgw/parser.c
index fc8c238fe5..dfabac2dbf 100644
--- a/dpdk/examples/ipsec-secgw/parser.c
+++ b/dpdk/examples/ipsec-secgw/parser.c
@@ -1,6 +1,9 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2016 Intel Corporation
  */
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
 #include <rte_common.h>
 #include <rte_crypto.h>
 #include <rte_string_fns.h>
@@ -39,172 +42,6 @@ parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
 	return 0;
 }
 
-#define INADDRSZ 4
-#define IN6ADDRSZ 16
-
-/* int
- * inet_pton4(src, dst)
- *      like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- *      1 if `src' is a valid dotted quad, else 0.
- * notice:
- *      does not touch `dst' unless it's returning 1.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton4(const char *src, unsigned char *dst)
-{
-	static const char digits[] = "0123456789";
-	int saw_digit, octets, ch;
-	unsigned char tmp[INADDRSZ], *tp;
-
-	saw_digit = 0;
-	octets = 0;
-	*(tp = tmp) = 0;
-	while ((ch = *src++) != '\0') {
-		const char *pch;
-
-		pch = strchr(digits, ch);
-		if (pch != NULL) {
-			unsigned int new = *tp * 10 + (pch - digits);
-
-			if (new > 255)
-				return 0;
-			if (!saw_digit) {
-				if (++octets > 4)
-					return 0;
-				saw_digit = 1;
-			}
-			*tp = (unsigned char)new;
-		} else if (ch == '.' && saw_digit) {
-			if (octets == 4)
-				return 0;
-			*++tp = 0;
-			saw_digit = 0;
-		} else
-			return 0;
-	}
-	if (octets < 4)
-		return 0;
-
-	memcpy(dst, tmp, INADDRSZ);
-	return 1;
-}
-
-/* int
- * inet_pton6(src, dst)
- *      convert presentation level address to network order binary form.
- * return:
- *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- *      (1) does not touch `dst' unless it's returning 1.
- *      (2) :: in a full address is silently ignored.
- * credit:
- *      inspired by Mark Andrews.
- * author:
- *      Paul Vixie, 1996.
- */
-static int
-inet_pton6(const char *src, unsigned char *dst)
-{
-	static const char xdigits_l[] = "0123456789abcdef",
-		xdigits_u[] = "0123456789ABCDEF";
-	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
-	const char *xdigits = 0, *curtok = 0;
-	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
-	unsigned int val = 0;
-	unsigned dbloct_count = 0;
-
-	memset((tp = tmp), '\0', IN6ADDRSZ);
-	endp = tp + IN6ADDRSZ;
-	colonp = NULL;
-	/* Leading :: requires some special handling. */
-	if (*src == ':')
-		if (*++src != ':')
-			return 0;
-	curtok = src;
-	saw_xdigit = count_xdigit = 0;
-	val = 0;
-
-	while ((ch = *src++) != '\0') {
-		const char *pch;
-
-		pch = strchr((xdigits = xdigits_l), ch);
-		if (pch == NULL)
-			pch = strchr((xdigits = xdigits_u), ch);
-		if (pch != NULL) {
-			if (count_xdigit >= 4)
-				return 0;
-			val <<= 4;
-			val |= (pch - xdigits);
-			if (val > 0xffff)
-				return 0;
-			saw_xdigit = 1;
-			count_xdigit++;
-			continue;
-		}
-		if (ch == ':') {
-			curtok = src;
-			if (!saw_xdigit) {
-				if (colonp)
-					return 0;
-				colonp = tp;
-				continue;
-			} else if (*src == '\0') {
-				return 0;
-			}
-			if (tp + sizeof(int16_t) > endp)
-				return 0;
-			*tp++ = (unsigned char) ((val >> 8) & 0xff);
-			*tp++ = (unsigned char) (val & 0xff);
-			saw_xdigit = 0;
-			count_xdigit = 0;
-			val = 0;
-			dbloct_count++;
-			continue;
-		}
-		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
-		    inet_pton4(curtok, tp) > 0) {
-			tp += INADDRSZ;
-			saw_xdigit = 0;
-			dbloct_count += 2;
-			break;  /* '\0' was seen by inet_pton4(). */
-		}
-		return 0;
-	}
-	if (saw_xdigit) {
-		if (tp + sizeof(int16_t) > endp)
-			return 0;
-		*tp++ = (unsigned char) ((val >> 8) & 0xff);
-		*tp++ = (unsigned char) (val & 0xff);
-		dbloct_count++;
-	}
-	if (colonp != NULL) {
-		/* if we already have 8 double octets, having a colon
-		 * means error */
-		if (dbloct_count == 8)
-			return 0;
-
-		/*
-		 * Since some memmove()'s erroneously fail to handle
-		 * overlapping regions, we'll do the shift by hand.
-		 */
-		const int n = tp - colonp;
-		int i;
-
-		for (i = 1; i <= n; i++) {
-			endp[-i] = colonp[n - i];
-			colonp[n - i] = 0;
-		}
-		tp = endp;
-	}
-	if (tp != endp)
-		return 0;
-	memcpy(dst, tmp, IN6ADDRSZ);
-	return 1;
-}
-
 int
 parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
 {
@@ -229,7 +66,7 @@ parse_ipv4_addr(const char *token, struct in_addr *ipv4, uint32_t *mask)
 	if (strlen(ip_str) >= INET_ADDRSTRLEN)
 		return -EINVAL;
 
-	if (inet_pton4(ip_str, (unsigned char *)ipv4) != 1)
+	if (inet_pton(AF_INET, ip_str, ipv4) != 1)
 		return -EINVAL;
 
 	return 0;
@@ -260,7 +97,7 @@ parse_ipv6_addr(const char *token, struct in6_addr *ipv6, uint32_t *mask)
 	if (strlen(ip_str) >= INET6_ADDRSTRLEN)
 		return -EINVAL;
 
-	if (inet_pton6(ip_str, (unsigned char *)ipv6) != 1)
+	if (inet_pton(AF_INET6, ip_str, ipv6) != 1)
 		return -EINVAL;
 
 	return 0;
diff --git a/dpdk/examples/ipsec-secgw/sa.c b/dpdk/examples/ipsec-secgw/sa.c
index 7f046e3ed7..fcc6695388 100644
--- a/dpdk/examples/ipsec-secgw/sa.c
+++ b/dpdk/examples/ipsec-secgw/sa.c
@@ -314,6 +314,9 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			APP_CHECK(algo != NULL, status, "unrecognized "
 				"input \"%s\"", tokens[ti]);
 
+			if (status->status < 0)
+				return;
+
 			rule->cipher_algo = algo->algo;
 			rule->block_size = algo->block_size;
 			rule->iv_len = algo->iv_len;
@@ -378,6 +381,9 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			APP_CHECK(algo != NULL, status, "unrecognized "
 				"input \"%s\"", tokens[ti]);
 
+			if (status->status < 0)
+				return;
+
 			rule->auth_algo = algo->algo;
 			rule->auth_key_len = algo->key_len;
 			rule->digest_len = algo->digest_len;
@@ -433,6 +439,9 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
 			APP_CHECK(algo != NULL, status, "unrecognized "
 				"input \"%s\"", tokens[ti]);
 
+			if (status->status < 0)
+				return;
+
 			rule->aead_algo = algo->algo;
 			rule->cipher_key_len = algo->key_len;
 			rule->digest_len = algo->digest_len;
@@ -984,7 +993,6 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 		}
 
 		if (sa->aead_algo == RTE_CRYPTO_AEAD_AES_GCM) {
-			struct rte_ipsec_session *ips;
 			iv_length = 12;
 
 			sa_ctx->xf[idx].a.type = RTE_CRYPTO_SYM_XFORM_AEAD;
@@ -1004,20 +1012,6 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 				sa->digest_len;
 
 			sa->xforms = &sa_ctx->xf[idx].a;
-
-			ips = ipsec_get_primary_session(sa);
-			if (ips->type ==
-				RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
-				ips->type ==
-				RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
-				rc = create_inline_session(skt_ctx, sa, ips);
-				if (rc != 0) {
-					RTE_LOG(ERR, IPSEC_ESP,
-						"create_inline_session() failed\n");
-					return -EINVAL;
-				}
-			}
-			print_one_sa_rule(sa, inbound);
 		} else {
 			switch (sa->cipher_algo) {
 			case RTE_CRYPTO_CIPHER_NULL:
@@ -1082,9 +1076,21 @@ sa_add_rules(struct sa_ctx *sa_ctx, const struct ipsec_sa entries[],
 			sa_ctx->xf[idx].a.next = &sa_ctx->xf[idx].b;
 			sa_ctx->xf[idx].b.next = NULL;
 			sa->xforms = &sa_ctx->xf[idx].a;
+		}
 
-			print_one_sa_rule(sa, inbound);
+		if (ips->type ==
+			RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL ||
+			ips->type ==
+			RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO) {
+			rc = create_inline_session(skt_ctx, sa, ips);
+			if (rc != 0) {
+				RTE_LOG(ERR, IPSEC_ESP,
+					"create_inline_session() failed\n");
+				return -EINVAL;
+			}
 		}
+
+		print_one_sa_rule(sa, inbound);
 	}
 
 	return 0;
diff --git a/dpdk/examples/ipv4_multicast/Makefile b/dpdk/examples/ipv4_multicast/Makefile
index 92d3db0f4d..5e34bbba00 100644
--- a/dpdk/examples/ipv4_multicast/Makefile
+++ b/dpdk/examples/ipv4_multicast/Makefile
@@ -23,7 +23,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/ipv4_multicast/main.c b/dpdk/examples/ipv4_multicast/main.c
index 63333b5b69..09d9270aff 100644
--- a/dpdk/examples/ipv4_multicast/main.c
+++ b/dpdk/examples/ipv4_multicast/main.c
@@ -600,7 +600,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 					portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/kni/Makefile b/dpdk/examples/kni/Makefile
index c7ca96d8a0..10b42891da 100644
--- a/dpdk/examples/kni/Makefile
+++ b/dpdk/examples/kni/Makefile
@@ -23,7 +23,9 @@ PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
+
+LDFLAGS += -pthread
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/kni/main.c b/dpdk/examples/kni/main.c
index 5f713e6b22..7edc73ab91 100644
--- a/dpdk/examples/kni/main.c
+++ b/dpdk/examples/kni/main.c
@@ -158,6 +158,8 @@ print_stats(void)
 						kni_stats[i].tx_dropped);
 	}
 	printf("======  ==============  ============  ============  ============  ============\n");
+
+	fflush(stdout);
 }
 
 /* Custom handling of signals to handle stats and kni processing */
@@ -679,7 +681,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up - speed %uMbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
@@ -764,15 +766,16 @@ monitor_all_ports_link_status(void *arg)
 	return NULL;
 }
 
-/* Callback for request of changing MTU */
 static int
-kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
+kni_change_mtu_(uint16_t port_id, unsigned int new_mtu)
 {
 	int ret;
 	uint16_t nb_rxd = NB_RXD;
+	uint16_t nb_txd = NB_TXD;
 	struct rte_eth_conf conf;
 	struct rte_eth_dev_info dev_info;
 	struct rte_eth_rxconf rxq_conf;
+	struct rte_eth_txconf txq_conf;
 
 	if (!rte_eth_dev_is_valid_port(port_id)) {
 		RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id);
@@ -800,7 +803,7 @@ kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
 		return ret;
 	}
 
-	ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, NULL);
+	ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, &nb_txd);
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors "
 				"for port%u (%d)\n", (unsigned int)port_id,
@@ -825,6 +828,16 @@ kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
 		return ret;
 	}
 
+	txq_conf = dev_info.default_txconf;
+	txq_conf.offloads = conf.txmode.offloads;
+	ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd,
+		rte_eth_dev_socket_id(port_id), &txq_conf);
+	if (ret < 0) {
+		RTE_LOG(ERR, APP, "Fail to setup Tx queue of port %d\n",
+				port_id);
+		return ret;
+	}
+
 	/* Restart specific port */
 	ret = rte_eth_dev_start(port_id);
 	if (ret < 0) {
@@ -835,6 +848,19 @@ kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
 	return 0;
 }
 
+/* Callback for request of changing MTU */
+static int
+kni_change_mtu(uint16_t port_id, unsigned int new_mtu)
+{
+	int ret;
+
+	rte_atomic32_inc(&kni_pause);
+	ret =  kni_change_mtu_(port_id, new_mtu);
+	rte_atomic32_dec(&kni_pause);
+
+	return ret;
+}
+
 /* Callback for request of configuring network interface up/down */
 static int
 kni_config_network_interface(uint16_t port_id, uint8_t if_up)
diff --git a/dpdk/examples/l2fwd-cat/Makefile b/dpdk/examples/l2fwd-cat/Makefile
index b0e53c37e8..e8fdc46d74 100644
--- a/dpdk/examples/l2fwd-cat/Makefile
+++ b/dpdk/examples/l2fwd-cat/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 LDFLAGS += -lpqos
 
diff --git a/dpdk/examples/l2fwd-crypto/Makefile b/dpdk/examples/l2fwd-crypto/Makefile
index 2f1405a72b..cafe778fc6 100644
--- a/dpdk/examples/l2fwd-crypto/Makefile
+++ b/dpdk/examples/l2fwd-crypto/Makefile
@@ -22,7 +22,13 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CONFIG_DEFINES = $(shell $(CC) $(CFLAGS) -dM -E - < /dev/null)
+ifneq ($(findstring RTE_CRYPTO_SCHEDULER,$(CONFIG_DEFINES)),)
+LDFLAGS_SHARED += -lrte_crypto_scheduler
+endif
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l2fwd-crypto/main.c b/dpdk/examples/l2fwd-crypto/main.c
index 61d78295d4..827da9b3e3 100644
--- a/dpdk/examples/l2fwd-crypto/main.c
+++ b/dpdk/examples/l2fwd-crypto/main.c
@@ -334,6 +334,8 @@ print_stats(void)
 		   total_packets_dropped,
 		   total_packets_errors);
 	printf("\n====================================================\n");
+
+	fflush(stdout);
 }
 
 static int
@@ -1756,7 +1758,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/l2fwd-crypto/meson.build b/dpdk/examples/l2fwd-crypto/meson.build
index 6c852ad199..c08d8469b4 100644
--- a/dpdk/examples/l2fwd-crypto/meson.build
+++ b/dpdk/examples/l2fwd-crypto/meson.build
@@ -7,6 +7,9 @@
 # DPDK instance, use 'make'
 
 deps += 'cryptodev'
+if dpdk_conf.has('RTE_LIBRTE_CRYPTO_SCHEDULER_PMD')
+	deps += 'pmd_crypto_scheduler'
+endif
 allow_experimental_apis = true
 sources = files(
 	'main.c'
diff --git a/dpdk/examples/l2fwd-event/Makefile b/dpdk/examples/l2fwd-event/Makefile
index 4cdae36f17..bf0ee890d5 100644
--- a/dpdk/examples/l2fwd-event/Makefile
+++ b/dpdk/examples/l2fwd-event/Makefile
@@ -28,7 +28,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l2fwd-event/l2fwd_common.c b/dpdk/examples/l2fwd-event/l2fwd_common.c
index 181301fe6b..ab341e55b2 100644
--- a/dpdk/examples/l2fwd-event/l2fwd_common.c
+++ b/dpdk/examples/l2fwd-event/l2fwd_common.c
@@ -50,6 +50,17 @@ l2fwd_event_init_ports(struct l2fwd_resources *rsrc)
 		if (ret != 0)
 			rte_panic("Error during getting device (port %u) info: %s\n",
 				  port_id, strerror(-ret));
+		local_port_conf.rx_adv_conf.rss_conf.rss_hf &=
+			dev_info.flow_type_rss_offloads;
+		if (local_port_conf.rx_adv_conf.rss_conf.rss_hf !=
+				port_conf.rx_adv_conf.rss_conf.rss_hf) {
+			printf("Port %u modified RSS hash function based on hardware support,"
+			       "requested:%#"PRIx64" configured:%#"PRIx64"",
+				port_id,
+				port_conf.rx_adv_conf.rss_conf.rss_hf,
+				local_port_conf.rx_adv_conf.rss_conf.rss_hf);
+		}
+
 		if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
 			local_port_conf.txmode.offloads |=
 				DEV_TX_OFFLOAD_MBUF_FAST_FREE;
diff --git a/dpdk/examples/l2fwd-event/l2fwd_event.c b/dpdk/examples/l2fwd-event/l2fwd_event.c
index 0379c580d6..38d590c14c 100644
--- a/dpdk/examples/l2fwd-event/l2fwd_event.c
+++ b/dpdk/examples/l2fwd-event/l2fwd_event.c
@@ -67,7 +67,7 @@ l2fwd_event_service_setup(struct l2fwd_resources *rsrc)
 	int ret, i;
 
 	rte_event_dev_info_get(evt_rsrc->event_d_id, &evdev_info);
-	if (evdev_info.event_dev_cap  & RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED) {
+	if (!(evdev_info.event_dev_cap & RTE_EVENT_DEV_CAP_DISTRIBUTED_SCHED)) {
 		ret = rte_event_dev_service_id_get(evt_rsrc->event_d_id,
 				&service_id);
 		if (ret != -ESRCH && ret != 0)
diff --git a/dpdk/examples/l2fwd-event/l2fwd_event_generic.c b/dpdk/examples/l2fwd-event/l2fwd_event_generic.c
index b7e467c1e1..2dc95e5f7d 100644
--- a/dpdk/examples/l2fwd-event/l2fwd_event_generic.c
+++ b/dpdk/examples/l2fwd-event/l2fwd_event_generic.c
@@ -42,8 +42,10 @@ l2fwd_event_device_setup_generic(struct l2fwd_resources *rsrc)
 
 	/* Event device configurtion */
 	rte_event_dev_info_get(event_d_id, &dev_info);
-	evt_rsrc->disable_implicit_release = !!(dev_info.event_dev_cap &
-				    RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE);
+
+	/* Enable implicit release */
+	if (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE)
+		evt_rsrc->disable_implicit_release = 0;
 
 	if (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES)
 		event_queue_cfg |= RTE_EVENT_QUEUE_CFG_ALL_TYPES;
@@ -70,7 +72,8 @@ l2fwd_event_device_setup_generic(struct l2fwd_resources *rsrc)
 		event_d_conf.nb_event_port_enqueue_depth =
 				dev_info.max_event_port_enqueue_depth;
 
-	num_workers = rte_lcore_count() - rte_service_lcore_count();
+	/* Ignore Master core and service cores. */
+	num_workers = rte_lcore_count() - 1 - rte_service_lcore_count();
 	if (dev_info.max_event_ports < num_workers)
 		num_workers = dev_info.max_event_ports;
 
@@ -109,7 +112,9 @@ l2fwd_event_port_setup_generic(struct l2fwd_resources *rsrc)
 		rte_panic("No space is available\n");
 
 	memset(&def_p_conf, 0, sizeof(struct rte_event_port_conf));
-	rte_event_port_default_conf_get(event_d_id, 0, &def_p_conf);
+	ret = rte_event_port_default_conf_get(event_d_id, 0, &def_p_conf);
+	if (ret < 0)
+		rte_panic("Error to get default configuration of event port\n");
 
 	if (def_p_conf.new_event_threshold < event_p_conf.new_event_threshold)
 		event_p_conf.new_event_threshold =
@@ -170,7 +175,10 @@ l2fwd_event_queue_setup_generic(struct l2fwd_resources *rsrc,
 	if (!evt_rsrc->evq.event_q_id)
 		rte_panic("Memory allocation failure\n");
 
-	rte_event_queue_default_conf_get(event_d_id, 0, &def_q_conf);
+	ret = rte_event_queue_default_conf_get(event_d_id, 0, &def_q_conf);
+	if (ret < 0)
+		rte_panic("Error to get default config of event queue\n");
+
 	if (def_q_conf.nb_atomic_flows < event_q_conf.nb_atomic_flows)
 		event_q_conf.nb_atomic_flows = def_q_conf.nb_atomic_flows;
 
diff --git a/dpdk/examples/l2fwd-event/l2fwd_event_internal_port.c b/dpdk/examples/l2fwd-event/l2fwd_event_internal_port.c
index b382763dd9..63d57b46c2 100644
--- a/dpdk/examples/l2fwd-event/l2fwd_event_internal_port.c
+++ b/dpdk/examples/l2fwd-event/l2fwd_event_internal_port.c
@@ -27,7 +27,6 @@ l2fwd_event_device_setup_internal_port(struct l2fwd_resources *rsrc)
 		.nb_event_port_enqueue_depth = 128
 	};
 	struct rte_event_dev_info dev_info;
-	uint8_t disable_implicit_release;
 	const uint8_t event_d_id = 0; /* Always use first event device only */
 	uint32_t event_queue_cfg = 0;
 	uint16_t ethdev_count = 0;
@@ -44,10 +43,9 @@ l2fwd_event_device_setup_internal_port(struct l2fwd_resources *rsrc)
 	/* Event device configurtion */
 	rte_event_dev_info_get(event_d_id, &dev_info);
 
-	disable_implicit_release = !!(dev_info.event_dev_cap &
-				    RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE);
-	evt_rsrc->disable_implicit_release =
-						disable_implicit_release;
+	/* Enable implicit release */
+	if (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE)
+		evt_rsrc->disable_implicit_release = 0;
 
 	if (dev_info.event_dev_cap & RTE_EVENT_DEV_CAP_QUEUE_ALL_TYPES)
 		event_queue_cfg |= RTE_EVENT_QUEUE_CFG_ALL_TYPES;
@@ -73,7 +71,8 @@ l2fwd_event_device_setup_internal_port(struct l2fwd_resources *rsrc)
 		event_d_conf.nb_event_port_enqueue_depth =
 				dev_info.max_event_port_enqueue_depth;
 
-	num_workers = rte_lcore_count();
+	/* Ignore Master core. */
+	num_workers = rte_lcore_count() - 1;
 	if (dev_info.max_event_ports < num_workers)
 		num_workers = dev_info.max_event_ports;
 
@@ -110,7 +109,10 @@ l2fwd_event_port_setup_internal_port(struct l2fwd_resources *rsrc)
 	if (!evt_rsrc->evp.event_p_id)
 		rte_panic("Failed to allocate memory for Event Ports\n");
 
-	rte_event_port_default_conf_get(event_d_id, 0, &def_p_conf);
+	ret = rte_event_port_default_conf_get(event_d_id, 0, &def_p_conf);
+	if (ret < 0)
+		rte_panic("Error to get default configuration of event port\n");
+
 	if (def_p_conf.new_event_threshold < event_p_conf.new_event_threshold)
 		event_p_conf.new_event_threshold =
 						def_p_conf.new_event_threshold;
@@ -162,7 +164,10 @@ l2fwd_event_queue_setup_internal_port(struct l2fwd_resources *rsrc,
 	uint8_t event_q_id = 0;
 	int32_t ret;
 
-	rte_event_queue_default_conf_get(event_d_id, event_q_id, &def_q_conf);
+	ret = rte_event_queue_default_conf_get(event_d_id, event_q_id,
+					       &def_q_conf);
+	if (ret < 0)
+		rte_panic("Error to get default config of event queue\n");
 
 	if (def_q_conf.nb_atomic_flows < event_q_conf.nb_atomic_flows)
 		event_q_conf.nb_atomic_flows = def_q_conf.nb_atomic_flows;
diff --git a/dpdk/examples/l2fwd-event/l2fwd_poll.c b/dpdk/examples/l2fwd-event/l2fwd_poll.c
index a3a3835582..2033c65e54 100644
--- a/dpdk/examples/l2fwd-event/l2fwd_poll.c
+++ b/dpdk/examples/l2fwd-event/l2fwd_poll.c
@@ -116,6 +116,7 @@ l2fwd_poll_lcore_config(struct l2fwd_resources *rsrc)
 
 		/* get the lcore_id for this port */
 		while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
+		       rx_lcore_id == rte_get_master_lcore() ||
 		       poll_rsrc->lcore_queue_conf[rx_lcore_id].n_rx_port ==
 		       rsrc->rx_queue_per_lcore) {
 			rx_lcore_id++;
diff --git a/dpdk/examples/l2fwd-event/main.c b/dpdk/examples/l2fwd-event/main.c
index 89a6bb9a44..7969a1c313 100644
--- a/dpdk/examples/l2fwd-event/main.c
+++ b/dpdk/examples/l2fwd-event/main.c
@@ -263,7 +263,7 @@ check_all_ports_link_status(struct l2fwd_resources *rsrc,
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						port_id, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", port_id);
 				continue;
@@ -385,6 +385,8 @@ print_stats(struct l2fwd_resources *rsrc)
 		   total_packets_rx,
 		   total_packets_dropped);
 	printf("\n====================================================\n");
+
+	fflush(stdout);
 }
 
 static void
diff --git a/dpdk/examples/l2fwd-jobstats/Makefile b/dpdk/examples/l2fwd-jobstats/Makefile
index 73c91faa8d..c26803909f 100644
--- a/dpdk/examples/l2fwd-jobstats/Makefile
+++ b/dpdk/examples/l2fwd-jobstats/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l2fwd-jobstats/main.c b/dpdk/examples/l2fwd-jobstats/main.c
index f975aa12d0..c2180c2d1c 100644
--- a/dpdk/examples/l2fwd-jobstats/main.c
+++ b/dpdk/examples/l2fwd-jobstats/main.c
@@ -329,6 +329,9 @@ show_stats_cb(__rte_unused void *param)
 	}
 
 	printf("\n====================================================\n");
+
+	fflush(stdout);
+
 	rte_eal_alarm_set(timer_period * US_PER_S, show_stats_cb, NULL);
 }
 
@@ -710,7 +713,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/l2fwd-keepalive/Makefile b/dpdk/examples/l2fwd-keepalive/Makefile
index 94d1e58bb5..ea3a9cbbf3 100644
--- a/dpdk/examples/l2fwd-keepalive/Makefile
+++ b/dpdk/examples/l2fwd-keepalive/Makefile
@@ -24,7 +24,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l2fwd-keepalive/main.c b/dpdk/examples/l2fwd-keepalive/main.c
index b36834974e..ba2745c915 100644
--- a/dpdk/examples/l2fwd-keepalive/main.c
+++ b/dpdk/examples/l2fwd-keepalive/main.c
@@ -44,7 +44,7 @@
 
 #define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
 
-#define NB_MBUF   8192
+#define NB_MBUF_PER_PORT 3000
 
 #define MAX_PKT_BURST 32
 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */
@@ -160,6 +160,8 @@ print_stats(__attribute__((unused)) struct rte_timer *ptr_timer,
 		   total_packets_rx,
 		   total_packets_dropped);
 	printf("\n====================================================\n");
+
+	fflush(stdout);
 }
 
 static void
@@ -475,7 +477,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
@@ -536,6 +538,7 @@ main(int argc, char **argv)
 	uint16_t portid, last_port;
 	unsigned lcore_id, rx_lcore_id;
 	unsigned nb_ports_in_mask = 0;
+	unsigned int total_nb_mbufs;
 	struct sigaction signal_handler;
 	struct rte_keepalive_shm *ka_shm;
 
@@ -561,16 +564,19 @@ main(int argc, char **argv)
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
 
-	/* create the mbuf pool */
-	l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, 32,
-		0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id());
-	if (l2fwd_pktmbuf_pool == NULL)
-		rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
-
 	nb_ports = rte_eth_dev_count_avail();
 	if (nb_ports == 0)
 		rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
+	/* create the mbuf pool */
+	total_nb_mbufs = NB_MBUF_PER_PORT * nb_ports;
+
+	l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
+		total_nb_mbufs,	32, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
+		rte_socket_id());
+	if (l2fwd_pktmbuf_pool == NULL)
+		rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
+
 	/* reset l2fwd_dst_ports */
 	for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
 		l2fwd_dst_ports[portid] = 0;
diff --git a/dpdk/examples/l2fwd-keepalive/meson.build b/dpdk/examples/l2fwd-keepalive/meson.build
index 6f7b007e1e..aecc8d9fc9 100644
--- a/dpdk/examples/l2fwd-keepalive/meson.build
+++ b/dpdk/examples/l2fwd-keepalive/meson.build
@@ -6,7 +6,13 @@
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
-ext_deps += cc.find_library('rt')
+librt = cc.find_library('rt', required: false)
+if not librt.found()
+	build = false
+	subdir_done()
+endif
+
+ext_deps += librt
 deps += 'timer'
 sources = files(
 	'main.c', 'shm.c'
diff --git a/dpdk/examples/l2fwd/Makefile b/dpdk/examples/l2fwd/Makefile
index 8b7b26cb90..15105ac57e 100644
--- a/dpdk/examples/l2fwd/Makefile
+++ b/dpdk/examples/l2fwd/Makefile
@@ -24,7 +24,7 @@ CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 # Add flag to allow experimental API as l2fwd uses rte_ethdev_set_ptype API
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l2fwd/main.c b/dpdk/examples/l2fwd/main.c
index 09257aab1c..e3767a3159 100644
--- a/dpdk/examples/l2fwd/main.c
+++ b/dpdk/examples/l2fwd/main.c
@@ -146,6 +146,8 @@ print_stats(void)
 		   total_packets_rx,
 		   total_packets_dropped);
 	printf("\n====================================================\n");
+
+	fflush(stdout);
 }
 
 static void
@@ -478,7 +480,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/l3fwd-acl/Makefile b/dpdk/examples/l3fwd-acl/Makefile
index d9909584b1..156dc19606 100644
--- a/dpdk/examples/l3fwd-acl/Makefile
+++ b/dpdk/examples/l3fwd-acl/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l3fwd-acl/main.c b/dpdk/examples/l3fwd-acl/main.c
index fa92a28297..cfbeee962b 100644
--- a/dpdk/examples/l3fwd-acl/main.c
+++ b/dpdk/examples/l3fwd-acl/main.c
@@ -1839,7 +1839,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/l3fwd-power/Makefile b/dpdk/examples/l3fwd-power/Makefile
index 729d49639b..74441f98cf 100644
--- a/dpdk/examples/l3fwd-power/Makefile
+++ b/dpdk/examples/l3fwd-power/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/l3fwd-power/main.c b/dpdk/examples/l3fwd-power/main.c
index d049d8a5dc..7fe5cbf577 100644
--- a/dpdk/examples/l3fwd-power/main.c
+++ b/dpdk/examples/l3fwd-power/main.c
@@ -880,9 +880,6 @@ sleep_until_rx_interrupt(int num)
 		port_id = ((uintptr_t)data) >> CHAR_BIT;
 		queue_id = ((uintptr_t)data) &
 			RTE_LEN2MASK(CHAR_BIT, uint8_t);
-		rte_spinlock_lock(&(locks[port_id]));
-		rte_eth_dev_rx_intr_disable(port_id, queue_id);
-		rte_spinlock_unlock(&(locks[port_id]));
 		RTE_LOG(INFO, L3FWD_POWER,
 			"lcore %u is waked up from rx interrupt on"
 			" port %d queue %d\n",
@@ -892,7 +889,7 @@ sleep_until_rx_interrupt(int num)
 	return 0;
 }
 
-static void turn_on_intr(struct lcore_conf *qconf)
+static void turn_on_off_intr(struct lcore_conf *qconf, bool on)
 {
 	int i;
 	struct lcore_rx_queue *rx_queue;
@@ -905,7 +902,10 @@ static void turn_on_intr(struct lcore_conf *qconf)
 		queue_id = rx_queue->queue_id;
 
 		rte_spinlock_lock(&(locks[port_id]));
-		rte_eth_dev_rx_intr_enable(port_id, queue_id);
+		if (on)
+			rte_eth_dev_rx_intr_enable(port_id, queue_id);
+		else
+			rte_eth_dev_rx_intr_disable(port_id, queue_id);
 		rte_spinlock_unlock(&(locks[port_id]));
 	}
 }
@@ -1338,11 +1338,12 @@ main_loop(__attribute__((unused)) void *dummy)
 				 */
 				rte_delay_us(lcore_idle_hint);
 			else {
-				/* suspend until rx interrupt trigges */
+				/* suspend until rx interrupt triggers */
 				if (intr_en) {
-					turn_on_intr(qconf);
+					turn_on_off_intr(qconf, 1);
 					sleep_until_rx_interrupt(
 						qconf->n_rx_queue);
+					turn_on_off_intr(qconf, 0);
 					/**
 					 * start receiving packets immediately
 					 */
@@ -1997,7 +1998,7 @@ check_all_ports_link_status(uint32_t port_mask)
 						"Mbps - %s\n", (uint8_t)portid,
 						(unsigned)link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n",
 						(uint8_t)portid);
@@ -2444,9 +2445,7 @@ main(int argc, char **argv)
 				if (add_cb_parse_ptype(portid, queueid) < 0)
 					rte_exit(EXIT_FAILURE,
 						 "Fail to add ptype cb\n");
-			} else if (!check_ptype(portid))
-				rte_exit(EXIT_FAILURE,
-					 "PMD can not provide needed ptypes\n");
+			}
 		}
 	}
 
@@ -2477,6 +2476,11 @@ main(int argc, char **argv)
 		}
 		/* initialize spinlock for each port */
 		rte_spinlock_init(&(locks[portid]));
+
+		if (!parse_ptype)
+			if (!check_ptype(portid))
+				rte_exit(EXIT_FAILURE,
+					"PMD can not provide needed ptypes\n");
 	}
 
 	check_all_ports_link_status(enabled_port_mask);
diff --git a/dpdk/examples/l3fwd/Makefile b/dpdk/examples/l3fwd/Makefile
index b2dbf26075..38a370c2cf 100644
--- a/dpdk/examples/l3fwd/Makefile
+++ b/dpdk/examples/l3fwd/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/l3fwd/main.c b/dpdk/examples/l3fwd/main.c
index 4dea12a653..b98040df45 100644
--- a/dpdk/examples/l3fwd/main.c
+++ b/dpdk/examples/l3fwd/main.c
@@ -53,7 +53,7 @@
 #define RTE_TEST_RX_DESC_DEFAULT 1024
 #define RTE_TEST_TX_DESC_DEFAULT 1024
 
-#define MAX_TX_QUEUE_PER_PORT RTE_MAX_ETHPORTS
+#define MAX_TX_QUEUE_PER_PORT RTE_MAX_LCORE
 #define MAX_RX_QUEUE_PER_PORT 128
 
 #define MAX_LCORE_PARAMS 1024
@@ -747,7 +747,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps -%s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/link_status_interrupt/Makefile b/dpdk/examples/link_status_interrupt/Makefile
index 4f02a89013..879ee7384d 100644
--- a/dpdk/examples/link_status_interrupt/Makefile
+++ b/dpdk/examples/link_status_interrupt/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/link_status_interrupt/main.c b/dpdk/examples/link_status_interrupt/main.c
index a924aa2313..6b8c153b58 100644
--- a/dpdk/examples/link_status_interrupt/main.c
+++ b/dpdk/examples/link_status_interrupt/main.c
@@ -162,6 +162,8 @@ print_stats(void)
 		   total_packets_rx,
 		   total_packets_dropped);
 	printf("\n====================================================\n");
+
+	fflush(stdout);
 }
 
 static void
@@ -500,7 +502,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/meson.build b/dpdk/examples/meson.build
index 1f2b6f5168..9e081f3fb7 100644
--- a/dpdk/examples/meson.build
+++ b/dpdk/examples/meson.build
@@ -1,9 +1,9 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017-2019 Intel Corporation
 
-driver_libs = []
+link_whole_libs = []
 if get_option('default_library') == 'static'
-	driver_libs = dpdk_drivers
+	link_whole_libs = dpdk_static_libraries + dpdk_drivers
 endif
 
 execinfo = cc.find_library('execinfo', required: false)
@@ -46,13 +46,6 @@ all_examples = [
 	'vm_power_manager/guest_cli',
 	'vmdq', 'vmdq_dcb',
 ]
-# install all example code on install - irrespective of whether the example in
-# question is to be built as part of this build or not.
-foreach ex:all_examples
-	install_subdir(ex,
-			install_dir: get_option('datadir') + '/dpdk/examples',
-			exclude_files: 'meson.build')
-endforeach
 
 if get_option('examples') == ''
 	subdir_done()
@@ -69,6 +62,10 @@ default_cflags = machine_args
 if cc.has_argument('-Wno-format-truncation')
 	default_cflags += '-Wno-format-truncation'
 endif
+default_ldflags = dpdk_extra_ldflags
+if get_option('default_library') == 'static' and not is_windows
+	default_ldflags += ['-Wl,--export-dynamic']
+endif
 
 foreach example: examples
 	name = example.split('/')[-1]
@@ -76,6 +73,7 @@ foreach example: examples
 	sources = []
 	allow_experimental_apis = false
 	cflags = default_cflags
+	ldflags = default_ldflags
 
 	ext_deps = [execinfo]
 	includes = [include_directories(example)]
@@ -99,8 +97,8 @@ foreach example: examples
 		endif
 		executable('dpdk-' + name, sources,
 			include_directories: includes,
-			link_whole: driver_libs,
-			link_args: dpdk_extra_ldflags,
+			link_whole: link_whole_libs,
+			link_args: ldflags,
 			c_args: cflags,
 			dependencies: dep_objs)
 	elif not allow_skips
diff --git a/dpdk/examples/multi_process/client_server_mp/mp_server/init.c b/dpdk/examples/multi_process/client_server_mp/mp_server/init.c
index ad9f46f0aa..c2ec07ac65 100644
--- a/dpdk/examples/multi_process/client_server_mp/mp_server/init.c
+++ b/dpdk/examples/multi_process/client_server_mp/mp_server/init.c
@@ -209,7 +209,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
 						"Mbps - %s\n", ports->id[portid],
 						(unsigned)link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n",
 						(uint8_t)ports->id[portid]);
diff --git a/dpdk/examples/multi_process/client_server_mp/mp_server/main.c b/dpdk/examples/multi_process/client_server_mp/mp_server/main.c
index 802e29d10d..1084b303ff 100644
--- a/dpdk/examples/multi_process/client_server_mp/mp_server/main.c
+++ b/dpdk/examples/multi_process/client_server_mp/mp_server/main.c
@@ -59,12 +59,17 @@ static struct client_rx_buf *cl_rx_buf;
 static const char *
 get_printable_mac_addr(uint16_t port)
 {
-	static const char err_address[] = "00:00:00:00:00:00";
-	static char addresses[RTE_MAX_ETHPORTS][sizeof(err_address)];
+	static const struct rte_ether_addr null_mac; /* static defaults to 0 */
+	static char err_address[32];
+	static char addresses[RTE_MAX_ETHPORTS][32];
 	int ret;
 
-	if (unlikely(port >= RTE_MAX_ETHPORTS))
+	if (unlikely(port >= RTE_MAX_ETHPORTS)) {
+		if (err_address[0] == '\0')
+			rte_ether_format_addr(err_address,
+					sizeof(err_address), &null_mac);
 		return err_address;
+	}
 	if (unlikely(addresses[port][0]=='\0')){
 		struct rte_ether_addr mac;
 		ret = rte_eth_macaddr_get(port, &mac);
@@ -73,10 +78,8 @@ get_printable_mac_addr(uint16_t port)
 			       port, rte_strerror(-ret));
 			return err_address;
 		}
-		snprintf(addresses[port], sizeof(addresses[port]),
-				"%02x:%02x:%02x:%02x:%02x:%02x\n",
-				mac.addr_bytes[0], mac.addr_bytes[1], mac.addr_bytes[2],
-				mac.addr_bytes[3], mac.addr_bytes[4], mac.addr_bytes[5]);
+		rte_ether_format_addr(addresses[port],
+				sizeof(addresses[port]), &mac);
 	}
 	return addresses[port];
 }
diff --git a/dpdk/examples/multi_process/client_server_mp/shared/common.h b/dpdk/examples/multi_process/client_server_mp/shared/common.h
index 6dd43fcac2..76beca0101 100644
--- a/dpdk/examples/multi_process/client_server_mp/shared/common.h
+++ b/dpdk/examples/multi_process/client_server_mp/shared/common.h
@@ -43,7 +43,7 @@ struct port_info {
  * Given the rx queue name template above, get the queue name
  */
 static inline const char *
-get_rx_queue_name(unsigned id)
+get_rx_queue_name(uint8_t id)
 {
 	/* buffer for return value. Size calculated by %u being replaced
 	 * by maximum 3 digits (plus an extra byte for safety) */
diff --git a/dpdk/examples/multi_process/symmetric_mp/main.c b/dpdk/examples/multi_process/symmetric_mp/main.c
index 7f491452a7..c5cd8825e5 100644
--- a/dpdk/examples/multi_process/symmetric_mp/main.c
+++ b/dpdk/examples/multi_process/symmetric_mp/main.c
@@ -389,7 +389,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/ntb/Makefile b/dpdk/examples/ntb/Makefile
index baeba11e85..f41ccfac27 100644
--- a/dpdk/examples/ntb/Makefile
+++ b/dpdk/examples/ntb/Makefile
@@ -26,7 +26,7 @@ LDFLAGS += -pthread
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
@@ -40,7 +40,7 @@ build:
 .PHONY: clean
 clean:
 	rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
-	rmdir --ignore-fail-on-non-empty build
+	test -d build && rmdir -p build || true
 
 else # Build using legacy build system
 
diff --git a/dpdk/examples/ntb/ntb_fwd.c b/dpdk/examples/ntb/ntb_fwd.c
index c914256dd4..17eedcf0b8 100644
--- a/dpdk/examples/ntb/ntb_fwd.c
+++ b/dpdk/examples/ntb/ntb_fwd.c
@@ -19,6 +19,7 @@
 #include <rte_lcore.h>
 #include <rte_cycles.h>
 #include <rte_pmd_ntb.h>
+#include <rte_mbuf_pool_ops.h>
 
 /* Per-port statistics struct */
 struct ntb_port_statistics {
@@ -1256,6 +1257,11 @@ ntb_mbuf_pool_create(uint16_t mbuf_seg_size, uint32_t nb_mbuf,
 	if (mp == NULL)
 		return NULL;
 
+	if (rte_mempool_set_ops_byname(mp, rte_mbuf_best_mempool_ops(), NULL)) {
+		printf("error setting mempool handler\n");
+		goto fail;
+	}
+
 	memset(&mbp_priv, 0, sizeof(mbp_priv));
 	mbp_priv.mbuf_data_room_size = mbuf_seg_size;
 	mbp_priv.mbuf_priv_size = 0;
diff --git a/dpdk/examples/packet_ordering/Makefile b/dpdk/examples/packet_ordering/Makefile
index 261b7f06a8..1e50389421 100644
--- a/dpdk/examples/packet_ordering/Makefile
+++ b/dpdk/examples/packet_ordering/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/packet_ordering/main.c b/dpdk/examples/packet_ordering/main.c
index b397b318e6..edaf810d94 100644
--- a/dpdk/examples/packet_ordering/main.c
+++ b/dpdk/examples/packet_ordering/main.c
@@ -675,7 +675,7 @@ main(int argc, char **argv)
 	/* Initialize EAL */
 	ret = rte_eal_init(argc, argv);
 	if (ret < 0)
-		return -1;
+		rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
 
 	argc -= ret;
 	argv += ret;
@@ -683,7 +683,7 @@ main(int argc, char **argv)
 	/* Parse the application specific arguments */
 	ret = parse_args(argc, argv);
 	if (ret < 0)
-		return -1;
+		rte_exit(EXIT_FAILURE, "Invalid packet_ordering arguments\n");
 
 	/* Check if we have enought cores */
 	if (rte_lcore_count() < 3)
diff --git a/dpdk/examples/performance-thread/l3fwd-thread/main.c b/dpdk/examples/performance-thread/l3fwd-thread/main.c
index ad540fd842..96fbdcdde2 100644
--- a/dpdk/examples/performance-thread/l3fwd-thread/main.c
+++ b/dpdk/examples/performance-thread/l3fwd-thread/main.c
@@ -2,6 +2,10 @@
  * Copyright(c) 2010-2016 Intel Corporation
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -12,6 +16,7 @@
 #include <stdarg.h>
 #include <errno.h>
 #include <getopt.h>
+#include <sched.h>
 
 #include <rte_common.h>
 #include <rte_vect.h>
@@ -599,8 +604,8 @@ struct thread_rx_conf rx_thread[MAX_RX_THREAD];
 struct thread_tx_conf {
 	struct thread_conf conf;
 
-	uint16_t tx_queue_id[RTE_MAX_LCORE];
-	struct mbuf_table tx_mbufs[RTE_MAX_LCORE];
+	uint16_t tx_queue_id[RTE_MAX_ETHPORTS];
+	struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS];
 
 	struct rte_ring *ring;
 	struct lthread_cond **ready;
@@ -3457,7 +3462,7 @@ check_all_ports_link_status(uint32_t port_mask)
 					"Port%d Link Up. Speed %u Mbps - %s\n",
 						portid, link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n", portid);
 				continue;
diff --git a/dpdk/examples/ptpclient/Makefile b/dpdk/examples/ptpclient/Makefile
index 82d72b3e31..9e47a60117 100644
--- a/dpdk/examples/ptpclient/Makefile
+++ b/dpdk/examples/ptpclient/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/qos_meter/Makefile b/dpdk/examples/qos_meter/Makefile
index 7c2bf88a90..f733facaeb 100644
--- a/dpdk/examples/qos_meter/Makefile
+++ b/dpdk/examples/qos_meter/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/qos_sched/Makefile b/dpdk/examples/qos_sched/Makefile
index 525061ca07..736ac00a36 100644
--- a/dpdk/examples/qos_sched/Makefile
+++ b/dpdk/examples/qos_sched/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/qos_sched/args.c b/dpdk/examples/qos_sched/args.c
index 7431b29816..2727fd4f27 100644
--- a/dpdk/examples/qos_sched/args.c
+++ b/dpdk/examples/qos_sched/args.c
@@ -39,7 +39,7 @@ static const char usage[] =
 	"           multiple pfc can be configured in command line                      \n"
 	"                                                                               \n"
 	"Application optional parameters:                                               \n"
-        "    --i     : run in interactive mode (default value is %u)                    \n"
+	"    -i      : run in interactive mode (default value is %u)                    \n"
 	"    --mst I : master core index (default value is %u)                          \n"
 	"    --rsz \"A, B, C\" :   Ring sizes                                           \n"
 	"           A = Size (in number of buffer descriptors) of each of the NIC RX    \n"
diff --git a/dpdk/examples/qos_sched/cfg_file.c b/dpdk/examples/qos_sched/cfg_file.c
index 5714c3f36d..f078e4f7de 100644
--- a/dpdk/examples/qos_sched/cfg_file.c
+++ b/dpdk/examples/qos_sched/cfg_file.c
@@ -20,6 +20,9 @@
  * for new entries do we add in */
 #define CFG_ALLOC_ENTRY_BATCH 16
 
+uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE];
+uint32_t n_active_queues;
+
 int
 cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params)
 {
diff --git a/dpdk/examples/qos_sched/init.c b/dpdk/examples/qos_sched/init.c
index 0a17e0d4d5..9626c15b81 100644
--- a/dpdk/examples/qos_sched/init.c
+++ b/dpdk/examples/qos_sched/init.c
@@ -164,7 +164,7 @@ app_init_port(uint16_t portid, struct rte_mempool *mp)
 		printf(" Link Up - speed %u Mbps - %s\n",
 			(uint32_t) link.link_speed,
 			(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-			("full-duplex") : ("half-duplex\n"));
+			("full-duplex") : ("half-duplex"));
 	} else {
 		printf(" Link Down\n");
 	}
diff --git a/dpdk/examples/qos_sched/main.h b/dpdk/examples/qos_sched/main.h
index baa2b3eadc..23bc418d97 100644
--- a/dpdk/examples/qos_sched/main.h
+++ b/dpdk/examples/qos_sched/main.h
@@ -148,8 +148,8 @@ extern struct burst_conf burst_conf;
 extern struct ring_thresh rx_thresh;
 extern struct ring_thresh tx_thresh;
 
-uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE];
-uint32_t n_active_queues;
+extern uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE];
+extern uint32_t n_active_queues;
 
 extern struct rte_sched_port_params port_params;
 extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS];
diff --git a/dpdk/examples/rxtx_callbacks/Makefile b/dpdk/examples/rxtx_callbacks/Makefile
index 584b9fafb0..eecdcada3e 100644
--- a/dpdk/examples/rxtx_callbacks/Makefile
+++ b/dpdk/examples/rxtx_callbacks/Makefile
@@ -22,7 +22,9 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/server_node_efd/server/init.c b/dpdk/examples/server_node_efd/server/init.c
index 00e2e40599..378a74fa5c 100644
--- a/dpdk/examples/server_node_efd/server/init.c
+++ b/dpdk/examples/server_node_efd/server/init.c
@@ -272,7 +272,7 @@ check_all_ports_link_status(uint16_t port_num, uint32_t port_mask)
 						info->id[portid],
 						link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n",
 						info->id[portid]);
diff --git a/dpdk/examples/service_cores/Makefile b/dpdk/examples/service_cores/Makefile
index c47055813e..b8669fdf7e 100644
--- a/dpdk/examples/service_cores/Makefile
+++ b/dpdk/examples/service_cores/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/skeleton/Makefile b/dpdk/examples/skeleton/Makefile
index 2c29004d79..5059f3123f 100644
--- a/dpdk/examples/skeleton/Makefile
+++ b/dpdk/examples/skeleton/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/tep_termination/Makefile b/dpdk/examples/tep_termination/Makefile
index 645112498d..548ca3cee3 100644
--- a/dpdk/examples/tep_termination/Makefile
+++ b/dpdk/examples/tep_termination/Makefile
@@ -24,7 +24,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -Wno-deprecated-declarations
 
diff --git a/dpdk/examples/tep_termination/main.c b/dpdk/examples/tep_termination/main.c
index ab956ad7ce..b9fffca020 100644
--- a/dpdk/examples/tep_termination/main.c
+++ b/dpdk/examples/tep_termination/main.c
@@ -1110,6 +1110,8 @@ print_stats(__rte_unused void *arg)
 			dev_ll = dev_ll->next;
 		}
 		printf("\n================================================\n");
+
+		fflush(stdout);
 	}
 
 	return NULL;
diff --git a/dpdk/examples/tep_termination/vxlan_setup.c b/dpdk/examples/tep_termination/vxlan_setup.c
index eca119a728..4b44ccc143 100644
--- a/dpdk/examples/tep_termination/vxlan_setup.c
+++ b/dpdk/examples/tep_termination/vxlan_setup.c
@@ -194,8 +194,6 @@ vxlan_port_init(uint16_t port, struct rte_mempool *mbuf_pool)
 			ports_eth_addr[port].addr_bytes[5]);
 
 	if (tso_segsz != 0) {
-		struct rte_eth_dev_info dev_info;
-		rte_eth_dev_info_get(port, &dev_info);
 		if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0)
 			RTE_LOG(WARNING, PORT,
 				"hardware TSO offload is not supported\n");
diff --git a/dpdk/examples/timer/Makefile b/dpdk/examples/timer/Makefile
index bf86339ab7..b34c8baa6b 100644
--- a/dpdk/examples/timer/Makefile
+++ b/dpdk/examples/timer/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/vdpa/Makefile b/dpdk/examples/vdpa/Makefile
index 6a25497cd8..bc0b6793e6 100644
--- a/dpdk/examples/vdpa/Makefile
+++ b/dpdk/examples/vdpa/Makefile
@@ -23,7 +23,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/vhost/Makefile b/dpdk/examples/vhost/Makefile
index f2b1615418..ef6f3550f3 100644
--- a/dpdk/examples/vhost/Makefile
+++ b/dpdk/examples/vhost/Makefile
@@ -24,7 +24,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/vhost/main.c b/dpdk/examples/vhost/main.c
index ab649bf147..312829e8b9 100644
--- a/dpdk/examples/vhost/main.c
+++ b/dpdk/examples/vhost/main.c
@@ -1334,6 +1334,8 @@ print_stats(__rte_unused void *arg)
 		}
 
 		printf("===================================================\n");
+
+		fflush(stdout);
 	}
 
 	return NULL;
diff --git a/dpdk/examples/vhost_blk/Makefile b/dpdk/examples/vhost_blk/Makefile
index 39244320d8..3952791784 100644
--- a/dpdk/examples/vhost_blk/Makefile
+++ b/dpdk/examples/vhost_blk/Makefile
@@ -25,7 +25,7 @@ LDFLAGS += -pthread
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 CFLAGS += -DALLOW_EXPERIMENTAL_API
 
diff --git a/dpdk/examples/vhost_blk/vhost_blk.c b/dpdk/examples/vhost_blk/vhost_blk.c
index 3182a488bb..d0c30a9c6f 100644
--- a/dpdk/examples/vhost_blk/vhost_blk.c
+++ b/dpdk/examples/vhost_blk/vhost_blk.c
@@ -2,6 +2,12 @@
  * Copyright(c) 2010-2019 Intel Corporation
  */
 
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <pthread.h>
+#include <sched.h>
+
 #include <stdint.h>
 #include <unistd.h>
 #include <stdbool.h>
@@ -31,6 +37,8 @@
 			    (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \
 			    (1ULL << VHOST_USER_F_PROTOCOL_FEATURES))
 
+struct vhost_blk_ctrlr *g_vhost_ctrlr;
+
 /* Path to folder where character device will be created. Can be set by user. */
 static char dev_pathname[PATH_MAX] = "";
 static sem_t exit_sem;
@@ -856,6 +864,7 @@ new_device(int vid)
 				ctrlr->bdev->vid, i,
 				&blk_vq->last_avail_idx,
 				&blk_vq->last_used_idx);
+			assert(ret == 0);
 
 			blk_vq->avail_wrap_counter = blk_vq->last_avail_idx &
 				(1 << 15);
@@ -993,11 +1002,7 @@ vhost_blk_ctrlr_construct(const char *ctrlr_name)
 	}
 	snprintf(dev_pathname, sizeof(dev_pathname), "%s/%s", path, ctrlr_name);
 
-	if (access(dev_pathname, F_OK) != -1) {
-		if (unlink(dev_pathname) != 0)
-			rte_exit(EXIT_FAILURE, "Cannot remove %s.\n",
-				 dev_pathname);
-	}
+	unlink(dev_pathname);
 
 	if (rte_vhost_driver_register(dev_pathname, 0) != 0) {
 		fprintf(stderr, "socket %s already exists\n", dev_pathname);
@@ -1040,8 +1045,7 @@ signal_handler(__rte_unused int signum)
 {
 	struct vhost_blk_ctrlr *ctrlr;
 
-	if (access(dev_pathname, F_OK) == 0)
-		unlink(dev_pathname);
+	unlink(dev_pathname);
 
 	if (g_should_stop != -1) {
 		g_should_stop = 1;
@@ -1084,7 +1088,11 @@ int main(int argc, char *argv[])
 		return -1;
 	}
 
-	rte_vhost_driver_start(dev_pathname);
+	ret = rte_vhost_driver_start(dev_pathname);
+	if (ret < 0) {
+		fprintf(stderr, "Failed to start vhost driver.\n");
+		return -1;
+	}
 
 	/* loop for exit the application */
 	while (1)
diff --git a/dpdk/examples/vhost_blk/vhost_blk.h b/dpdk/examples/vhost_blk/vhost_blk.h
index 933e2b7c57..17258d284b 100644
--- a/dpdk/examples/vhost_blk/vhost_blk.h
+++ b/dpdk/examples/vhost_blk/vhost_blk.h
@@ -112,8 +112,8 @@ struct inflight_blk_task {
 	struct rte_vhost_inflight_info_packed *inflight_packed;
 };
 
-struct vhost_blk_ctrlr *g_vhost_ctrlr;
-struct vhost_device_ops vhost_blk_device_ops;
+extern struct vhost_blk_ctrlr *g_vhost_ctrlr;
+extern struct vhost_device_ops vhost_blk_device_ops;
 
 int vhost_bdev_process_blk_commands(struct vhost_block_dev *bdev,
 				     struct vhost_blk_task *task);
diff --git a/dpdk/examples/vhost_crypto/Makefile b/dpdk/examples/vhost_crypto/Makefile
index ae8cb81f87..28e3e4de74 100644
--- a/dpdk/examples/vhost_crypto/Makefile
+++ b/dpdk/examples/vhost_crypto/Makefile
@@ -23,7 +23,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/vhost_crypto/main.c b/dpdk/examples/vhost_crypto/main.c
index 1d7ba94196..405d16966d 100644
--- a/dpdk/examples/vhost_crypto/main.c
+++ b/dpdk/examples/vhost_crypto/main.c
@@ -195,7 +195,7 @@ vhost_crypto_usage(const char *prgname)
 {
 	printf("%s [EAL options] --\n"
 		"  --%s <lcore>,SOCKET-FILE-PATH\n"
-		"  --%s (lcore,cdev_id,queue_id)[,(lcore,cdev_id,queue_id)]"
+		"  --%s (lcore,cdev_id,queue_id)[,(lcore,cdev_id,queue_id)]\n"
 		"  --%s: zero copy\n"
 		"  --%s: guest polling\n",
 		prgname, SOCKET_FILE_KEYWORD, CONFIG_KEYWORD,
@@ -544,7 +544,7 @@ main(int argc, char *argv[])
 		snprintf(name, 127, "COPPOOL_%u", lo->lcore_id);
 		info->cop_pool = rte_crypto_op_pool_create(name,
 				RTE_CRYPTO_OP_TYPE_SYMMETRIC, NB_MEMPOOL_OBJS,
-				NB_CACHE_OBJS, 0,
+				NB_CACHE_OBJS, VHOST_CRYPTO_MAX_IV_LEN,
 				rte_lcore_to_socket_id(lo->lcore_id));
 
 		if (!info->cop_pool) {
diff --git a/dpdk/examples/vm_power_manager/channel_manager.c b/dpdk/examples/vm_power_manager/channel_manager.c
index 4ac21f02c1..0a28cb643b 100644
--- a/dpdk/examples/vm_power_manager/channel_manager.c
+++ b/dpdk/examples/vm_power_manager/channel_manager.c
@@ -4,7 +4,6 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/un.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <inttypes.h>
@@ -28,13 +27,14 @@
 #include <libvirt/libvirt.h>
 
 #include "channel_manager.h"
-#include "channel_commands.h"
 #include "channel_monitor.h"
 #include "power_manager.h"
 
 
 #define RTE_LOGTYPE_CHANNEL_MANAGER RTE_LOGTYPE_USER1
 
+struct libvirt_vm_info lvm_info[MAX_CLIENTS];
+
 /* Global pointer to libvirt connection */
 static virConnectPtr global_vir_conn_ptr;
 
@@ -466,9 +466,15 @@ add_all_channels(const char *vm_name)
 			continue;
 		}
 
-		snprintf(chan_info->channel_path,
+		if ((size_t)snprintf(chan_info->channel_path,
 				sizeof(chan_info->channel_path), "%s%s",
-				CHANNEL_MGR_SOCKET_PATH, dir->d_name);
+				CHANNEL_MGR_SOCKET_PATH, dir->d_name)
+					>= sizeof(chan_info->channel_path)) {
+			RTE_LOG(ERR, CHANNEL_MANAGER, "Pathname too long for channel '%s%s'\n",
+					CHANNEL_MGR_SOCKET_PATH, dir->d_name);
+			rte_free(chan_info);
+			continue;
+		}
 
 		if (setup_channel_info(&vm_info, &chan_info, channel_num) < 0) {
 			rte_free(chan_info);
diff --git a/dpdk/examples/vm_power_manager/channel_manager.h b/dpdk/examples/vm_power_manager/channel_manager.h
index 8284be0a18..e55376fcdb 100644
--- a/dpdk/examples/vm_power_manager/channel_manager.h
+++ b/dpdk/examples/vm_power_manager/channel_manager.h
@@ -10,7 +10,7 @@ extern "C" {
 #endif
 
 #include <linux/limits.h>
-#include <sys/un.h>
+#include <linux/un.h>
 #include <rte_atomic.h>
 #include <stdbool.h>
 
@@ -26,11 +26,6 @@ extern "C" {
 /* FIFO file name template */
 #define CHANNEL_MGR_FIFO_PATTERN_NAME   "fifo"
 
-#ifndef UNIX_PATH_MAX
-struct sockaddr_un _sockaddr_un;
-#define UNIX_PATH_MAX sizeof(_sockaddr_un.sun_path)
-#endif
-
 #define MAX_CLIENTS 64
 #define MAX_VCPUS 20
 
@@ -41,7 +36,7 @@ struct libvirt_vm_info {
 	uint8_t num_cpus;
 };
 
-struct libvirt_vm_info lvm_info[MAX_CLIENTS];
+extern struct libvirt_vm_info lvm_info[MAX_CLIENTS];
 /* Communication Channel Status */
 enum channel_status { CHANNEL_MGR_CHANNEL_DISCONNECTED = 0,
 	CHANNEL_MGR_CHANNEL_CONNECTED,
diff --git a/dpdk/examples/vm_power_manager/channel_monitor.c b/dpdk/examples/vm_power_manager/channel_monitor.c
index 090c2a98b0..fe5a183fd7 100644
--- a/dpdk/examples/vm_power_manager/channel_monitor.c
+++ b/dpdk/examples/vm_power_manager/channel_monitor.c
@@ -35,7 +35,6 @@
 
 #include <libvirt/libvirt.h>
 #include "channel_monitor.h"
-#include "channel_commands.h"
 #include "channel_manager.h"
 #include "power_manager.h"
 #include "oob_monitor.h"
@@ -108,7 +107,7 @@ str_to_ether_addr(const char *a, struct rte_ether_addr *ether_addr)
 }
 
 static int
-set_policy_mac(struct channel_packet *pkt, int idx, char *mac)
+set_policy_mac(struct rte_power_channel_packet *pkt, int idx, char *mac)
 {
 	union PFID pfid;
 	int ret;
@@ -165,7 +164,7 @@ get_resource_id_from_vmname(const char *vm_name)
 }
 
 static int
-parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
+parse_json_to_pkt(json_t *element, struct rte_power_channel_packet *pkt,
 					const char *vm_name)
 {
 	const char *key;
@@ -173,14 +172,14 @@ parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
 	int ret;
 	int resource_id;
 
-	memset(pkt, 0, sizeof(struct channel_packet));
+	memset(pkt, 0, sizeof(*pkt));
 
 	pkt->nb_mac_to_monitor = 0;
 	pkt->t_boost_status.tbEnabled = false;
-	pkt->workload = LOW;
-	pkt->policy_to_use = TIME;
-	pkt->command = PKT_POLICY;
-	pkt->core_type = CORE_TYPE_PHYSICAL;
+	pkt->workload = RTE_POWER_WL_LOW;
+	pkt->policy_to_use = RTE_POWER_POLICY_TIME;
+	pkt->command = RTE_POWER_PKT_POLICY;
+	pkt->core_type = RTE_POWER_CORE_TYPE_PHYSICAL;
 
 	if (vm_name == NULL) {
 		RTE_LOG(ERR, CHANNEL_MONITOR,
@@ -203,11 +202,11 @@ parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
 			char command[32];
 			strlcpy(command, json_string_value(value), 32);
 			if (!strcmp(command, "power")) {
-				pkt->command = CPU_POWER;
+				pkt->command = RTE_POWER_CPU_POWER;
 			} else if (!strcmp(command, "create")) {
-				pkt->command = PKT_POLICY;
+				pkt->command = RTE_POWER_PKT_POLICY;
 			} else if (!strcmp(command, "destroy")) {
-				pkt->command = PKT_POLICY_REMOVE;
+				pkt->command = RTE_POWER_PKT_POLICY_REMOVE;
 			} else {
 				RTE_LOG(ERR, CHANNEL_MONITOR,
 					"Invalid command received in JSON\n");
@@ -217,13 +216,17 @@ parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
 			char command[32];
 			strlcpy(command, json_string_value(value), 32);
 			if (!strcmp(command, "TIME")) {
-				pkt->policy_to_use = TIME;
+				pkt->policy_to_use =
+						RTE_POWER_POLICY_TIME;
 			} else if (!strcmp(command, "TRAFFIC")) {
-				pkt->policy_to_use = TRAFFIC;
+				pkt->policy_to_use =
+						RTE_POWER_POLICY_TRAFFIC;
 			} else if (!strcmp(command, "WORKLOAD")) {
-				pkt->policy_to_use = WORKLOAD;
+				pkt->policy_to_use =
+						RTE_POWER_POLICY_WORKLOAD;
 			} else if (!strcmp(command, "BRANCH_RATIO")) {
-				pkt->policy_to_use = BRANCH_RATIO;
+				pkt->policy_to_use =
+						RTE_POWER_POLICY_BRANCH_RATIO;
 			} else {
 				RTE_LOG(ERR, CHANNEL_MONITOR,
 					"Wrong policy_type received in JSON\n");
@@ -233,11 +236,11 @@ parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
 			char command[32];
 			strlcpy(command, json_string_value(value), 32);
 			if (!strcmp(command, "HIGH")) {
-				pkt->workload = HIGH;
+				pkt->workload = RTE_POWER_WL_HIGH;
 			} else if (!strcmp(command, "MEDIUM")) {
-				pkt->workload = MEDIUM;
+				pkt->workload = RTE_POWER_WL_MEDIUM;
 			} else if (!strcmp(command, "LOW")) {
-				pkt->workload = LOW;
+				pkt->workload = RTE_POWER_WL_LOW;
 			} else {
 				RTE_LOG(ERR, CHANNEL_MONITOR,
 					"Wrong workload received in JSON\n");
@@ -283,17 +286,17 @@ parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
 			char unit[32];
 			strlcpy(unit, json_string_value(value), 32);
 			if (!strcmp(unit, "SCALE_UP")) {
-				pkt->unit = CPU_POWER_SCALE_UP;
+				pkt->unit = RTE_POWER_SCALE_UP;
 			} else if (!strcmp(unit, "SCALE_DOWN")) {
-				pkt->unit = CPU_POWER_SCALE_DOWN;
+				pkt->unit = RTE_POWER_SCALE_DOWN;
 			} else if (!strcmp(unit, "SCALE_MAX")) {
-				pkt->unit = CPU_POWER_SCALE_MAX;
+				pkt->unit = RTE_POWER_SCALE_MAX;
 			} else if (!strcmp(unit, "SCALE_MIN")) {
-				pkt->unit = CPU_POWER_SCALE_MIN;
+				pkt->unit = RTE_POWER_SCALE_MIN;
 			} else if (!strcmp(unit, "ENABLE_TURBO")) {
-				pkt->unit = CPU_POWER_ENABLE_TURBO;
+				pkt->unit = RTE_POWER_ENABLE_TURBO;
 			} else if (!strcmp(unit, "DISABLE_TURBO")) {
-				pkt->unit = CPU_POWER_DISABLE_TURBO;
+				pkt->unit = RTE_POWER_DISABLE_TURBO;
 			} else {
 				RTE_LOG(ERR, CHANNEL_MONITOR,
 					"Invalid command received in JSON\n");
@@ -312,7 +315,7 @@ parse_json_to_pkt(json_t *element, struct channel_packet *pkt,
 				vm_name);
 			return -1;
 		}
-		strlcpy(pkt->vm_name, vm_name, VM_MAX_NAME_SZ);
+		strlcpy(pkt->vm_name, vm_name, RTE_POWER_VM_MAX_NAME_SZ);
 		pkt->resource_id = resource_id;
 	}
 	return 0;
@@ -367,7 +370,7 @@ pcpu_monitor(struct policy *pol, struct core_info *ci, int pcpu, int count)
 {
 	int ret = 0;
 
-	if (pol->pkt.policy_to_use == BRANCH_RATIO) {
+	if (pol->pkt.policy_to_use == RTE_POWER_POLICY_BRANCH_RATIO) {
 		ci->cd[pcpu].oob_enabled = 1;
 		ret = add_core_to_monitor(pcpu);
 		if (ret == 0)
@@ -407,7 +410,7 @@ get_pcpu_to_control(struct policy *pol)
 	 * differenciate between them when adding them to the branch monitor.
 	 * Virtual cores need to be converted to physical cores.
 	 */
-	if (pol->pkt.core_type == CORE_TYPE_VIRTUAL) {
+	if (pol->pkt.core_type == RTE_POWER_CORE_TYPE_VIRTUAL) {
 		/*
 		 * If the cores in the policy are virtual, we need to map them
 		 * to physical core. We look up the vm info and use that for
@@ -463,7 +466,7 @@ get_pfid(struct policy *pol)
 }
 
 static int
-update_policy(struct channel_packet *pkt)
+update_policy(struct rte_power_channel_packet *pkt)
 {
 
 	unsigned int updated = 0;
@@ -479,7 +482,8 @@ update_policy(struct channel_packet *pkt)
 			policies[i].pkt = *pkt;
 			get_pcpu_to_control(&policies[i]);
 			/* Check Eth dev only for Traffic policy */
-			if (policies[i].pkt.policy_to_use == TRAFFIC) {
+			if (policies[i].pkt.policy_to_use ==
+					RTE_POWER_POLICY_TRAFFIC) {
 				if (get_pfid(&policies[i]) < 0) {
 					updated = 1;
 					break;
@@ -496,7 +500,8 @@ update_policy(struct channel_packet *pkt)
 				policies[i].pkt = *pkt;
 				get_pcpu_to_control(&policies[i]);
 				/* Check Eth dev only for Traffic policy */
-				if (policies[i].pkt.policy_to_use == TRAFFIC) {
+				if (policies[i].pkt.policy_to_use ==
+						RTE_POWER_POLICY_TRAFFIC) {
 					if (get_pfid(&policies[i]) < 0) {
 						updated = 1;
 						break;
@@ -512,7 +517,7 @@ update_policy(struct channel_packet *pkt)
 }
 
 static int
-remove_policy(struct channel_packet *pkt __rte_unused)
+remove_policy(struct rte_power_channel_packet *pkt __rte_unused)
 {
 	unsigned int i;
 
@@ -615,7 +620,7 @@ apply_time_profile(struct policy *pol)
 	/* Format the date and time, down to a single second. */
 	strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm);
 
-	for (x = 0; x < HOURS; x++) {
+	for (x = 0; x < RTE_POWER_HOURS_PER_DAY; x++) {
 
 		if (ptm->tm_hour == pol->pkt.timer_policy.busy_hours[x]) {
 			for (count = 0; count < pol->pkt.num_vcpu; count++) {
@@ -648,19 +653,19 @@ apply_workload_profile(struct policy *pol)
 
 	int count;
 
-	if (pol->pkt.workload == HIGH) {
+	if (pol->pkt.workload == RTE_POWER_WL_HIGH) {
 		for (count = 0; count < pol->pkt.num_vcpu; count++) {
 			if (pol->core_share[count].status != 1)
 				power_manager_scale_core_max(
 						pol->core_share[count].pcpu);
 		}
-	} else if (pol->pkt.workload == MEDIUM) {
+	} else if (pol->pkt.workload == RTE_POWER_WL_MEDIUM) {
 		for (count = 0; count < pol->pkt.num_vcpu; count++) {
 			if (pol->core_share[count].status != 1)
 				power_manager_scale_core_med(
 						pol->core_share[count].pcpu);
 		}
-	} else if (pol->pkt.workload == LOW) {
+	} else if (pol->pkt.workload == RTE_POWER_WL_LOW) {
 		for (count = 0; count < pol->pkt.num_vcpu; count++) {
 			if (pol->core_share[count].status != 1)
 				power_manager_scale_core_min(
@@ -673,14 +678,14 @@ static void
 apply_policy(struct policy *pol)
 {
 
-	struct channel_packet *pkt = &pol->pkt;
+	struct rte_power_channel_packet *pkt = &pol->pkt;
 
 	/*Check policy to use*/
-	if (pkt->policy_to_use == TRAFFIC)
+	if (pkt->policy_to_use == RTE_POWER_POLICY_TRAFFIC)
 		apply_traffic_profile(pol);
-	else if (pkt->policy_to_use == TIME)
+	else if (pkt->policy_to_use == RTE_POWER_POLICY_TIME)
 		apply_time_profile(pol);
-	else if (pkt->policy_to_use == WORKLOAD)
+	else if (pkt->policy_to_use == RTE_POWER_POLICY_WORKLOAD)
 		apply_workload_profile(pol);
 }
 
@@ -715,24 +720,24 @@ write_binary_packet(void *buffer,
 }
 
 static int
-send_freq(struct channel_packet *pkt,
+send_freq(struct rte_power_channel_packet *pkt,
 		struct channel_info *chan_info,
 		bool freq_list)
 {
 	unsigned int vcore_id = pkt->resource_id;
-	struct channel_packet_freq_list channel_pkt_freq_list;
+	struct rte_power_channel_packet_freq_list channel_pkt_freq_list;
 	struct vm_info info;
 
 	if (get_info_vm(pkt->vm_name, &info) != 0)
 		return -1;
 
-	if (!freq_list && vcore_id >= MAX_VCPU_PER_VM)
+	if (!freq_list && vcore_id >= RTE_POWER_MAX_VCPU_PER_VM)
 		return -1;
 
 	if (!info.allow_query)
 		return -1;
 
-	channel_pkt_freq_list.command = CPU_POWER_FREQ_LIST;
+	channel_pkt_freq_list.command = RTE_POWER_FREQ_LIST;
 	channel_pkt_freq_list.num_vcpu = info.num_vcpus;
 
 	if (freq_list) {
@@ -751,12 +756,12 @@ send_freq(struct channel_packet *pkt,
 }
 
 static int
-send_capabilities(struct channel_packet *pkt,
+send_capabilities(struct rte_power_channel_packet *pkt,
 		struct channel_info *chan_info,
 		bool list_requested)
 {
 	unsigned int vcore_id = pkt->resource_id;
-	struct channel_packet_caps_list channel_pkt_caps_list;
+	struct rte_power_channel_packet_caps_list channel_pkt_caps_list;
 	struct vm_info info;
 	struct rte_power_core_capabilities caps;
 	int ret;
@@ -764,13 +769,13 @@ send_capabilities(struct channel_packet *pkt,
 	if (get_info_vm(pkt->vm_name, &info) != 0)
 		return -1;
 
-	if (!list_requested && vcore_id >= MAX_VCPU_PER_VM)
+	if (!list_requested && vcore_id >= RTE_POWER_MAX_VCPU_PER_VM)
 		return -1;
 
 	if (!info.allow_query)
 		return -1;
 
-	channel_pkt_caps_list.command = CPU_POWER_CAPS_LIST;
+	channel_pkt_caps_list.command = RTE_POWER_CAPS_LIST;
 	channel_pkt_caps_list.num_vcpu = info.num_vcpus;
 
 	if (list_requested) {
@@ -805,18 +810,19 @@ send_capabilities(struct channel_packet *pkt,
 }
 
 static int
-send_ack_for_received_cmd(struct channel_packet *pkt,
+send_ack_for_received_cmd(struct rte_power_channel_packet *pkt,
 		struct channel_info *chan_info,
 		uint32_t command)
 {
 	pkt->command = command;
 	return write_binary_packet(pkt,
-			sizeof(struct channel_packet),
+			sizeof(*pkt),
 			chan_info);
 }
 
 static int
-process_request(struct channel_packet *pkt, struct channel_info *chan_info)
+process_request(struct rte_power_channel_packet *pkt,
+		struct channel_info *chan_info)
 {
 	int ret;
 
@@ -827,10 +833,10 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info)
 			CHANNEL_MGR_CHANNEL_PROCESSING) == 0)
 		return -1;
 
-	if (pkt->command == CPU_POWER) {
+	if (pkt->command == RTE_POWER_CPU_POWER) {
 		unsigned int core_num;
 
-		if (pkt->core_type == CORE_TYPE_VIRTUAL)
+		if (pkt->core_type == RTE_POWER_CORE_TYPE_VIRTUAL)
 			core_num = get_pcpu(chan_info, pkt->resource_id);
 		else
 			core_num = pkt->resource_id;
@@ -842,22 +848,22 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info)
 		bool valid_unit = true;
 
 		switch (pkt->unit) {
-		case(CPU_POWER_SCALE_MIN):
+		case(RTE_POWER_SCALE_MIN):
 			scale_res = power_manager_scale_core_min(core_num);
 			break;
-		case(CPU_POWER_SCALE_MAX):
+		case(RTE_POWER_SCALE_MAX):
 			scale_res = power_manager_scale_core_max(core_num);
 			break;
-		case(CPU_POWER_SCALE_DOWN):
+		case(RTE_POWER_SCALE_DOWN):
 			scale_res = power_manager_scale_core_down(core_num);
 			break;
-		case(CPU_POWER_SCALE_UP):
+		case(RTE_POWER_SCALE_UP):
 			scale_res = power_manager_scale_core_up(core_num);
 			break;
-		case(CPU_POWER_ENABLE_TURBO):
+		case(RTE_POWER_ENABLE_TURBO):
 			scale_res = power_manager_enable_turbo_core(core_num);
 			break;
-		case(CPU_POWER_DISABLE_TURBO):
+		case(RTE_POWER_DISABLE_TURBO):
 			scale_res = power_manager_disable_turbo_core(core_num);
 			break;
 		default:
@@ -868,9 +874,9 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info)
 		if (valid_unit) {
 			ret = send_ack_for_received_cmd(pkt,
 					chan_info,
-					scale_res > 0 ?
-						CPU_POWER_CMD_ACK :
-						CPU_POWER_CMD_NACK);
+					scale_res >= 0 ?
+						RTE_POWER_CMD_ACK :
+						RTE_POWER_CMD_NACK);
 			if (ret < 0)
 				RTE_LOG(ERR, CHANNEL_MONITOR, "Error during sending ack command.\n");
 		} else
@@ -878,19 +884,19 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info)
 
 	}
 
-	if (pkt->command == PKT_POLICY) {
+	if (pkt->command == RTE_POWER_PKT_POLICY) {
 		RTE_LOG(INFO, CHANNEL_MONITOR, "Processing policy request %s\n",
 				pkt->vm_name);
 		int ret = send_ack_for_received_cmd(pkt,
 				chan_info,
-				CPU_POWER_CMD_ACK);
+				RTE_POWER_CMD_ACK);
 		if (ret < 0)
 			RTE_LOG(ERR, CHANNEL_MONITOR, "Error during sending ack command.\n");
 		update_policy(pkt);
 		policy_is_set = 1;
 	}
 
-	if (pkt->command == PKT_POLICY_REMOVE) {
+	if (pkt->command == RTE_POWER_PKT_POLICY_REMOVE) {
 		ret = remove_policy(pkt);
 		if (ret == 0)
 			RTE_LOG(INFO, CHANNEL_MONITOR,
@@ -900,26 +906,26 @@ process_request(struct channel_packet *pkt, struct channel_info *chan_info)
 				 "Policy %s does not exist\n", pkt->vm_name);
 	}
 
-	if (pkt->command == CPU_POWER_QUERY_FREQ_LIST ||
-		pkt->command == CPU_POWER_QUERY_FREQ) {
+	if (pkt->command == RTE_POWER_QUERY_FREQ_LIST ||
+		pkt->command == RTE_POWER_QUERY_FREQ) {
 
 		RTE_LOG(INFO, CHANNEL_MONITOR,
 			"Frequency for %s requested.\n", pkt->vm_name);
 		int ret = send_freq(pkt,
 				chan_info,
-				pkt->command == CPU_POWER_QUERY_FREQ_LIST);
+				pkt->command == RTE_POWER_QUERY_FREQ_LIST);
 		if (ret < 0)
 			RTE_LOG(ERR, CHANNEL_MONITOR, "Error during frequency sending.\n");
 	}
 
-	if (pkt->command == CPU_POWER_QUERY_CAPS_LIST ||
-		pkt->command == CPU_POWER_QUERY_CAPS) {
+	if (pkt->command == RTE_POWER_QUERY_CAPS_LIST ||
+		pkt->command == RTE_POWER_QUERY_CAPS) {
 
 		RTE_LOG(INFO, CHANNEL_MONITOR,
 			"Capabilities for %s requested.\n", pkt->vm_name);
 		int ret = send_capabilities(pkt,
 				chan_info,
-				pkt->command == CPU_POWER_QUERY_CAPS_LIST);
+				pkt->command == RTE_POWER_QUERY_CAPS_LIST);
 		if (ret < 0)
 			RTE_LOG(ERR, CHANNEL_MONITOR, "Error during sending capabilities.\n");
 	}
@@ -988,7 +994,7 @@ channel_monitor_init(void)
 static void
 read_binary_packet(struct channel_info *chan_info)
 {
-	struct channel_packet pkt;
+	struct rte_power_channel_packet pkt;
 	void *buffer = &pkt;
 	int buffer_len = sizeof(pkt);
 	int n_bytes, err = 0;
@@ -1019,7 +1025,7 @@ read_binary_packet(struct channel_info *chan_info)
 static void
 read_json_packet(struct channel_info *chan_info)
 {
-	struct channel_packet pkt;
+	struct rte_power_channel_packet pkt;
 	int n_bytes, ret;
 	json_t *root;
 	json_error_t error;
@@ -1063,7 +1069,7 @@ read_json_packet(struct channel_info *chan_info)
 			/*
 			 * Because our data is now in the json
 			 * object, we can overwrite the pkt
-			 * with a channel_packet struct, using
+			 * with a rte_power_channel_packet struct, using
 			 * parse_json_to_pkt()
 			 */
 			ret = parse_json_to_pkt(root, &pkt, resource_name);
diff --git a/dpdk/examples/vm_power_manager/channel_monitor.h b/dpdk/examples/vm_power_manager/channel_monitor.h
index 7362a80d26..2b38c554b5 100644
--- a/dpdk/examples/vm_power_manager/channel_monitor.h
+++ b/dpdk/examples/vm_power_manager/channel_monitor.h
@@ -5,8 +5,9 @@
 #ifndef CHANNEL_MONITOR_H_
 #define CHANNEL_MONITOR_H_
 
+#include <rte_power.h>
+
 #include "channel_manager.h"
-#include "channel_commands.h"
 
 struct core_share {
 	unsigned int pcpu;
@@ -18,11 +19,11 @@ struct core_share {
 };
 
 struct policy {
-	struct channel_packet pkt;
-	uint32_t pfid[MAX_VFS];
-	uint32_t port[MAX_VFS];
+	struct rte_power_channel_packet pkt;
+	uint32_t pfid[RTE_POWER_MAX_VFS];
+	uint32_t port[RTE_POWER_MAX_VFS];
 	unsigned int enabled;
-	struct core_share core_share[MAX_VCPU_PER_VM];
+	struct core_share core_share[RTE_POWER_MAX_VCPU_PER_VM];
 };
 
 #ifdef __cplusplus
diff --git a/dpdk/examples/vm_power_manager/guest_cli/main.c b/dpdk/examples/vm_power_manager/guest_cli/main.c
index f63b3c988a..4e17f7fb90 100644
--- a/dpdk/examples/vm_power_manager/guest_cli/main.c
+++ b/dpdk/examples/vm_power_manager/guest_cli/main.c
@@ -48,10 +48,10 @@ parse_args(int argc, char **argv)
 		{ "policy", required_argument, 0, 'o'},
 		{NULL, 0, 0, 0}
 	};
-	struct channel_packet *policy;
+	struct rte_power_channel_packet *policy;
 	unsigned short int hours[MAX_HOURS];
-	unsigned short int cores[MAX_VCPU_PER_VM];
-	unsigned short int ports[MAX_VCPU_PER_VM];
+	unsigned short int cores[RTE_POWER_MAX_VCPU_PER_VM];
+	unsigned short int ports[RTE_POWER_MAX_VCPU_PER_VM];
 	int i, cnt, idx;
 
 	policy = get_policy();
@@ -69,7 +69,8 @@ parse_args(int argc, char **argv)
 		switch (opt) {
 		/* portmask */
 		case 'n':
-			strlcpy(policy->vm_name, optarg, VM_MAX_NAME_SZ);
+			strlcpy(policy->vm_name, optarg,
+					RTE_POWER_VM_MAX_NAME_SZ);
 			printf("Setting VM Name to [%s]\n", policy->vm_name);
 			break;
 		case 'b':
@@ -97,14 +98,15 @@ parse_args(int argc, char **argv)
 			}
 			break;
 		case 'l':
-			cnt = parse_set(optarg, cores, MAX_VCPU_PER_VM);
+			cnt = parse_set(optarg, cores,
+					RTE_POWER_MAX_VCPU_PER_VM);
 			if (cnt < 0) {
 				printf("Invalid value passed to vcpu-list - [%s]\n",
 						optarg);
 				break;
 			}
 			idx = 0;
-			for (i = 0; i < MAX_VCPU_PER_VM; i++) {
+			for (i = 0; i < RTE_POWER_MAX_VCPU_PER_VM; i++) {
 				if (cores[i]) {
 					printf("***Using core %d\n", i);
 					policy->vcpu_to_control[idx++] = i;
@@ -114,14 +116,15 @@ parse_args(int argc, char **argv)
 			printf("Total cores: %d\n", idx);
 			break;
 		case 'p':
-			cnt = parse_set(optarg, ports, MAX_VCPU_PER_VM);
+			cnt = parse_set(optarg, ports,
+					RTE_POWER_MAX_VCPU_PER_VM);
 			if (cnt < 0) {
 				printf("Invalid value passed to port-list - [%s]\n",
 						optarg);
 				break;
 			}
 			idx = 0;
-			for (i = 0; i < MAX_VCPU_PER_VM; i++) {
+			for (i = 0; i < RTE_POWER_MAX_VCPU_PER_VM; i++) {
 				if (ports[i]) {
 					printf("***Using port %d\n", i);
 					if (set_policy_mac(i, idx++) != 0) {
@@ -135,13 +138,17 @@ parse_args(int argc, char **argv)
 			break;
 		case 'o':
 			if (!strcmp(optarg, "TRAFFIC"))
-				policy->policy_to_use = TRAFFIC;
+				policy->policy_to_use =
+						RTE_POWER_POLICY_TRAFFIC;
 			else if (!strcmp(optarg, "TIME"))
-				policy->policy_to_use = TIME;
+				policy->policy_to_use =
+						RTE_POWER_POLICY_TIME;
 			else if (!strcmp(optarg, "WORKLOAD"))
-				policy->policy_to_use = WORKLOAD;
+				policy->policy_to_use =
+						RTE_POWER_POLICY_WORKLOAD;
 			else if (!strcmp(optarg, "BRANCH_RATIO"))
-				policy->policy_to_use = BRANCH_RATIO;
+				policy->policy_to_use =
+						RTE_POWER_POLICY_BRANCH_RATIO;
 			else {
 				printf("Invalid policy specified: %s\n",
 						optarg);
diff --git a/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c
index 96c1a1ff69..1618030627 100644
--- a/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c
+++ b/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c
@@ -19,7 +19,6 @@
 #include <rte_ethdev.h>
 
 #include <rte_power.h>
-#include <guest_channel.h>
 
 #include "vm_power_cli_guest.h"
 
@@ -38,9 +37,9 @@ union PFID {
 	uint64_t pfid;
 };
 
-static struct channel_packet policy;
+static struct rte_power_channel_packet policy;
 
-struct channel_packet *
+struct rte_power_channel_packet *
 get_policy(void)
 {
 	return &policy;
@@ -49,7 +48,7 @@ get_policy(void)
 int
 set_policy_mac(int port, int idx)
 {
-	struct channel_packet *policy;
+	struct rte_power_channel_packet *policy;
 	union PFID pfid;
 	int ret;
 
@@ -73,7 +72,7 @@ set_policy_mac(int port, int idx)
 }
 
 int
-set_policy_defaults(struct channel_packet *pkt)
+set_policy_defaults(struct rte_power_channel_packet *pkt)
 {
 	int ret;
 
@@ -103,10 +102,10 @@ set_policy_defaults(struct channel_packet *pkt)
 	pkt->timer_policy.hours_to_use_traffic_profile[0] = 8;
 	pkt->timer_policy.hours_to_use_traffic_profile[1] = 10;
 
-	pkt->core_type = CORE_TYPE_VIRTUAL;
-	pkt->workload = LOW;
-	pkt->policy_to_use = TIME;
-	pkt->command = PKT_POLICY;
+	pkt->core_type = RTE_POWER_CORE_TYPE_VIRTUAL;
+	pkt->workload = RTE_POWER_WL_LOW;
+	pkt->policy_to_use = RTE_POWER_POLICY_TIME;
+	pkt->command = RTE_POWER_PKT_POLICY;
 	strlcpy(pkt->vm_name, "ubuntu2", sizeof(pkt->vm_name));
 
 	return 0;
@@ -145,7 +144,7 @@ struct cmd_freq_list_result {
 };
 
 static int
-query_data(struct channel_packet *pkt, unsigned int lcore_id)
+query_data(struct rte_power_channel_packet *pkt, unsigned int lcore_id)
 {
 	int ret;
 	ret = rte_power_guest_channel_send_msg(pkt, lcore_id);
@@ -157,19 +156,19 @@ query_data(struct channel_packet *pkt, unsigned int lcore_id)
 }
 
 static int
-receive_freq_list(struct channel_packet_freq_list *pkt_freq_list,
+receive_freq_list(struct rte_power_channel_packet_freq_list *pkt_freq_list,
 		unsigned int lcore_id)
 {
 	int ret;
 
 	ret = rte_power_guest_channel_receive_msg(pkt_freq_list,
-			sizeof(struct channel_packet_freq_list),
+			sizeof(*pkt_freq_list),
 			lcore_id);
 	if (ret < 0) {
 		RTE_LOG(ERR, GUEST_CLI, "Error receiving message.\n");
 		return -1;
 	}
-	if (pkt_freq_list->command != CPU_POWER_FREQ_LIST) {
+	if (pkt_freq_list->command != RTE_POWER_FREQ_LIST) {
 		RTE_LOG(ERR, GUEST_CLI, "Unexpected message received.\n");
 		return -1;
 	}
@@ -183,14 +182,14 @@ cmd_query_freq_list_parsed(void *parsed_result,
 {
 	struct cmd_freq_list_result *res = parsed_result;
 	unsigned int lcore_id;
-	struct channel_packet_freq_list pkt_freq_list;
-	struct channel_packet pkt;
+	struct rte_power_channel_packet_freq_list pkt_freq_list;
+	struct rte_power_channel_packet pkt;
 	bool query_list = false;
 	int ret;
 	char *ep;
 
-	memset(&pkt, 0, sizeof(struct channel_packet));
-	memset(&pkt_freq_list, 0, sizeof(struct channel_packet_freq_list));
+	memset(&pkt, 0, sizeof(pkt));
+	memset(&pkt_freq_list, 0, sizeof(pkt_freq_list));
 
 	if (!strcmp(res->cpu_num, "all")) {
 
@@ -203,18 +202,18 @@ cmd_query_freq_list_parsed(void *parsed_result,
 			return;
 		}
 
-		pkt.command = CPU_POWER_QUERY_FREQ_LIST;
+		pkt.command = RTE_POWER_QUERY_FREQ_LIST;
 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
 		query_list = true;
 	} else {
 		errno = 0;
 		lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
-		if (errno != 0 || lcore_id >= MAX_VCPU_PER_VM ||
+		if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
 			ep == res->cpu_num) {
 			cmdline_printf(cl, "Invalid parameter provided.\n");
 			return;
 		}
-		pkt.command = CPU_POWER_QUERY_FREQ;
+		pkt.command = RTE_POWER_QUERY_FREQ;
 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
 		pkt.resource_id = lcore_id;
 	}
@@ -267,19 +266,19 @@ struct cmd_query_caps_result {
 };
 
 static int
-receive_capabilities(struct channel_packet_caps_list *pkt_caps_list,
+receive_capabilities(struct rte_power_channel_packet_caps_list *pkt_caps_list,
 		unsigned int lcore_id)
 {
 	int ret;
 
 	ret = rte_power_guest_channel_receive_msg(pkt_caps_list,
-		sizeof(struct channel_packet_caps_list),
+		sizeof(*pkt_caps_list),
 		lcore_id);
 	if (ret < 0) {
 		RTE_LOG(ERR, GUEST_CLI, "Error receiving message.\n");
 		return -1;
 	}
-	if (pkt_caps_list->command != CPU_POWER_CAPS_LIST) {
+	if (pkt_caps_list->command != RTE_POWER_CAPS_LIST) {
 		RTE_LOG(ERR, GUEST_CLI, "Unexpected message received.\n");
 		return -1;
 	}
@@ -293,14 +292,14 @@ cmd_query_caps_list_parsed(void *parsed_result,
 {
 	struct cmd_query_caps_result *res = parsed_result;
 	unsigned int lcore_id;
-	struct channel_packet_caps_list pkt_caps_list;
-	struct channel_packet pkt;
+	struct rte_power_channel_packet_caps_list pkt_caps_list;
+	struct rte_power_channel_packet pkt;
 	bool query_list = false;
 	int ret;
 	char *ep;
 
-	memset(&pkt, 0, sizeof(struct channel_packet));
-	memset(&pkt_caps_list, 0, sizeof(struct channel_packet_caps_list));
+	memset(&pkt, 0, sizeof(pkt));
+	memset(&pkt_caps_list, 0, sizeof(pkt_caps_list));
 
 	if (!strcmp(res->cpu_num, "all")) {
 
@@ -313,18 +312,18 @@ cmd_query_caps_list_parsed(void *parsed_result,
 			return;
 		}
 
-		pkt.command = CPU_POWER_QUERY_CAPS_LIST;
+		pkt.command = RTE_POWER_QUERY_CAPS_LIST;
 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
 		query_list = true;
 	} else {
 		errno = 0;
 		lcore_id = (unsigned int)strtol(res->cpu_num, &ep, 10);
-		if (errno != 0 || lcore_id >= MAX_VCPU_PER_VM ||
+		if (errno != 0 || lcore_id >= RTE_POWER_MAX_VCPU_PER_VM ||
 			ep == res->cpu_num) {
 			cmdline_printf(cl, "Invalid parameter provided.\n");
 			return;
 		}
-		pkt.command = CPU_POWER_QUERY_CAPS;
+		pkt.command = RTE_POWER_QUERY_CAPS;
 		strlcpy(pkt.vm_name, policy.vm_name, sizeof(pkt.vm_name));
 		pkt.resource_id = lcore_id;
 	}
@@ -344,13 +343,15 @@ cmd_query_caps_list_parsed(void *parsed_result,
 		unsigned int i;
 		for (i = 0; i < pkt_caps_list.num_vcpu; ++i)
 			cmdline_printf(cl, "Capabilities of [%d] vcore are:"
-					" turbo possibility: %ld, is priority core: %ld.\n",
+					" turbo possibility: %" PRId64 ", "
+					"is priority core: %" PRId64 ".\n",
 					i,
 					pkt_caps_list.turbo[i],
 					pkt_caps_list.priority[i]);
 	} else {
 		cmdline_printf(cl, "Capabilities of [%d] vcore are:"
-				" turbo possibility: %ld, is priority core: %ld.\n",
+				" turbo possibility: %" PRId64 ", "
+				"is priority core: %" PRId64 ".\n",
 				lcore_id,
 				pkt_caps_list.turbo[lcore_id],
 				pkt_caps_list.priority[lcore_id]);
@@ -378,7 +379,7 @@ cmdline_parse_inst_t cmd_query_caps_list = {
 static int
 check_response_cmd(unsigned int lcore_id, int *result)
 {
-	struct channel_packet pkt;
+	struct rte_power_channel_packet pkt;
 	int ret;
 
 	ret = rte_power_guest_channel_receive_msg(&pkt, sizeof pkt, lcore_id);
@@ -386,10 +387,10 @@ check_response_cmd(unsigned int lcore_id, int *result)
 		return -1;
 
 	switch (pkt.command) {
-	case(CPU_POWER_CMD_ACK):
+	case(RTE_POWER_CMD_ACK):
 		*result = 1;
 		break;
-	case(CPU_POWER_CMD_NACK):
+	case(RTE_POWER_CMD_NACK):
 		*result = 0;
 		break;
 	default:
@@ -471,7 +472,7 @@ struct cmd_send_policy_result {
 };
 
 static inline int
-send_policy(struct channel_packet *pkt, struct cmdline *cl)
+send_policy(struct rte_power_channel_packet *pkt, struct cmdline *cl)
 {
 	int ret;
 
diff --git a/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h b/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h
index 0c2cc1374d..50c435544e 100644
--- a/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h
+++ b/dpdk/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h
@@ -9,13 +9,11 @@
 extern "C" {
 #endif
 
-#include "channel_commands.h"
-
-struct channel_packet *get_policy(void);
+struct rte_power_channel_packet *get_policy(void);
 
 int set_policy_mac(int port, int idx);
 
-int set_policy_defaults(struct channel_packet *pkt);
+int set_policy_defaults(struct rte_power_channel_packet *pkt);
 
 void run_cli(__attribute__((unused)) void *arg);
 
diff --git a/dpdk/examples/vm_power_manager/main.c b/dpdk/examples/vm_power_manager/main.c
index d39f044c1e..2316aace5a 100644
--- a/dpdk/examples/vm_power_manager/main.c
+++ b/dpdk/examples/vm_power_manager/main.c
@@ -272,7 +272,7 @@ check_all_ports_link_status(uint32_t port_mask)
 						"Mbps - %s\n", (uint16_t)portid,
 						(unsigned int)link.link_speed,
 				(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
-					("full-duplex") : ("half-duplex\n"));
+					("full-duplex") : ("half-duplex"));
 				else
 					printf("Port %d Link Down\n",
 						(uint16_t)portid);
@@ -395,7 +395,7 @@ main(int argc, char **argv)
 					"Cannot init port %"PRIu8 "\n",
 					portid);
 
-			for (w = 0; w < MAX_VFS; w++) {
+			for (w = 0; w < RTE_POWER_MAX_VFS; w++) {
 				eth.addr_bytes[5] = w + 0xf0;
 
 				ret = -ENOTSUP;
diff --git a/dpdk/examples/vm_power_manager/meson.build b/dpdk/examples/vm_power_manager/meson.build
index 20a4a05b3b..8dd5bd2eb6 100644
--- a/dpdk/examples/vm_power_manager/meson.build
+++ b/dpdk/examples/vm_power_manager/meson.build
@@ -40,7 +40,7 @@ opt_dep = cc.find_library('virt', required : false)
 build = opt_dep.found()
 ext_deps += opt_dep
 
-opt_dep = dependency('jansson', required : false)
+opt_dep = dependency('jansson', required : false, method: 'pkg-config')
 if opt_dep.found()
 	ext_deps += opt_dep
 	cflags += '-DUSE_JANSSON'
diff --git a/dpdk/examples/vm_power_manager/power_manager.c b/dpdk/examples/vm_power_manager/power_manager.c
index 7b4f4b3c4d..cd51d4741f 100644
--- a/dpdk/examples/vm_power_manager/power_manager.c
+++ b/dpdk/examples/vm_power_manager/power_manager.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <stdint.h>
 #include <inttypes.h>
-#include <sys/un.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <dirent.h>
diff --git a/dpdk/examples/vm_power_manager/vm_power_cli.c b/dpdk/examples/vm_power_manager/vm_power_cli.c
index 5f64b83fb0..8eb87217e9 100644
--- a/dpdk/examples/vm_power_manager/vm_power_cli.c
+++ b/dpdk/examples/vm_power_manager/vm_power_cli.c
@@ -21,7 +21,6 @@
 #include "channel_manager.h"
 #include "channel_monitor.h"
 #include "power_manager.h"
-#include "channel_commands.h"
 
 struct cmd_quit_result {
 	cmdline_fixed_string_t quit;
diff --git a/dpdk/examples/vmdq/Makefile b/dpdk/examples/vmdq/Makefile
index 0767c715a1..7e59e4d658 100644
--- a/dpdk/examples/vmdq/Makefile
+++ b/dpdk/examples/vmdq/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/examples/vmdq/main.c b/dpdk/examples/vmdq/main.c
index 6e6fc91ec0..b082bc8c1c 100644
--- a/dpdk/examples/vmdq/main.c
+++ b/dpdk/examples/vmdq/main.c
@@ -59,6 +59,7 @@ static uint32_t enabled_port_mask;
 /* number of pools (if user does not specify any, 8 by default */
 static uint32_t num_queues = 8;
 static uint32_t num_pools = 8;
+static uint8_t rss_enable;
 
 /* empty vmdq configuration structure. Filled in programatically */
 static const struct rte_eth_conf vmdq_conf_default = {
@@ -143,6 +144,13 @@ get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_pools)
 	(void)(rte_memcpy(eth_conf, &vmdq_conf_default, sizeof(*eth_conf)));
 	(void)(rte_memcpy(&eth_conf->rx_adv_conf.vmdq_rx_conf, &conf,
 		   sizeof(eth_conf->rx_adv_conf.vmdq_rx_conf)));
+	if (rss_enable) {
+		eth_conf->rxmode.mq_mode = ETH_MQ_RX_VMDQ_RSS;
+		eth_conf->rx_adv_conf.rss_conf.rss_hf = ETH_RSS_IP |
+							ETH_RSS_UDP |
+							ETH_RSS_TCP |
+							ETH_RSS_SCTP;
+	}
 	return 0;
 }
 
@@ -164,6 +172,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool)
 	uint16_t q;
 	uint16_t queues_per_pool;
 	uint32_t max_nb_pools;
+	uint64_t rss_hf_tmp;
 
 	/*
 	 * The max pool number from dev_info will be used to validate the pool
@@ -209,6 +218,17 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool)
 	if (!rte_eth_dev_is_valid_port(port))
 		return -1;
 
+	rss_hf_tmp = port_conf.rx_adv_conf.rss_conf.rss_hf;
+	port_conf.rx_adv_conf.rss_conf.rss_hf &=
+		dev_info.flow_type_rss_offloads;
+	if (port_conf.rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) {
+		printf("Port %u modified RSS hash function based on hardware support,"
+			"requested:%#"PRIx64" configured:%#"PRIx64"\n",
+			port,
+			rss_hf_tmp,
+			port_conf.rx_adv_conf.rss_conf.rss_hf);
+	}
+
 	/*
 	 * Though in this example, we only receive packets from the first queue
 	 * of each pool and send packets through first rte_lcore_count() tx
@@ -363,7 +383,8 @@ static void
 vmdq_usage(const char *prgname)
 {
 	printf("%s [EAL options] -- -p PORTMASK]\n"
-	"  --nb-pools NP: number of pools\n",
+	"  --nb-pools NP: number of pools\n"
+	"  --enable-rss: enable RSS (disabled by default)\n",
 	       prgname);
 }
 
@@ -377,6 +398,7 @@ vmdq_parse_args(int argc, char **argv)
 	const char *prgname = argv[0];
 	static struct option long_option[] = {
 		{"nb-pools", required_argument, NULL, 0},
+		{"enable-rss", 0, NULL, 0},
 		{NULL, 0, 0, 0}
 	};
 
@@ -394,11 +416,18 @@ vmdq_parse_args(int argc, char **argv)
 			}
 			break;
 		case 0:
-			if (vmdq_parse_num_pools(optarg) == -1) {
-				printf("invalid number of pools\n");
-				vmdq_usage(prgname);
-				return -1;
+			if (!strcmp(long_option[option_index].name,
+			    "nb-pools")) {
+				if (vmdq_parse_num_pools(optarg) == -1) {
+					printf("invalid number of pools\n");
+					vmdq_usage(prgname);
+					return -1;
+				}
 			}
+
+			if (!strcmp(long_option[option_index].name,
+			    "enable-rss"))
+				rss_enable = 1;
 			break;
 
 		default:
@@ -441,10 +470,11 @@ update_mac_address(struct rte_mbuf *m, unsigned dst_port)
 static void
 sighup_handler(int signum)
 {
-	unsigned q;
-	for (q = 0; q < num_queues; q++) {
-		if (q % (num_queues/num_pools) == 0)
-			printf("\nPool %u: ", q/(num_queues/num_pools));
+	unsigned int q = vmdq_queue_base;
+	for (; q < num_queues; q++) {
+		if ((q - vmdq_queue_base) % (num_vmdq_queues / num_pools) == 0)
+			printf("\nPool %u: ", (q - vmdq_queue_base) /
+			       (num_vmdq_queues / num_pools));
 		printf("%lu ", rxPackets[q]);
 	}
 	printf("\nFinished handling signal %d\n", signum);
diff --git a/dpdk/examples/vmdq_dcb/Makefile b/dpdk/examples/vmdq_dcb/Makefile
index 2a9b04143f..2302577d00 100644
--- a/dpdk/examples/vmdq_dcb/Makefile
+++ b/dpdk/examples/vmdq_dcb/Makefile
@@ -22,7 +22,7 @@ PKGCONF ?= pkg-config
 PC_FILE := $(shell $(PKGCONF) --path libdpdk 2>/dev/null)
 CFLAGS += -O3 $(shell $(PKGCONF) --cflags libdpdk)
 LDFLAGS_SHARED = $(shell $(PKGCONF) --libs libdpdk)
-LDFLAGS_STATIC = -Wl,-Bstatic $(shell $(PKGCONF) --static --libs libdpdk)
+LDFLAGS_STATIC = $(shell $(PKGCONF) --static --libs libdpdk)
 
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
 	$(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
diff --git a/dpdk/kernel/freebsd/contigmem/contigmem.c b/dpdk/kernel/freebsd/contigmem/contigmem.c
index 64e0a7fecd..abb76f241e 100644
--- a/dpdk/kernel/freebsd/contigmem/contigmem.c
+++ b/dpdk/kernel/freebsd/contigmem/contigmem.c
@@ -165,9 +165,11 @@ contigmem_load()
 
 error:
 	for (i = 0; i < contigmem_num_buffers; i++) {
-		if (contigmem_buffers[i].addr != NULL)
+		if (contigmem_buffers[i].addr != NULL) {
 			contigfree(contigmem_buffers[i].addr,
 				contigmem_buffer_size, M_CONTIGMEM);
+			contigmem_buffers[i].addr = NULL;
+		}
 		if (mtx_initialized(&contigmem_buffers[i].mtx))
 			mtx_destroy(&contigmem_buffers[i].mtx);
 	}
diff --git a/dpdk/kernel/linux/kni/compat.h b/dpdk/kernel/linux/kni/compat.h
index 7109474ec5..5f65640d5e 100644
--- a/dpdk/kernel/linux/kni/compat.h
+++ b/dpdk/kernel/linux/kni/compat.h
@@ -130,3 +130,13 @@
 #if KERNEL_VERSION(4, 10, 0) <= LINUX_VERSION_CODE
 #define HAVE_IOVA_TO_KVA_MAPPING_SUPPORT
 #endif
+
+#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE || \
+	(defined(RHEL_RELEASE_CODE) && \
+	 RHEL_RELEASE_VERSION(8, 3) <= RHEL_RELEASE_CODE)
+#define HAVE_TX_TIMEOUT_TXQUEUE
+#endif
+
+#if KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE
+#define HAVE_TSK_IN_GUP
+#endif
diff --git a/dpdk/kernel/linux/kni/kni_dev.h b/dpdk/kernel/linux/kni/kni_dev.h
index 5e75c6371f..c15da311ba 100644
--- a/dpdk/kernel/linux/kni/kni_dev.h
+++ b/dpdk/kernel/linux/kni/kni_dev.h
@@ -32,7 +32,7 @@
 #define MBUF_BURST_SZ 32
 
 /* Default carrier state for created KNI network interfaces */
-extern uint32_t dflt_carrier;
+extern uint32_t kni_dflt_carrier;
 
 /**
  * A structure describing the private information for a kni device.
@@ -101,8 +101,13 @@ static inline phys_addr_t iova_to_phys(struct task_struct *tsk,
 	offset = iova & (PAGE_SIZE - 1);
 
 	/* Read one page struct info */
+#ifdef HAVE_TSK_IN_GUP
 	ret = get_user_pages_remote(tsk, tsk->mm, iova, 1,
 				    FOLL_TOUCH, &page, NULL, NULL);
+#else
+	ret = get_user_pages_remote(tsk->mm, iova, 1,
+				    FOLL_TOUCH, &page, NULL, NULL);
+#endif
 	if (ret < 0)
 		return 0;
 
diff --git a/dpdk/kernel/linux/kni/kni_misc.c b/dpdk/kernel/linux/kni/kni_misc.c
index cda71bde08..2b464c4381 100644
--- a/dpdk/kernel/linux/kni/kni_misc.c
+++ b/dpdk/kernel/linux/kni/kni_misc.c
@@ -39,7 +39,7 @@ static uint32_t multiple_kthread_on;
 
 /* Default carrier state for created KNI network interfaces */
 static char *carrier;
-uint32_t dflt_carrier;
+uint32_t kni_dflt_carrier;
 
 #define KNI_DEV_IN_USE_BIT_NUM 0 /* Bit number for device in use */
 
@@ -554,14 +554,14 @@ static int __init
 kni_parse_carrier_state(void)
 {
 	if (!carrier) {
-		dflt_carrier = 0;
+		kni_dflt_carrier = 0;
 		return 0;
 	}
 
 	if (strcmp(carrier, "off") == 0)
-		dflt_carrier = 0;
+		kni_dflt_carrier = 0;
 	else if (strcmp(carrier, "on") == 0)
-		dflt_carrier = 1;
+		kni_dflt_carrier = 1;
 	else
 		return -1;
 
@@ -588,7 +588,7 @@ kni_init(void)
 		return -EINVAL;
 	}
 
-	if (dflt_carrier == 0)
+	if (kni_dflt_carrier == 0)
 		pr_debug("Default carrier state set to off.\n");
 	else
 		pr_debug("Default carrier state set to on.\n");
diff --git a/dpdk/kernel/linux/kni/kni_net.c b/dpdk/kernel/linux/kni/kni_net.c
index 1ba9b1b99f..c82c881a2c 100644
--- a/dpdk/kernel/linux/kni/kni_net.c
+++ b/dpdk/kernel/linux/kni/kni_net.c
@@ -158,7 +158,7 @@ kni_net_open(struct net_device *dev)
 	struct kni_dev *kni = netdev_priv(dev);
 
 	netif_start_queue(dev);
-	if (dflt_carrier == 1)
+	if (kni_dflt_carrier == 1)
 		netif_carrier_on(dev);
 	else
 		netif_carrier_off(dev);
@@ -623,8 +623,13 @@ kni_net_rx(struct kni_dev *kni)
 /*
  * Deal with a transmit timeout.
  */
+#ifdef HAVE_TX_TIMEOUT_TXQUEUE
+static void
+kni_net_tx_timeout(struct net_device *dev, unsigned int txqueue)
+#else
 static void
 kni_net_tx_timeout(struct net_device *dev)
+#endif
 {
 	pr_debug("Transmit timeout at %ld, latency %ld\n", jiffies,
 			jiffies - dev_trans_start(dev));
diff --git a/dpdk/kernel/linux/kni/meson.build b/dpdk/kernel/linux/kni/meson.build
index 955eec9496..f93e97fa09 100644
--- a/dpdk/kernel/linux/kni/meson.build
+++ b/dpdk/kernel/linux/kni/meson.build
@@ -23,7 +23,6 @@ custom_target('rte_kni',
 		' -I' + meson.current_source_dir(),
 		'modules'],
 	depends: kni_mkfile,
-	console: true,
 	install: true,
 	install_dir: kernel_dir + '/extra/dpdk',
 	build_by_default: get_option('enable_kmods'))
diff --git a/dpdk/lib/Makefile b/dpdk/lib/Makefile
index 46b91ae1a4..2cbb096f12 100644
--- a/dpdk/lib/Makefile
+++ b/dpdk/lib/Makefile
@@ -113,7 +113,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_BPF) += librte_bpf
 DEPDIRS-librte_bpf := librte_eal librte_mempool librte_mbuf librte_ethdev
 DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += librte_ipsec
 DEPDIRS-librte_ipsec := librte_eal librte_mbuf librte_cryptodev librte_security \
-			librte_net
+			librte_net librte_hash
 DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry
 DEPDIRS-librte_telemetry := librte_eal librte_metrics librte_ethdev
 DIRS-$(CONFIG_RTE_LIBRTE_RCU) += librte_rcu
diff --git a/dpdk/lib/librte_acl/acl_bld.c b/dpdk/lib/librte_acl/acl_bld.c
index b06bbe9207..d1f920b09c 100644
--- a/dpdk/lib/librte_acl/acl_bld.c
+++ b/dpdk/lib/librte_acl/acl_bld.c
@@ -778,9 +778,8 @@ acl_build_reset(struct rte_acl_ctx *ctx)
 }
 
 static void
-acl_gen_range(struct acl_build_context *context,
-	const uint8_t *hi, const uint8_t *lo, int size, int level,
-	struct rte_acl_node *root, struct rte_acl_node *end)
+acl_gen_full_range(struct acl_build_context *context, struct rte_acl_node *root,
+	struct rte_acl_node *end, int size, int level)
 {
 	struct rte_acl_node *node, *prev;
 	uint32_t n;
@@ -788,10 +787,71 @@ acl_gen_range(struct acl_build_context *context,
 	prev = root;
 	for (n = size - 1; n > 0; n--) {
 		node = acl_alloc_node(context, level++);
-		acl_add_ptr_range(context, prev, node, lo[n], hi[n]);
+		acl_add_ptr_range(context, prev, node, 0, UINT8_MAX);
 		prev = node;
 	}
-	acl_add_ptr_range(context, prev, end, lo[0], hi[0]);
+	acl_add_ptr_range(context, prev, end, 0, UINT8_MAX);
+}
+
+static void
+acl_gen_range_mdl(struct acl_build_context *context, struct rte_acl_node *root,
+	struct rte_acl_node *end, uint8_t lo, uint8_t hi, int size, int level)
+{
+	struct rte_acl_node *node;
+
+	node = acl_alloc_node(context, level++);
+	acl_add_ptr_range(context, root, node, lo, hi);
+	acl_gen_full_range(context, node, end, size - 1, level);
+}
+
+static void
+acl_gen_range_low(struct acl_build_context *context, struct rte_acl_node *root,
+	struct rte_acl_node *end, const uint8_t *lo, int size, int level)
+{
+	struct rte_acl_node *node;
+	uint32_t n;
+
+	n = size - 1;
+	if (n == 0) {
+		acl_add_ptr_range(context, root, end, lo[0], UINT8_MAX);
+		return;
+	}
+
+	node = acl_alloc_node(context, level++);
+	acl_add_ptr_range(context, root, node, lo[n], lo[n]);
+
+	/* generate lower-bound sub-trie */
+	acl_gen_range_low(context, node, end, lo, n, level);
+
+	/* generate middle sub-trie */
+	if (n > 1 && lo[n - 1] != UINT8_MAX)
+		acl_gen_range_mdl(context, node, end, lo[n - 1] + 1, UINT8_MAX,
+			n, level);
+}
+
+static void
+acl_gen_range_high(struct acl_build_context *context, struct rte_acl_node *root,
+	struct rte_acl_node *end, const uint8_t *hi, int size, int level)
+{
+	struct rte_acl_node *node;
+	uint32_t n;
+
+	n = size - 1;
+	if (n == 0) {
+		acl_add_ptr_range(context, root, end, 0, hi[0]);
+		return;
+	}
+
+	node = acl_alloc_node(context, level++);
+	acl_add_ptr_range(context, root, node, hi[n], hi[n]);
+
+	/* generate upper-bound sub-trie */
+	acl_gen_range_high(context, node, end, hi, n, level);
+
+	/* generate middle sub-trie */
+	if (n > 1 && hi[n - 1] != 0)
+		acl_gen_range_mdl(context, node, end, 0, hi[n - 1] - 1,
+			n, level);
 }
 
 static struct rte_acl_node *
@@ -799,52 +859,56 @@ acl_gen_range_trie(struct acl_build_context *context,
 	const void *min, const void *max,
 	int size, int level, struct rte_acl_node **pend)
 {
-	int32_t n;
-	struct rte_acl_node *root;
-	const uint8_t *lo = min;
-	const uint8_t *hi = max;
+	int32_t k, n;
+	uint8_t hi_ff, lo_00;
+	struct rte_acl_node *node, *prev, *root;
+	const uint8_t *lo;
+	const uint8_t *hi;
+
+	lo = min;
+	hi = max;
 
-	*pend = acl_alloc_node(context, level+size);
+	*pend = acl_alloc_node(context, level + size);
 	root = acl_alloc_node(context, level++);
+	prev = root;
 
-	if (lo[size - 1] == hi[size - 1]) {
-		acl_gen_range(context, hi, lo, size, level, root, *pend);
-	} else {
-		uint8_t limit_lo[64];
-		uint8_t limit_hi[64];
-		uint8_t hi_ff = UINT8_MAX;
-		uint8_t lo_00 = 0;
+	/* build common sub-trie till possible */
+	for (n = size - 1; n > 0 && lo[n] == hi[n]; n--) {
+		node = acl_alloc_node(context, level++);
+		acl_add_ptr_range(context, prev, node, lo[n], hi[n]);
+		prev = node;
+	}
 
-		memset(limit_lo, 0, RTE_DIM(limit_lo));
-		memset(limit_hi, UINT8_MAX, RTE_DIM(limit_hi));
+	/* no branch needed, just one sub-trie */
+	if (n == 0) {
+		acl_add_ptr_range(context, prev, *pend, lo[0], hi[0]);
+		return root;
+	}
 
-		for (n = size - 2; n >= 0; n--) {
-			hi_ff = (uint8_t)(hi_ff & hi[n]);
-			lo_00 = (uint8_t)(lo_00 | lo[n]);
-		}
+	/* gather information about divirgent paths */
+	lo_00 = 0;
+	hi_ff = UINT8_MAX;
+	for (k = n - 1; k >= 0; k--) {
+		hi_ff &= hi[k];
+		lo_00 |= lo[k];
+	}
 
-		if (hi_ff != UINT8_MAX) {
-			limit_lo[size - 1] = hi[size - 1];
-			acl_gen_range(context, hi, limit_lo, size, level,
-				root, *pend);
-		}
+	/* generate left (lower-bound) sub-trie */
+	if (lo_00 != 0)
+		acl_gen_range_low(context, prev, *pend, lo, n + 1, level);
 
-		if (lo_00 != 0) {
-			limit_hi[size - 1] = lo[size - 1];
-			acl_gen_range(context, limit_hi, lo, size, level,
-				root, *pend);
-		}
+	/* generate right (upper-bound) sub-trie */
+	if (hi_ff != UINT8_MAX)
+		acl_gen_range_high(context, prev, *pend, hi, n + 1, level);
 
-		if (hi[size - 1] - lo[size - 1] > 1 ||
-				lo_00 == 0 ||
-				hi_ff == UINT8_MAX) {
-			limit_lo[size-1] = (uint8_t)(lo[size-1] + (lo_00 != 0));
-			limit_hi[size-1] = (uint8_t)(hi[size-1] -
-				(hi_ff != UINT8_MAX));
-			acl_gen_range(context, limit_hi, limit_lo, size,
-				level, root, *pend);
-		}
+	/* generate sub-trie in the middle */
+	if (lo[n] + 1 != hi[n] || lo_00 == 0 || hi_ff == UINT8_MAX) {
+		lo_00 = lo[n] + (lo_00 != 0);
+		hi_ff = hi[n] - (hi_ff != UINT8_MAX);
+		acl_gen_range_mdl(context, prev, *pend, lo_00, hi_ff,
+			n + 1, level);
 	}
+
 	return root;
 }
 
diff --git a/dpdk/lib/librte_acl/rte_acl.c b/dpdk/lib/librte_acl/rte_acl.c
index 777ec4d340..715b023592 100644
--- a/dpdk/lib/librte_acl/rte_acl.c
+++ b/dpdk/lib/librte_acl/rte_acl.c
@@ -16,7 +16,6 @@ static struct rte_tailq_elem rte_acl_tailq = {
 };
 EAL_REGISTER_TAILQ(rte_acl_tailq)
 
-#ifndef RTE_ARCH_X86
 #ifndef CC_AVX2_SUPPORT
 /*
  * If the compiler doesn't support AVX2 instructions,
@@ -33,6 +32,7 @@ rte_acl_classify_avx2(__rte_unused const struct rte_acl_ctx *ctx,
 }
 #endif
 
+#ifndef RTE_ARCH_X86
 int
 rte_acl_classify_sse(__rte_unused const struct rte_acl_ctx *ctx,
 	__rte_unused const uint8_t **data,
diff --git a/dpdk/lib/librte_bbdev/rte_bbdev.h b/dpdk/lib/librte_bbdev/rte_bbdev.h
index 591fb7914a..6fcf448262 100644
--- a/dpdk/lib/librte_bbdev/rte_bbdev.h
+++ b/dpdk/lib/librte_bbdev/rte_bbdev.h
@@ -11,7 +11,8 @@
  * Wireless base band device abstraction APIs.
  *
  * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
  *
  * This API allows an application to discover, configure and use a device to
  * process operations. An asynchronous API (enqueue, followed by later dequeue)
@@ -440,21 +441,21 @@ TAILQ_HEAD(rte_bbdev_cb_list, rte_bbdev_callback);
  * these fields, but should only write to the *_ops fields.
  */
 struct __rte_cache_aligned rte_bbdev {
-	/**< Enqueue encode function */
+	/** Enqueue encode function */
 	rte_bbdev_enqueue_enc_ops_t enqueue_enc_ops;
-	/**< Enqueue decode function */
+	/** Enqueue decode function */
 	rte_bbdev_enqueue_dec_ops_t enqueue_dec_ops;
-	/**< Dequeue encode function */
+	/** Dequeue encode function */
 	rte_bbdev_dequeue_enc_ops_t dequeue_enc_ops;
-	/**< Dequeue decode function */
+	/** Dequeue decode function */
 	rte_bbdev_dequeue_dec_ops_t dequeue_dec_ops;
-	/**< Enqueue encode function */
+	/** Enqueue encode function */
 	rte_bbdev_enqueue_enc_ops_t enqueue_ldpc_enc_ops;
-	/**< Enqueue decode function */
+	/** Enqueue decode function */
 	rte_bbdev_enqueue_dec_ops_t enqueue_ldpc_dec_ops;
-	/**< Dequeue encode function */
+	/** Dequeue encode function */
 	rte_bbdev_dequeue_enc_ops_t dequeue_ldpc_enc_ops;
-	/**< Dequeue decode function */
+	/** Dequeue decode function */
 	rte_bbdev_dequeue_dec_ops_t dequeue_ldpc_dec_ops;
 	const struct rte_bbdev_ops *dev_ops;  /**< Functions exported by PMD */
 	struct rte_bbdev_data *data;  /**< Pointer to device data */
diff --git a/dpdk/lib/librte_bbdev/rte_bbdev_op.h b/dpdk/lib/librte_bbdev/rte_bbdev_op.h
index 1e119a757b..6e43495fb4 100644
--- a/dpdk/lib/librte_bbdev/rte_bbdev_op.h
+++ b/dpdk/lib/librte_bbdev/rte_bbdev_op.h
@@ -389,12 +389,12 @@ struct rte_bbdev_op_turbo_dec {
 	 */
 	uint8_t num_maps;
 
-	/**< [0 - TB : 1 - CB] */
+	/** [0 - TB : 1 - CB] */
 	uint8_t code_block_mode;
 	union {
-		/**< Struct which stores Code Block specific parameters */
+		/** Struct which stores Code Block specific parameters */
 		struct rte_bbdev_op_dec_turbo_cb_params cb_params;
-		/**< Struct which stores Transport Block specific parameters */
+		/** Struct which stores Transport Block specific parameters */
 		struct rte_bbdev_op_dec_turbo_tb_params tb_params;
 	};
 };
@@ -545,7 +545,7 @@ struct rte_bbdev_op_enc_turbo_tb_params {
 	 * the Turbo operation when r >= C-, [K:3*Kpi]
 	 */
 	uint16_t ncb_pos;
-	/**< The index of the first CB in the inbound mbuf data, default is 0 */
+	/** The index of the first CB in the inbound mbuf data, default is 0 */
 	uint8_t r;
 };
 
@@ -744,11 +744,11 @@ enum {
 
 /** Structure specifying a single encode operation */
 struct rte_bbdev_enc_op {
-	/**< Status of operation that was performed */
+	/** Status of operation that was performed */
 	int status;
-	/**< Mempool which op instance is in */
+	/** Mempool which op instance is in */
 	struct rte_mempool *mempool;
-	/**< Opaque pointer for user data */
+	/** Opaque pointer for user data */
 	void *opaque_data;
 	union {
 		/** Contains turbo decoder specific parameters */
@@ -785,7 +785,7 @@ struct rte_bbdev_op_cap {
 	} cap;  /**< Operation-type specific capabilities */
 };
 
-/**< @internal Private data structure stored with operation pool. */
+/** @internal Private data structure stored with operation pool. */
 struct rte_bbdev_op_pool_private {
 	enum rte_bbdev_op_type type;  /**< Type of operations in a pool */
 };
diff --git a/dpdk/lib/librte_bbdev/rte_bbdev_pmd.h b/dpdk/lib/librte_bbdev/rte_bbdev_pmd.h
index 24ddcee7af..237e3361d7 100644
--- a/dpdk/lib/librte_bbdev/rte_bbdev_pmd.h
+++ b/dpdk/lib/librte_bbdev/rte_bbdev_pmd.h
@@ -146,18 +146,18 @@ typedef int (*rte_bbdev_queue_intr_disable_t)(struct rte_bbdev *dev,
  * fields are for non-vital operations
  */
 struct rte_bbdev_ops {
-	/**< Allocate and configure device memory. Optional. */
+	/** Allocate and configure device memory. Optional. */
 	rte_bbdev_setup_queues_t setup_queues;
-	/**< Configure interrupts. Optional. */
+	/** Configure interrupts. Optional. */
 	rte_bbdev_intr_enable_t intr_enable;
-	/**< Start device. Optional. */
+	/** Start device. Optional. */
 	rte_bbdev_start_t start;
-	/**< Stop device. Optional. */
+	/** Stop device. Optional. */
 	rte_bbdev_stop_t stop;
-	/**< Close device. Optional. */
+	/** Close device. Optional. */
 	rte_bbdev_close_t close;
 
-	/**< Get device info. Required. */
+	/** Get device info. Required. */
 	rte_bbdev_info_get_t info_get;
 	/** Get device statistics. Optional. */
 	rte_bbdev_stats_get_t stats_get;
@@ -170,7 +170,7 @@ struct rte_bbdev_ops {
 	rte_bbdev_queue_release_t queue_release;
 	/** Start a queue. Optional. */
 	rte_bbdev_queue_start_t queue_start;
-	/**< Stop a queue pair. Optional. */
+	/** Stop a queue pair. Optional. */
 	rte_bbdev_queue_stop_t queue_stop;
 
 	/** Enable queue interrupt. Optional */
diff --git a/dpdk/lib/librte_bpf/bpf_validate.c b/dpdk/lib/librte_bpf/bpf_validate.c
index 6bd6f78e9b..80d21fabbe 100644
--- a/dpdk/lib/librte_bpf/bpf_validate.c
+++ b/dpdk/lib/librte_bpf/bpf_validate.c
@@ -226,7 +226,7 @@ eval_add(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, uint64_t msk)
 	struct bpf_reg_val rv;
 
 	rv.u.min = (rd->u.min + rs->u.min) & msk;
-	rv.u.max = (rd->u.min + rs->u.max) & msk;
+	rv.u.max = (rd->u.max + rs->u.max) & msk;
 	rv.s.min = (rd->s.min + rs->s.min) & msk;
 	rv.s.max = (rd->s.max + rs->s.max) & msk;
 
@@ -254,10 +254,10 @@ eval_sub(struct bpf_reg_val *rd, const struct bpf_reg_val *rs, uint64_t msk)
 {
 	struct bpf_reg_val rv;
 
-	rv.u.min = (rd->u.min - rs->u.min) & msk;
-	rv.u.max = (rd->u.min - rs->u.max) & msk;
-	rv.s.min = (rd->s.min - rs->s.min) & msk;
-	rv.s.max = (rd->s.max - rs->s.max) & msk;
+	rv.u.min = (rd->u.min - rs->u.max) & msk;
+	rv.u.max = (rd->u.max - rs->u.min) & msk;
+	rv.s.min = (rd->s.min - rs->s.max) & msk;
+	rv.s.max = (rd->s.max - rs->s.min) & msk;
 
 	/*
 	 * if at least one of the operands is not constant,
diff --git a/dpdk/lib/librte_bpf/meson.build b/dpdk/lib/librte_bpf/meson.build
index 13fc02db38..76e00e9fd4 100644
--- a/dpdk/lib/librte_bpf/meson.build
+++ b/dpdk/lib/librte_bpf/meson.build
@@ -14,13 +14,13 @@ elif dpdk_conf.has('RTE_ARCH_ARM64')
 	sources += files('bpf_jit_arm64.c')
 endif
 
-install_headers = files('bpf_def.h',
+install_headers('bpf_def.h',
 			'rte_bpf.h',
 			'rte_bpf_ethdev.h')
 
 deps += ['mbuf', 'net', 'ethdev']
 
-dep = dependency('libelf', required: false)
+dep = dependency('libelf', required: false, method: 'pkg-config')
 if dep.found()
 	dpdk_conf.set('RTE_LIBRTE_BPF_ELF', 1)
 	sources += files('bpf_load_elf.c')
diff --git a/dpdk/lib/librte_bpf/rte_bpf.h b/dpdk/lib/librte_bpf/rte_bpf.h
index cbf1cddaca..e2d419b4ef 100644
--- a/dpdk/lib/librte_bpf/rte_bpf.h
+++ b/dpdk/lib/librte_bpf/rte_bpf.h
@@ -7,9 +7,13 @@
 
 /**
  * @file rte_bpf.h
- * @b EXPERIMENTAL: this API may change without prior notice
  *
  * RTE BPF support.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
  * librte_bpf provides a framework to load and execute eBPF bytecode
  * inside user-space dpdk based applications.
  * It supports basic set of features from eBPF spec
diff --git a/dpdk/lib/librte_cfgfile/rte_cfgfile.c b/dpdk/lib/librte_cfgfile/rte_cfgfile.c
index 9049fd9c23..0c419d6adc 100644
--- a/dpdk/lib/librte_cfgfile/rte_cfgfile.c
+++ b/dpdk/lib/librte_cfgfile/rte_cfgfile.c
@@ -191,7 +191,8 @@ rte_cfgfile_load_with_params(const char *filename, int flags,
 		}
 		/* skip parsing if comment character found */
 		pos = memchr(buffer, params->comment_character, len);
-		if (pos != NULL && (*(pos-1) != '\\')) {
+		if (pos != NULL &&
+		    (pos == buffer || *(pos-1) != '\\')) {
 			*pos = '\0';
 			len = pos -  buffer;
 		}
diff --git a/dpdk/lib/librte_cfgfile/rte_cfgfile_version.map b/dpdk/lib/librte_cfgfile/rte_cfgfile_version.map
index 906eee96bf..22c999fe16 100644
--- a/dpdk/lib/librte_cfgfile/rte_cfgfile_version.map
+++ b/dpdk/lib/librte_cfgfile/rte_cfgfile_version.map
@@ -15,6 +15,7 @@ DPDK_20.0 {
 	rte_cfgfile_section_entries;
 	rte_cfgfile_section_entries_by_index;
 	rte_cfgfile_section_num_entries;
+	rte_cfgfile_section_num_entries_by_index;
 	rte_cfgfile_sections;
 	rte_cfgfile_set_entry;
 
diff --git a/dpdk/lib/librte_compressdev/rte_compressdev.h b/dpdk/lib/librte_compressdev/rte_compressdev.h
index 8052efe675..2840c27c6c 100644
--- a/dpdk/lib/librte_compressdev/rte_compressdev.h
+++ b/dpdk/lib/librte_compressdev/rte_compressdev.h
@@ -8,7 +8,11 @@
 /**
  * @file rte_compressdev.h
  *
- * RTE Compression Device APIs
+ * RTE Compression Device APIs.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
  *
  * Defines comp device APIs for the provisioning of compression operations.
  */
diff --git a/dpdk/lib/librte_cryptodev/rte_crypto_sym.h b/dpdk/lib/librte_cryptodev/rte_crypto_sym.h
index ffa038dc40..4e05c7c6ac 100644
--- a/dpdk/lib/librte_cryptodev/rte_crypto_sym.h
+++ b/dpdk/lib/librte_cryptodev/rte_crypto_sym.h
@@ -208,9 +208,12 @@ enum rte_crypto_auth_algorithm {
 	/**< HMAC using MD5 algorithm */
 
 	RTE_CRYPTO_AUTH_SHA1,
-	/**< 128 bit SHA algorithm. */
+	/**< 160 bit SHA algorithm. */
 	RTE_CRYPTO_AUTH_SHA1_HMAC,
-	/**< HMAC using 128 bit SHA algorithm. */
+	/**< HMAC using 160 bit SHA algorithm.
+	 * HMAC-SHA-1-96 can be generated by setting
+	 * digest_length to 12 bytes in auth/aead xforms.
+	 */
 	RTE_CRYPTO_AUTH_SHA224,
 	/**< 224 bit SHA algorithm. */
 	RTE_CRYPTO_AUTH_SHA224_HMAC,
diff --git a/dpdk/lib/librte_cryptodev/rte_cryptodev.c b/dpdk/lib/librte_cryptodev/rte_cryptodev.c
index 89aa2ed3e2..ed9de3eb92 100644
--- a/dpdk/lib/librte_cryptodev/rte_cryptodev.c
+++ b/dpdk/lib/librte_cryptodev/rte_cryptodev.c
@@ -491,6 +491,8 @@ rte_cryptodev_get_feature_name(uint64_t flag)
 		return "RSA_PRIV_OP_KEY_QT";
 	case RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED:
 		return "DIGEST_ENCRYPTED";
+	case RTE_CRYPTODEV_FF_ASYM_SESSIONLESS:
+		return "ASYM_SESSIONLESS";
 	default:
 		return NULL;
 	}
@@ -525,7 +527,8 @@ rte_cryptodev_pmd_get_named_dev(const char *name)
 static inline uint8_t
 rte_cryptodev_is_valid_device_data(uint8_t dev_id)
 {
-	if (rte_crypto_devices[dev_id].data == NULL)
+	if (dev_id >= RTE_CRYPTO_MAX_DEVS ||
+			rte_crypto_devices[dev_id].data == NULL)
 		return 0;
 
 	return 1;
@@ -617,8 +620,9 @@ rte_cryptodev_devices_get(const char *driver_name, uint8_t *devices,
 void *
 rte_cryptodev_get_sec_ctx(uint8_t dev_id)
 {
-	if (rte_crypto_devices[dev_id].feature_flags &
-			RTE_CRYPTODEV_FF_SECURITY)
+	if (dev_id < RTE_CRYPTO_MAX_DEVS &&
+			(rte_crypto_devices[dev_id].feature_flags &
+			RTE_CRYPTODEV_FF_SECURITY))
 		return rte_crypto_devices[dev_id].security_ctx;
 
 	return NULL;
@@ -789,6 +793,11 @@ rte_cryptodev_queue_pair_count(uint8_t dev_id)
 {
 	struct rte_cryptodev *dev;
 
+	if (!rte_cryptodev_is_valid_device_data(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
+		return 0;
+	}
+
 	dev = &rte_crypto_devices[dev_id];
 	return dev->data->nb_queue_pairs;
 }
@@ -1254,6 +1263,11 @@ rte_cryptodev_sym_session_init(uint8_t dev_id,
 	uint8_t index;
 	int ret;
 
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
+		return -EINVAL;
+	}
+
 	dev = rte_cryptodev_pmd_get_dev(dev_id);
 
 	if (sess == NULL || xforms == NULL || dev == NULL)
@@ -1293,6 +1307,11 @@ rte_cryptodev_asym_session_init(uint8_t dev_id,
 	uint8_t index;
 	int ret;
 
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
+		return -EINVAL;
+	}
+
 	dev = rte_cryptodev_pmd_get_dev(dev_id);
 
 	if (sess == NULL || xforms == NULL || dev == NULL)
@@ -1428,6 +1447,11 @@ rte_cryptodev_sym_session_clear(uint8_t dev_id,
 	struct rte_cryptodev *dev;
 	uint8_t driver_id;
 
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
+		return -EINVAL;
+	}
+
 	dev = rte_cryptodev_pmd_get_dev(dev_id);
 
 	if (dev == NULL || sess == NULL)
@@ -1452,6 +1476,11 @@ rte_cryptodev_asym_session_clear(uint8_t dev_id,
 {
 	struct rte_cryptodev *dev;
 
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
+		return -EINVAL;
+	}
+
 	dev = rte_cryptodev_pmd_get_dev(dev_id);
 
 	if (dev == NULL || sess == NULL)
@@ -1754,8 +1783,14 @@ rte_cryptodev_driver_id_get(const char *name)
 const char *
 rte_cryptodev_name_get(uint8_t dev_id)
 {
-	struct rte_cryptodev *dev = rte_cryptodev_pmd_get_dev(dev_id);
+	struct rte_cryptodev *dev;
 
+	if (!rte_cryptodev_is_valid_device_data(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%" PRIu8, dev_id);
+		return NULL;
+	}
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
 	if (dev == NULL)
 		return NULL;
 
diff --git a/dpdk/lib/librte_cryptodev/rte_cryptodev_pmd.h b/dpdk/lib/librte_cryptodev/rte_cryptodev_pmd.h
index fba14f2fa0..c4935b3307 100644
--- a/dpdk/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/dpdk/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -41,7 +41,8 @@ extern "C" {
 static const char * const cryptodev_pmd_valid_params[] = {
 	RTE_CRYPTODEV_PMD_NAME_ARG,
 	RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,
-	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG
+	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,
+	NULL
 };
 
 /**
diff --git a/dpdk/lib/librte_distributor/distributor_private.h b/dpdk/lib/librte_distributor/distributor_private.h
index 489aef2acb..689fe3e183 100644
--- a/dpdk/lib/librte_distributor/distributor_private.h
+++ b/dpdk/lib/librte_distributor/distributor_private.h
@@ -155,6 +155,9 @@ struct rte_distributor {
 	enum rte_distributor_match_function dist_match_fn;
 
 	struct rte_distributor_single *d_single;
+
+	uint8_t active[RTE_DISTRIB_MAX_WORKERS];
+	uint8_t activesum;
 };
 
 void
diff --git a/dpdk/lib/librte_distributor/meson.build b/dpdk/lib/librte_distributor/meson.build
index 50b91887b5..266af64348 100644
--- a/dpdk/lib/librte_distributor/meson.build
+++ b/dpdk/lib/librte_distributor/meson.build
@@ -9,7 +9,6 @@ else
 endif
 headers = files('rte_distributor.h')
 deps += ['mbuf']
-use_function_versioning = true
 
 # for clang 32-bit compiles we need libatomic for 64-bit atomic ops
 if cc.get_id() == 'clang' and dpdk_conf.get('RTE_ARCH_64') == false
diff --git a/dpdk/lib/librte_distributor/rte_distributor.c b/dpdk/lib/librte_distributor/rte_distributor.c
index 6c5b0c86e8..ef34facba6 100644
--- a/dpdk/lib/librte_distributor/rte_distributor.c
+++ b/dpdk/lib/librte_distributor/rte_distributor.c
@@ -8,7 +8,6 @@
 #include <rte_mbuf.h>
 #include <rte_memory.h>
 #include <rte_cycles.h>
-#include <rte_function_versioning.h>
 #include <rte_memzone.h>
 #include <rte_errno.h>
 #include <rte_string_fns.h>
@@ -43,7 +42,7 @@ rte_distributor_request_pkt(struct rte_distributor *d,
 
 	if (unlikely(d->alg_type == RTE_DIST_ALG_SINGLE)) {
 		rte_distributor_request_pkt_single(d->d_single,
-			worker_id, oldpkt[0]);
+			worker_id, count ? oldpkt[0] : NULL);
 		return;
 	}
 
@@ -52,7 +51,7 @@ rte_distributor_request_pkt(struct rte_distributor *d,
 	 * Sync with worker on GET_BUF flag.
 	 */
 	while (unlikely(__atomic_load_n(retptr64, __ATOMIC_ACQUIRE)
-			& RTE_DISTRIB_GET_BUF)) {
+			& (RTE_DISTRIB_GET_BUF | RTE_DISTRIB_RETURN_BUF))) {
 		rte_pause();
 		uint64_t t = rte_rdtsc()+100;
 
@@ -68,11 +67,11 @@ rte_distributor_request_pkt(struct rte_distributor *d,
 	for (i = count; i < RTE_DIST_BURST_SIZE; i++)
 		buf->retptr64[i] = 0;
 
-	/* Set Return bit for each packet returned */
+	/* Set VALID_BUF bit for each packet returned */
 	for (i = count; i-- > 0; )
 		buf->retptr64[i] =
 			(((int64_t)(uintptr_t)(oldpkt[i])) <<
-			RTE_DISTRIB_FLAG_BITS) | RTE_DISTRIB_RETURN_BUF;
+			RTE_DISTRIB_FLAG_BITS) | RTE_DISTRIB_VALID_BUF;
 
 	/*
 	 * Finally, set the GET_BUF  to signal to distributor that cache
@@ -98,11 +97,13 @@ rte_distributor_poll_pkt(struct rte_distributor *d,
 		return (pkts[0]) ? 1 : 0;
 	}
 
-	/* If bit is set, return
+	/* If any of below bits is set, return.
+	 * GET_BUF is set when distributor hasn't sent any packets yet
+	 * RETURN_BUF is set when distributor must retrieve in-flight packets
 	 * Sync with distributor to acquire bufptrs
 	 */
 	if (__atomic_load_n(&(buf->bufptr64[0]), __ATOMIC_ACQUIRE)
-		& RTE_DISTRIB_GET_BUF)
+		& (RTE_DISTRIB_GET_BUF | RTE_DISTRIB_RETURN_BUF))
 		return -1;
 
 	/* since bufptr64 is signed, this should be an arithmetic shift */
@@ -114,7 +115,7 @@ rte_distributor_poll_pkt(struct rte_distributor *d,
 	}
 
 	/*
-	 * so now we've got the contents of the cacheline into an  array of
+	 * so now we've got the contents of the cacheline into an array of
 	 * mbuf pointers, so toggle the bit so scheduler can start working
 	 * on the next cacheline while we're working.
 	 * Sync with distributor on GET_BUF flag. Release bufptrs.
@@ -135,7 +136,7 @@ rte_distributor_get_pkt(struct rte_distributor *d,
 	if (unlikely(d->alg_type == RTE_DIST_ALG_SINGLE)) {
 		if (return_count <= 1) {
 			pkts[0] = rte_distributor_get_pkt_single(d->d_single,
-				worker_id, oldpkt[0]);
+				worker_id, return_count ? oldpkt[0] : NULL);
 			return (pkts[0]) ? 1 : 0;
 		} else
 			return -EINVAL;
@@ -166,25 +167,48 @@ rte_distributor_return_pkt(struct rte_distributor *d,
 		if (num == 1)
 			return rte_distributor_return_pkt_single(d->d_single,
 				worker_id, oldpkt[0]);
+		else if (num == 0)
+			return rte_distributor_return_pkt_single(d->d_single,
+				worker_id, NULL);
 		else
 			return -EINVAL;
 	}
 
+	/* Spin while handshake bits are set (scheduler clears it).
+	 * Sync with worker on GET_BUF flag.
+	 */
+	while (unlikely(__atomic_load_n(&(buf->retptr64[0]), __ATOMIC_RELAXED)
+			& (RTE_DISTRIB_GET_BUF | RTE_DISTRIB_RETURN_BUF))) {
+		rte_pause();
+		uint64_t t = rte_rdtsc()+100;
+
+		while (rte_rdtsc() < t)
+			rte_pause();
+	}
+
 	/* Sync with distributor to acquire retptrs */
 	__atomic_thread_fence(__ATOMIC_ACQUIRE);
 	for (i = 0; i < RTE_DIST_BURST_SIZE; i++)
 		/* Switch off the return bit first */
-		buf->retptr64[i] &= ~RTE_DISTRIB_RETURN_BUF;
+		buf->retptr64[i] = 0;
 
 	for (i = num; i-- > 0; )
 		buf->retptr64[i] = (((int64_t)(uintptr_t)oldpkt[i]) <<
-			RTE_DISTRIB_FLAG_BITS) | RTE_DISTRIB_RETURN_BUF;
+			RTE_DISTRIB_FLAG_BITS) | RTE_DISTRIB_VALID_BUF;
 
-	/* set the GET_BUF but even if we got no returns.
-	 * Sync with distributor on GET_BUF flag. Release retptrs.
+	/* Use RETURN_BUF on bufptr64 to notify distributor that
+	 * we won't read any mbufs from there even if GET_BUF is set.
+	 * This allows distributor to retrieve in-flight already sent packets.
+	 */
+	__atomic_or_fetch(&(buf->bufptr64[0]), RTE_DISTRIB_RETURN_BUF,
+		__ATOMIC_ACQ_REL);
+
+	/* set the RETURN_BUF on retptr64 even if we got no returns.
+	 * Sync with distributor on RETURN_BUF flag. Release retptrs.
+	 * Notify distributor that we don't request more packets any more.
 	 */
 	__atomic_store_n(&(buf->retptr64[0]),
-		buf->retptr64[0] | RTE_DISTRIB_GET_BUF, __ATOMIC_RELEASE);
+		buf->retptr64[0] | RTE_DISTRIB_RETURN_BUF, __ATOMIC_RELEASE);
 
 	return 0;
 }
@@ -235,13 +259,13 @@ find_match_scalar(struct rte_distributor *d,
 
 		for (j = 0; j < RTE_DIST_BURST_SIZE ; j++)
 			for (w = 0; w < RTE_DIST_BURST_SIZE; w++)
-				if (d->in_flight_tags[i][j] == data_ptr[w]) {
+				if (d->in_flight_tags[i][w] == data_ptr[j]) {
 					output_ptr[j] = i+1;
 					break;
 				}
 		for (j = 0; j < RTE_DIST_BURST_SIZE; j++)
 			for (w = 0; w < RTE_DIST_BURST_SIZE; w++)
-				if (bl->tags[j] == data_ptr[w]) {
+				if (bl->tags[w] == data_ptr[j]) {
 					output_ptr[j] = i+1;
 					break;
 				}
@@ -254,6 +278,59 @@ find_match_scalar(struct rte_distributor *d,
 	 */
 }
 
+/*
+ * When worker called rte_distributor_return_pkt()
+ * and passed RTE_DISTRIB_RETURN_BUF handshake through retptr64,
+ * distributor must retrieve both inflight and backlog packets assigned
+ * to the worker and reprocess them to another worker.
+ */
+static void
+handle_worker_shutdown(struct rte_distributor *d, unsigned int wkr)
+{
+	struct rte_distributor_buffer *buf = &(d->bufs[wkr]);
+	/* double BURST size for storing both inflights and backlog */
+	struct rte_mbuf *pkts[RTE_DIST_BURST_SIZE * 2];
+	unsigned int pkts_count = 0;
+	unsigned int i;
+
+	/* If GET_BUF is cleared there are in-flight packets sent
+	 * to worker which does not require new packets.
+	 * They must be retrieved and assigned to another worker.
+	 */
+	if (!(__atomic_load_n(&(buf->bufptr64[0]), __ATOMIC_ACQUIRE)
+		& RTE_DISTRIB_GET_BUF))
+		for (i = 0; i < RTE_DIST_BURST_SIZE; i++)
+			if (buf->bufptr64[i] & RTE_DISTRIB_VALID_BUF)
+				pkts[pkts_count++] = (void *)((uintptr_t)
+					(buf->bufptr64[i]
+						>> RTE_DISTRIB_FLAG_BITS));
+
+	/* Make following operations on handshake flags on bufptr64:
+	 * - set GET_BUF to indicate that distributor can overwrite buffer
+	 *     with new packets if worker will make a new request.
+	 * - clear RETURN_BUF to unlock reads on worker side.
+	 */
+	__atomic_store_n(&(buf->bufptr64[0]), RTE_DISTRIB_GET_BUF,
+		__ATOMIC_RELEASE);
+
+	/* Collect backlog packets from worker */
+	for (i = 0; i < d->backlog[wkr].count; i++)
+		pkts[pkts_count++] = (void *)((uintptr_t)
+			(d->backlog[wkr].pkts[i] >> RTE_DISTRIB_FLAG_BITS));
+
+	d->backlog[wkr].count = 0;
+
+	/* Clear both inflight and backlog tags */
+	for (i = 0; i < RTE_DIST_BURST_SIZE; i++) {
+		d->in_flight_tags[wkr][i] = 0;
+		d->backlog[wkr].tags[i] = 0;
+	}
+
+	/* Recursive call */
+	if (pkts_count > 0)
+		rte_distributor_process(d, pkts, pkts_count);
+}
+
 
 /*
  * When the handshake bits indicate that there are packets coming
@@ -272,19 +349,33 @@ handle_returns(struct rte_distributor *d, unsigned int wkr)
 
 	/* Sync on GET_BUF flag. Acquire retptrs. */
 	if (__atomic_load_n(&(buf->retptr64[0]), __ATOMIC_ACQUIRE)
-		& RTE_DISTRIB_GET_BUF) {
+		& (RTE_DISTRIB_GET_BUF | RTE_DISTRIB_RETURN_BUF)) {
 		for (i = 0; i < RTE_DIST_BURST_SIZE; i++) {
-			if (buf->retptr64[i] & RTE_DISTRIB_RETURN_BUF) {
+			if (buf->retptr64[i] & RTE_DISTRIB_VALID_BUF) {
 				oldbuf = ((uintptr_t)(buf->retptr64[i] >>
 					RTE_DISTRIB_FLAG_BITS));
 				/* store returns in a circular buffer */
 				store_return(oldbuf, d, &ret_start, &ret_count);
 				count++;
-				buf->retptr64[i] &= ~RTE_DISTRIB_RETURN_BUF;
+				buf->retptr64[i] &= ~RTE_DISTRIB_VALID_BUF;
 			}
 		}
 		d->returns.start = ret_start;
 		d->returns.count = ret_count;
+
+		/* If worker requested packets with GET_BUF, set it to active
+		 * otherwise (RETURN_BUF), set it to not active.
+		 */
+		d->activesum -= d->active[wkr];
+		d->active[wkr] = !!(buf->retptr64[0] & RTE_DISTRIB_GET_BUF);
+		d->activesum += d->active[wkr];
+
+		/* If worker returned packets without requesting new ones,
+		 * handle all in-flights and backlog packets assigned to it.
+		 */
+		if (unlikely(buf->retptr64[0] & RTE_DISTRIB_RETURN_BUF))
+			handle_worker_shutdown(d, wkr);
+
 		/* Clear for the worker to populate with more returns.
 		 * Sync with distributor on GET_BUF flag. Release retptrs.
 		 */
@@ -308,12 +399,18 @@ release(struct rte_distributor *d, unsigned int wkr)
 	struct rte_distributor_buffer *buf = &(d->bufs[wkr]);
 	unsigned int i;
 
+	handle_returns(d, wkr);
+	if (unlikely(!d->active[wkr]))
+		return 0;
+
 	/* Sync with worker on GET_BUF flag */
 	while (!(__atomic_load_n(&(d->bufs[wkr].bufptr64[0]), __ATOMIC_ACQUIRE)
-		& RTE_DISTRIB_GET_BUF))
+		& RTE_DISTRIB_GET_BUF)) {
+		handle_returns(d, wkr);
+		if (unlikely(!d->active[wkr]))
+			return 0;
 		rte_pause();
-
-	handle_returns(d, wkr);
+	}
 
 	buf->count = 0;
 
@@ -351,7 +448,7 @@ rte_distributor_process(struct rte_distributor *d,
 	int64_t next_value = 0;
 	uint16_t new_tag = 0;
 	uint16_t flows[RTE_DIST_BURST_SIZE] __rte_cache_aligned;
-	unsigned int i, j, w, wid;
+	unsigned int i, j, w, wid, matching_required;
 
 	if (d->alg_type == RTE_DIST_ALG_SINGLE) {
 		/* Call the old API */
@@ -359,12 +456,16 @@ rte_distributor_process(struct rte_distributor *d,
 			mbufs, num_mbufs);
 	}
 
+	for (wid = 0 ; wid < d->num_workers; wid++)
+		handle_returns(d, wid);
+
 	if (unlikely(num_mbufs == 0)) {
 		/* Flush out all non-full cache-lines to workers. */
 		for (wid = 0 ; wid < d->num_workers; wid++) {
 			/* Sync with worker on GET_BUF flag. */
 			if (__atomic_load_n(&(d->bufs[wid].bufptr64[0]),
 				__ATOMIC_ACQUIRE) & RTE_DISTRIB_GET_BUF) {
+				d->bufs[wid].count = 0;
 				release(d, wid);
 				handle_returns(d, wid);
 			}
@@ -372,15 +473,13 @@ rte_distributor_process(struct rte_distributor *d,
 		return 0;
 	}
 
+	if (unlikely(!d->activesum))
+		return 0;
+
 	while (next_idx < num_mbufs) {
 		uint16_t matches[RTE_DIST_BURST_SIZE];
 		unsigned int pkts;
 
-		/* Sync with worker on GET_BUF flag. */
-		if (__atomic_load_n(&(d->bufs[wkr].bufptr64[0]),
-			__ATOMIC_ACQUIRE) & RTE_DISTRIB_GET_BUF)
-			d->bufs[wkr].count = 0;
-
 		if ((num_mbufs - next_idx) < RTE_DIST_BURST_SIZE)
 			pkts = num_mbufs - next_idx;
 		else
@@ -396,22 +495,30 @@ rte_distributor_process(struct rte_distributor *d,
 		for (; i < RTE_DIST_BURST_SIZE; i++)
 			flows[i] = 0;
 
-		switch (d->dist_match_fn) {
-		case RTE_DIST_MATCH_VECTOR:
-			find_match_vec(d, &flows[0], &matches[0]);
-			break;
-		default:
-			find_match_scalar(d, &flows[0], &matches[0]);
-		}
+		matching_required = 1;
 
+		for (j = 0; j < pkts; j++) {
+			if (unlikely(!d->activesum))
+				return next_idx;
+
+			if (unlikely(matching_required)) {
+				switch (d->dist_match_fn) {
+				case RTE_DIST_MATCH_VECTOR:
+					find_match_vec(d, &flows[0],
+						&matches[0]);
+					break;
+				default:
+					find_match_scalar(d, &flows[0],
+						&matches[0]);
+				}
+				matching_required = 0;
+			}
 		/*
 		 * Matches array now contain the intended worker ID (+1) of
 		 * the incoming packets. Any zeroes need to be assigned
 		 * workers.
 		 */
 
-		for (j = 0; j < pkts; j++) {
-
 			next_mb = mbufs[next_idx++];
 			next_value = (((int64_t)(uintptr_t)next_mb) <<
 					RTE_DISTRIB_FLAG_BITS);
@@ -431,12 +538,18 @@ rte_distributor_process(struct rte_distributor *d,
 			 */
 			/* matches[j] = 0; */
 
-			if (matches[j]) {
+			if (matches[j] && d->active[matches[j]-1]) {
 				struct rte_distributor_backlog *bl =
 						&d->backlog[matches[j]-1];
 				if (unlikely(bl->count ==
 						RTE_DIST_BURST_SIZE)) {
 					release(d, matches[j]-1);
+					if (!d->active[matches[j]-1]) {
+						j--;
+						next_idx--;
+						matching_required = 1;
+						continue;
+					}
 				}
 
 				/* Add to worker that already has flow */
@@ -446,11 +559,21 @@ rte_distributor_process(struct rte_distributor *d,
 				bl->pkts[idx] = next_value;
 
 			} else {
-				struct rte_distributor_backlog *bl =
-						&d->backlog[wkr];
+				struct rte_distributor_backlog *bl;
+
+				while (unlikely(!d->active[wkr]))
+					wkr = (wkr + 1) % d->num_workers;
+				bl = &d->backlog[wkr];
+
 				if (unlikely(bl->count ==
 						RTE_DIST_BURST_SIZE)) {
 					release(d, wkr);
+					if (!d->active[wkr]) {
+						j--;
+						next_idx--;
+						matching_required = 1;
+						continue;
+					}
 				}
 
 				/* Add to current worker worker */
@@ -469,17 +592,17 @@ rte_distributor_process(struct rte_distributor *d,
 						matches[w] = wkr+1;
 			}
 		}
-		wkr++;
-		if (wkr >= d->num_workers)
-			wkr = 0;
+		wkr = (wkr + 1) % d->num_workers;
 	}
 
 	/* Flush out all non-full cache-lines to workers. */
 	for (wid = 0 ; wid < d->num_workers; wid++)
 		/* Sync with worker on GET_BUF flag. */
 		if ((__atomic_load_n(&(d->bufs[wid].bufptr64[0]),
-			__ATOMIC_ACQUIRE) & RTE_DISTRIB_GET_BUF))
+			__ATOMIC_ACQUIRE) & RTE_DISTRIB_GET_BUF)) {
+			d->bufs[wid].count = 0;
 			release(d, wid);
+		}
 
 	return num_mbufs;
 }
@@ -522,7 +645,7 @@ total_outstanding(const struct rte_distributor *d)
 	unsigned int wkr, total_outstanding = 0;
 
 	for (wkr = 0; wkr < d->num_workers; wkr++)
-		total_outstanding += d->backlog[wkr].count;
+		total_outstanding += d->backlog[wkr].count + d->bufs[wkr].count;
 
 	return total_outstanding;
 }
@@ -579,6 +702,8 @@ rte_distributor_clear_returns(struct rte_distributor *d)
 		/* Sync with worker. Release retptrs. */
 		__atomic_store_n(&(d->bufs[wkr].retptr64[0]), 0,
 				__ATOMIC_RELEASE);
+
+	d->returns.start = d->returns.count = 0;
 }
 
 /* creates a distributor instance */
@@ -647,6 +772,9 @@ rte_distributor_create(const char *name,
 	for (i = 0 ; i < num_workers ; i++)
 		d->backlog[i].tags = &d->in_flight_tags[i][RTE_DIST_BURST_SIZE];
 
+	memset(d->active, 0, sizeof(d->active));
+	d->activesum = 0;
+
 	dist_burst_list = RTE_TAILQ_CAST(rte_dist_burst_tailq.head,
 					  rte_dist_burst_list);
 
diff --git a/dpdk/lib/librte_distributor/rte_distributor.h b/dpdk/lib/librte_distributor/rte_distributor.h
index 327c0c4ab2..a073e64612 100644
--- a/dpdk/lib/librte_distributor/rte_distributor.h
+++ b/dpdk/lib/librte_distributor/rte_distributor.h
@@ -155,7 +155,7 @@ rte_distributor_clear_returns(struct rte_distributor *d);
  * @param pkts
  *   The mbufs pointer array to be filled in (up to 8 packets)
  * @param oldpkt
- *   The previous packet, if any, being processed by the worker
+ *   The previous packets, if any, being processed by the worker
  * @param retcount
  *   The number of packets being returned
  *
@@ -187,15 +187,15 @@ rte_distributor_return_pkt(struct rte_distributor *d,
 
 /**
  * API called by a worker to request a new packet to process.
- * Any previous packet given to the worker is assumed to have completed
+ * Any previous packets given to the worker are assumed to have completed
  * processing, and may be optionally returned to the distributor via
  * the oldpkt parameter.
- * Unlike rte_distributor_get_pkt_burst(), this function does not wait for a
- * new packet to be provided by the distributor.
+ * Unlike rte_distributor_get_pkt(), this function does not wait for
+ * new packets to be provided by the distributor.
  *
- * NOTE: after calling this function, rte_distributor_poll_pkt_burst() should
- * be used to poll for the packet requested. The rte_distributor_get_pkt_burst()
- * API should *not* be used to try and retrieve the new packet.
+ * NOTE: after calling this function, rte_distributor_poll_pkt() should
+ * be used to poll for the packets requested. The rte_distributor_get_pkt()
+ * API should *not* be used to try and retrieve the new packets.
  *
  * @param d
  *   The distributor instance to be used
@@ -213,9 +213,9 @@ rte_distributor_request_pkt(struct rte_distributor *d,
 		unsigned int count);
 
 /**
- * API called by a worker to check for a new packet that was previously
+ * API called by a worker to check for new packets that were previously
  * requested by a call to rte_distributor_request_pkt(). It does not wait
- * for the new packet to be available, but returns NULL if the request has
+ * for the new packets to be available, but returns if the request has
  * not yet been fulfilled by the distributor.
  *
  * @param d
@@ -227,8 +227,9 @@ rte_distributor_request_pkt(struct rte_distributor *d,
  *   The array of mbufs being given to the worker
  *
  * @return
- *   The number of packets being given to the worker thread, zero if no
- *   packet is yet available.
+ *   The number of packets being given to the worker thread,
+ *   -1 if no packets are yet available (burst API - RTE_DIST_ALG_BURST)
+ *   0 if no packets are yet available (legacy single API - RTE_DIST_ALG_SINGLE)
  */
 int
 rte_distributor_poll_pkt(struct rte_distributor *d,
diff --git a/dpdk/lib/librte_distributor/rte_distributor_single.c b/dpdk/lib/librte_distributor/rte_distributor_single.c
index 91d8824c64..f4725b1d0b 100644
--- a/dpdk/lib/librte_distributor/rte_distributor_single.c
+++ b/dpdk/lib/librte_distributor/rte_distributor_single.c
@@ -9,7 +9,6 @@
 #include <rte_memory.h>
 #include <rte_memzone.h>
 #include <rte_errno.h>
-#include <rte_function_versioning.h>
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 #include <rte_pause.h>
@@ -75,6 +74,10 @@ rte_distributor_return_pkt_single(struct rte_distributor_single *d,
 	union rte_distributor_buffer_single *buf = &d->bufs[worker_id];
 	uint64_t req = (((int64_t)(uintptr_t)oldpkt) << RTE_DISTRIB_FLAG_BITS)
 			| RTE_DISTRIB_RETURN_BUF;
+	while (unlikely(__atomic_load_n(&buf->bufptr64, __ATOMIC_RELAXED)
+			& RTE_DISTRIB_FLAGS_MASK))
+		rte_pause();
+
 	/* Sync with distributor on RETURN_BUF flag. */
 	__atomic_store_n(&(buf->bufptr64), req, __ATOMIC_RELEASE);
 	return 0;
diff --git a/dpdk/lib/librte_eal/common/arch/arm/rte_cycles.c b/dpdk/lib/librte_eal/common/arch/arm/rte_cycles.c
index 3500d523ef..5bd29b24b1 100644
--- a/dpdk/lib/librte_eal/common/arch/arm/rte_cycles.c
+++ b/dpdk/lib/librte_eal/common/arch/arm/rte_cycles.c
@@ -3,14 +3,35 @@
  */
 
 #include "eal_private.h"
+#include "rte_cycles.h"
 
 uint64_t
 get_tsc_freq_arch(void)
 {
 #if defined RTE_ARCH_ARM64 && !defined RTE_ARM_EAL_RDTSC_USE_PMU
-	uint64_t freq;
-	asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));
-	return freq;
+	return __rte_arm64_cntfrq();
+#elif defined RTE_ARCH_ARM64 && defined RTE_ARM_EAL_RDTSC_USE_PMU
+#define CYC_PER_1MHZ 1E6
+	/* Use the generic counter ticks to calculate the PMU
+	 * cycle frequency.
+	 */
+	uint64_t ticks;
+	uint64_t start_ticks, cur_ticks;
+	uint64_t start_pmu_cycles, end_pmu_cycles;
+
+	/* Number of ticks for 1/10 second */
+	ticks = __rte_arm64_cntfrq() / 10;
+
+	start_ticks = __rte_arm64_cntvct_precise();
+	start_pmu_cycles = rte_rdtsc_precise();
+	do {
+		cur_ticks = __rte_arm64_cntvct();
+	} while ((cur_ticks - start_ticks) < ticks);
+	end_pmu_cycles = rte_rdtsc_precise();
+
+	/* Adjust the cycles to next 1Mhz */
+	return RTE_ALIGN_MUL_CEIL(end_pmu_cycles - start_pmu_cycles,
+			CYC_PER_1MHZ) * 10;
 #else
 	return 0;
 #endif
diff --git a/dpdk/lib/librte_eal/common/eal_common_dev.c b/dpdk/lib/librte_eal/common/eal_common_dev.c
index 9e4f09d83e..363a2ca95e 100644
--- a/dpdk/lib/librte_eal/common/eal_common_dev.c
+++ b/dpdk/lib/librte_eal/common/eal_common_dev.c
@@ -526,6 +526,7 @@ rte_dev_event_callback_unregister(const char *device_name,
 		 */
 		if (event_cb->active == 0) {
 			TAILQ_REMOVE(&dev_event_cbs, event_cb, next);
+			free(event_cb->dev_name);
 			free(event_cb);
 			ret++;
 		} else {
diff --git a/dpdk/lib/librte_eal/common/eal_common_fbarray.c b/dpdk/lib/librte_eal/common/eal_common_fbarray.c
index 1312f936b8..de7e772042 100644
--- a/dpdk/lib/librte_eal/common/eal_common_fbarray.c
+++ b/dpdk/lib/librte_eal/common/eal_common_fbarray.c
@@ -114,7 +114,7 @@ overlap(const struct mem_area *ma, const void *start, size_t len)
 	if (start >= ma_start && start < ma_end)
 		return 1;
 	/* end overlap? */
-	if (end >= ma_start && end < ma_end)
+	if (end > ma_start && end < ma_end)
 		return 1;
 	return 0;
 }
@@ -1337,7 +1337,7 @@ fbarray_find_biggest(struct rte_fbarray *arr, unsigned int start, bool used,
 	 */
 
 	/* the API's called are thread-safe, but something may still happen
-	 * inbetween the API calls, so lock the fbarray. all other API's are
+	 * between the API calls, so lock the fbarray. all other API's are
 	 * read-locking the fbarray, so read lock here is OK.
 	 */
 	rte_rwlock_read_lock(&arr->rwlock);
diff --git a/dpdk/lib/librte_eal/common/eal_common_lcore.c b/dpdk/lib/librte_eal/common/eal_common_lcore.c
index 39efadef1a..3ecca3869b 100644
--- a/dpdk/lib/librte_eal/common/eal_common_lcore.c
+++ b/dpdk/lib/librte_eal/common/eal_common_lcore.c
@@ -31,8 +31,12 @@ int rte_lcore_index(int lcore_id)
 	if (unlikely(lcore_id >= RTE_MAX_LCORE))
 		return -1;
 
-	if (lcore_id < 0)
+	if (lcore_id < 0) {
+		if (rte_lcore_id() == LCORE_ID_ANY)
+			return -1;
+
 		lcore_id = (int)rte_lcore_id();
+	}
 
 	return lcore_config[lcore_id].core_index;
 }
@@ -42,8 +46,12 @@ int rte_lcore_to_cpu_id(int lcore_id)
 	if (unlikely(lcore_id >= RTE_MAX_LCORE))
 		return -1;
 
-	if (lcore_id < 0)
+	if (lcore_id < 0) {
+		if (rte_lcore_id() == LCORE_ID_ANY)
+			return -1;
+
 		lcore_id = (int)rte_lcore_id();
+	}
 
 	return lcore_config[lcore_id].core_id;
 }
diff --git a/dpdk/lib/librte_eal/common/eal_common_log.c b/dpdk/lib/librte_eal/common/eal_common_log.c
index c0efd5214f..975aea90db 100644
--- a/dpdk/lib/librte_eal/common/eal_common_log.c
+++ b/dpdk/lib/librte_eal/common/eal_common_log.c
@@ -302,7 +302,7 @@ rte_log_register_type_and_pick_level(const char *name, uint32_t level_def)
 			continue;
 
 		if (opt_ll->pattern) {
-			if (fnmatch(opt_ll->pattern, name, 0))
+			if (fnmatch(opt_ll->pattern, name, 0) == 0)
 				level = opt_ll->level;
 		} else {
 			if (regexec(&opt_ll->re_match, name, 0, NULL, 0) == 0)
diff --git a/dpdk/lib/librte_eal/common/eal_common_memory.c b/dpdk/lib/librte_eal/common/eal_common_memory.c
index 4a9cc1f19a..4c897a13f1 100644
--- a/dpdk/lib/librte_eal/common/eal_common_memory.c
+++ b/dpdk/lib/librte_eal/common/eal_common_memory.c
@@ -40,6 +40,14 @@
 static void *next_baseaddr;
 static uint64_t system_page_sz;
 
+#ifdef RTE_EXEC_ENV_LINUX
+#define RTE_DONTDUMP MADV_DONTDUMP
+#elif defined RTE_EXEC_ENV_FREEBSD
+#define RTE_DONTDUMP MADV_NOCORE
+#else
+#error "madvise doesn't support this OS"
+#endif
+
 #define MAX_MMAP_WITH_DEFINED_ADDR_TRIES 5
 void *
 eal_get_virtual_area(void *requested_addr, size_t *size,
@@ -97,7 +105,7 @@ eal_get_virtual_area(void *requested_addr, size_t *size,
 			return NULL;
 		}
 
-		mapped_addr = mmap(requested_addr, (size_t)map_sz, PROT_READ,
+		mapped_addr = mmap(requested_addr, (size_t)map_sz, PROT_NONE,
 				mmap_flags, -1, 0);
 		if (mapped_addr == MAP_FAILED && allow_shrink)
 			*size -= page_sz;
@@ -179,6 +187,13 @@ eal_get_virtual_area(void *requested_addr, size_t *size,
 			munmap(aligned_end, after_len);
 	}
 
+	if (!unmap) {
+		/* Exclude these pages from a core dump. */
+		if (madvise(aligned_addr, *size, RTE_DONTDUMP) != 0)
+			RTE_LOG(DEBUG, EAL, "madvise failed: %s\n",
+				strerror(errno));
+	}
+
 	return aligned_addr;
 }
 
diff --git a/dpdk/lib/librte_eal/common/eal_common_options.c b/dpdk/lib/librte_eal/common/eal_common_options.c
index a7f9c5f9bd..f791e9671d 100644
--- a/dpdk/lib/librte_eal/common/eal_common_options.c
+++ b/dpdk/lib/librte_eal/common/eal_common_options.c
@@ -1039,7 +1039,7 @@ eal_parse_log_level(const char *arg)
 	if (regex) {
 		if (rte_log_set_level_regexp(regex, priority) < 0) {
 			fprintf(stderr, "cannot set log level %s,%d\n",
-				pattern, priority);
+				regex, priority);
 			goto fail;
 		}
 		if (rte_log_save_regexp(regex, priority) < 0)
diff --git a/dpdk/lib/librte_eal/common/eal_common_proc.c b/dpdk/lib/librte_eal/common/eal_common_proc.c
index 935e8fefeb..13ae2b915e 100644
--- a/dpdk/lib/librte_eal/common/eal_common_proc.c
+++ b/dpdk/lib/librte_eal/common/eal_common_proc.c
@@ -416,7 +416,7 @@ process_async_request(struct pending_request *sr, const struct timespec *now)
 	/* did we timeout? */
 	timeout = timespec_cmp(&param->end, now) <= 0;
 
-	/* if we received a response, adjust relevant data and copy mesasge. */
+	/* if we received a response, adjust relevant data and copy message. */
 	if (sr->reply_received == 1 && sr->reply) {
 		struct rte_mp_msg *msg, *user_msgs, *tmp;
 
@@ -621,7 +621,7 @@ rte_mp_channel_init(void)
 
 	if (rte_ctrl_thread_create(&mp_handle_tid, "rte_mp_handle",
 			NULL, mp_handle, NULL) < 0) {
-		RTE_LOG(ERR, EAL, "failed to create mp thead: %s\n",
+		RTE_LOG(ERR, EAL, "failed to create mp thread: %s\n",
 			strerror(errno));
 		close(mp_fd);
 		close(dir_fd);
diff --git a/dpdk/lib/librte_eal/common/include/arch/arm/meson.build b/dpdk/lib/librte_eal/common/include/arch/arm/meson.build
index 77893fa359..faa3d84f67 100644
--- a/dpdk/lib/librte_eal/common/include/arch/arm/meson.build
+++ b/dpdk/lib/librte_eal/common/include/arch/arm/meson.build
@@ -14,6 +14,7 @@ install_headers(
 	'rte_cycles.h',
 	'rte_io_64.h',
 	'rte_io.h',
+	'rte_mcslock.h',
 	'rte_memcpy_32.h',
 	'rte_memcpy_64.h',
 	'rte_memcpy.h',
@@ -25,5 +26,6 @@ install_headers(
 	'rte_prefetch.h',
 	'rte_rwlock.h',
 	'rte_spinlock.h',
+	'rte_ticketlock.h',
 	'rte_vect.h',
 	subdir: get_option('include_subdir_arch'))
diff --git a/dpdk/lib/librte_eal/common/include/arch/arm/rte_atomic_64.h b/dpdk/lib/librte_eal/common/include/arch/arm/rte_atomic_64.h
index 859ae129d8..3384934afa 100644
--- a/dpdk/lib/librte_eal/common/include/arch/arm/rte_atomic_64.h
+++ b/dpdk/lib/librte_eal/common/include/arch/arm/rte_atomic_64.h
@@ -47,19 +47,26 @@ extern "C" {
 /*------------------------ 128 bit atomic operations -------------------------*/
 
 #if defined(__ARM_FEATURE_ATOMICS) || defined(RTE_ARM_FEATURE_ATOMICS)
+#if defined(RTE_CC_CLANG)
+#define __LSE_PREAMBLE	".arch armv8-a+lse\n"
+#else
+#define __LSE_PREAMBLE	""
+#endif
+
 #define __ATOMIC128_CAS_OP(cas_op_name, op_string)                          \
-static __rte_noinline rte_int128_t                                          \
-cas_op_name(rte_int128_t *dst, rte_int128_t old, rte_int128_t updated)      \
+static __rte_noinline void                                                  \
+cas_op_name(rte_int128_t *dst, rte_int128_t *old, rte_int128_t updated)     \
 {                                                                           \
 	/* caspX instructions register pair must start from even-numbered
 	 * register at operand 1.
 	 * So, specify registers for local variables here.
 	 */                                                                 \
-	register uint64_t x0 __asm("x0") = (uint64_t)old.val[0];            \
-	register uint64_t x1 __asm("x1") = (uint64_t)old.val[1];            \
+	register uint64_t x0 __asm("x0") = (uint64_t)old->val[0];           \
+	register uint64_t x1 __asm("x1") = (uint64_t)old->val[1];           \
 	register uint64_t x2 __asm("x2") = (uint64_t)updated.val[0];        \
 	register uint64_t x3 __asm("x3") = (uint64_t)updated.val[1];        \
 	asm volatile(                                                       \
+		__LSE_PREAMBLE						    \
 		op_string " %[old0], %[old1], %[upd0], %[upd1], [%[dst]]"   \
 		: [old0] "+r" (x0),                                         \
 		[old1] "+r" (x1)                                            \
@@ -67,9 +74,8 @@ cas_op_name(rte_int128_t *dst, rte_int128_t old, rte_int128_t updated)      \
 		[upd1] "r" (x3),                                            \
 		[dst] "r" (dst)                                             \
 		: "memory");                                                \
-	old.val[0] = x0;                                                    \
-	old.val[1] = x1;                                                    \
-	return old;                                                         \
+	old->val[0] = x0;                                                   \
+	old->val[1] = x1;                                                   \
 }
 
 __ATOMIC128_CAS_OP(__cas_128_relaxed, "casp")
@@ -77,6 +83,7 @@ __ATOMIC128_CAS_OP(__cas_128_acquire, "caspa")
 __ATOMIC128_CAS_OP(__cas_128_release, "caspl")
 __ATOMIC128_CAS_OP(__cas_128_acq_rel, "caspal")
 
+#undef __LSE_PREAMBLE
 #undef __ATOMIC128_CAS_OP
 
 #endif
@@ -106,13 +113,14 @@ rte_atomic128_cmp_exchange(rte_int128_t *dst, rte_int128_t *exp,
 
 #if defined(__ARM_FEATURE_ATOMICS) || defined(RTE_ARM_FEATURE_ATOMICS)
 	if (success == __ATOMIC_RELAXED)
-		old = __cas_128_relaxed(dst, expected, desired);
+		__cas_128_relaxed(dst, exp, desired);
 	else if (success == __ATOMIC_ACQUIRE)
-		old = __cas_128_acquire(dst, expected, desired);
+		__cas_128_acquire(dst, exp, desired);
 	else if (success == __ATOMIC_RELEASE)
-		old = __cas_128_release(dst, expected, desired);
+		__cas_128_release(dst, exp, desired);
 	else
-		old = __cas_128_acq_rel(dst, expected, desired);
+		__cas_128_acq_rel(dst, exp, desired);
+	old = *exp;
 #else
 #define __HAS_ACQ(mo) ((mo) != __ATOMIC_RELAXED && (mo) != __ATOMIC_RELEASE)
 #define __HAS_RLS(mo) ((mo) == __ATOMIC_RELEASE || (mo) == __ATOMIC_ACQ_REL || \
@@ -176,12 +184,12 @@ rte_atomic128_cmp_exchange(rte_int128_t *dst, rte_int128_t *exp,
 #undef __STORE_128
 
 	} while (unlikely(ret));
-#endif
 
-	/* Unconditionally updating expected removes an 'if' statement.
-	 * expected should already be in register if not in the cache.
+	/* Unconditionally updating the value of exp removes an 'if' statement.
+	 * The value of exp should already be in register if not in the cache.
 	 */
 	*exp = old;
+#endif
 
 	return (old.int128 == expected.int128);
 }
diff --git a/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_32.h b/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_32.h
index 859b09748c..f79718ce8c 100644
--- a/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_32.h
+++ b/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_32.h
@@ -57,7 +57,7 @@ __rte_rdtsc_syscall(void)
  *      asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(29));
  *      asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(0x8000000f));
  *
- * which is possible only from the priviledged mode (kernel space).
+ * which is possible only from the privileged mode (kernel space).
  */
 static inline uint64_t
 __rte_rdtsc_pmccntr(void)
diff --git a/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_64.h b/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_64.h
index 68e7c73384..e41f9dbd62 100644
--- a/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_64.h
+++ b/dpdk/lib/librte_eal/common/include/arch/arm/rte_cycles_64.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright(c) 2015 Cavium, Inc
+ * Copyright(c) 2020 Arm Limited
  */
 
 #ifndef _RTE_CYCLES_ARM64_H_
@@ -11,6 +12,33 @@ extern "C" {
 
 #include "generic/rte_cycles.h"
 
+/** Read generic counter frequency */
+static __rte_always_inline uint64_t
+__rte_arm64_cntfrq(void)
+{
+	uint64_t freq;
+
+	asm volatile("mrs %0, cntfrq_el0" : "=r" (freq));
+	return freq;
+}
+
+/** Read generic counter */
+static __rte_always_inline uint64_t
+__rte_arm64_cntvct(void)
+{
+	uint64_t tsc;
+
+	asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
+	return tsc;
+}
+
+static __rte_always_inline uint64_t
+__rte_arm64_cntvct_precise(void)
+{
+	asm volatile("isb" : : : "memory");
+	return __rte_arm64_cntvct();
+}
+
 /**
  * Read the time base register.
  *
@@ -25,10 +53,7 @@ extern "C" {
 static inline uint64_t
 rte_rdtsc(void)
 {
-	uint64_t tsc;
-
-	asm volatile("mrs %0, cntvct_el0" : "=r" (tsc));
-	return tsc;
+	return __rte_arm64_cntvct();
 }
 #else
 /**
@@ -49,20 +74,28 @@ rte_rdtsc(void)
  * asm volatile("msr pmcr_el0, %0" : : "r" (val));
  *
  */
-static inline uint64_t
-rte_rdtsc(void)
+
+/** Read PMU cycle counter */
+static __rte_always_inline uint64_t
+__rte_arm64_pmccntr(void)
 {
 	uint64_t tsc;
 
 	asm volatile("mrs %0, pmccntr_el0" : "=r"(tsc));
 	return tsc;
 }
+
+static inline uint64_t
+rte_rdtsc(void)
+{
+	return __rte_arm64_pmccntr();
+}
 #endif
 
 static inline uint64_t
 rte_rdtsc_precise(void)
 {
-	rte_mb();
+	asm volatile("isb" : : : "memory");
 	return rte_rdtsc();
 }
 
diff --git a/dpdk/lib/librte_eal/common/include/arch/arm/rte_vect.h b/dpdk/lib/librte_eal/common/include/arch/arm/rte_vect.h
index 2a18a68546..71e56ec63e 100644
--- a/dpdk/lib/librte_eal/common/include/arch/arm/rte_vect.h
+++ b/dpdk/lib/librte_eal/common/include/arch/arm/rte_vect.h
@@ -62,7 +62,11 @@ vaddvq_u16(uint16x8_t a)
 
 #endif
 
-#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION < 70000)
+#if defined(RTE_ARCH_ARM) || \
+(defined(RTE_ARCH_ARM64) && RTE_TOOLCHAIN_GCC && (GCC_VERSION < 70000))
+/* NEON intrinsic vcopyq_laneq_u32() is not supported in ARMv7-A(AArch32)
+ * On AArch64, this intrinsic is supported since GCC version 7.
+ */
 static inline uint32x4_t
 vcopyq_laneq_u32(uint32x4_t a, const int lane_a,
 		 uint32x4_t b, const int lane_b)
diff --git a/dpdk/lib/librte_eal/common/include/arch/ppc_64/meson.build b/dpdk/lib/librte_eal/common/include/arch/ppc_64/meson.build
index 00f9611768..5d3ebafa26 100644
--- a/dpdk/lib/librte_eal/common/include/arch/ppc_64/meson.build
+++ b/dpdk/lib/librte_eal/common/include/arch/ppc_64/meson.build
@@ -2,15 +2,18 @@
 # Copyright(c) 2018 Luca Boccassi <bluca@debian.org>
 
 install_headers(
+	'rte_altivec.h',
 	'rte_atomic.h',
 	'rte_byteorder.h',
 	'rte_cpuflags.h',
 	'rte_cycles.h',
 	'rte_io.h',
+	'rte_mcslock.h',
 	'rte_memcpy.h',
 	'rte_pause.h',
 	'rte_prefetch.h',
 	'rte_rwlock.h',
 	'rte_spinlock.h',
+	'rte_ticketlock.h',
 	'rte_vect.h',
 	subdir: get_option('include_subdir_arch'))
diff --git a/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_altivec.h b/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_altivec.h
new file mode 100644
index 0000000000..1551a94544
--- /dev/null
+++ b/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_altivec.h
@@ -0,0 +1,22 @@
+/*
+ * SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (C) Mellanox 2020.
+ */
+
+#ifndef _RTE_ALTIVEC_H_
+#define _RTE_ALTIVEC_H_
+
+/* To include altivec.h, GCC version must be >= 4.8 */
+#include <altivec.h>
+
+/*
+ * Compilation workaround for PPC64 when AltiVec is fully enabled, e.g. std=c11.
+ * Otherwise there would be a type conflict between stdbool and altivec.
+ */
+#if defined(__PPC64__) && !defined(__APPLE_ALTIVEC__)
+#undef bool
+/* redefine as in stdbool.h */
+#define bool _Bool
+#endif
+
+#endif /* _RTE_ALTIVEC_H_ */
diff --git a/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_memcpy.h b/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_memcpy.h
index 25311ba1d7..e63a1211a8 100644
--- a/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_memcpy.h
+++ b/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_memcpy.h
@@ -8,8 +8,10 @@
 
 #include <stdint.h>
 #include <string.h>
-/*To include altivec.h, GCC version must  >= 4.8 */
-#include <altivec.h>
+
+#include "rte_altivec.h"
+
+#include "rte_common.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -17,6 +19,11 @@ extern "C" {
 
 #include "generic/rte_memcpy.h"
 
+#if (GCC_VERSION >= 90000 && GCC_VERSION < 90400)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+
 static inline void
 rte_mov16(uint8_t *dst, const uint8_t *src)
 {
@@ -192,6 +199,10 @@ rte_memcpy_func(void *dst, const void *src, size_t n)
 	return ret;
 }
 
+#if (GCC_VERSION >= 90000 && GCC_VERSION < 90400)
+#pragma GCC diagnostic pop
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h b/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h
index 068c805b22..4caafd9d2b 100644
--- a/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h
+++ b/dpdk/lib/librte_eal/common/include/arch/ppc_64/rte_vect.h
@@ -6,7 +6,8 @@
 #ifndef _RTE_VECT_PPC_64_H_
 #define _RTE_VECT_PPC_64_H_
 
-#include <altivec.h>
+#include "rte_altivec.h"
+
 #include "generic/rte_vect.h"
 
 #ifdef __cplusplus
diff --git a/dpdk/lib/librte_eal/common/include/arch/x86/meson.build b/dpdk/lib/librte_eal/common/include/arch/x86/meson.build
index bc8ffea1ee..806cfad042 100644
--- a/dpdk/lib/librte_eal/common/include/arch/x86/meson.build
+++ b/dpdk/lib/librte_eal/common/include/arch/x86/meson.build
@@ -11,11 +11,13 @@ install_headers(
 	'rte_cpuflags.h',
 	'rte_cycles.h',
 	'rte_io.h',
+	'rte_mcslock.h',
 	'rte_memcpy.h',
 	'rte_prefetch.h',
 	'rte_pause.h',
 	'rte_rtm.h',
 	'rte_rwlock.h',
 	'rte_spinlock.h',
+	'rte_ticketlock.h',
 	'rte_vect.h',
 	subdir: get_option('include_subdir_arch'))
diff --git a/dpdk/lib/librte_eal/common/include/arch/x86/rte_atomic.h b/dpdk/lib/librte_eal/common/include/arch/x86/rte_atomic.h
index 148398f50a..b9dcd30aba 100644
--- a/dpdk/lib/librte_eal/common/include/arch/x86/rte_atomic.h
+++ b/dpdk/lib/librte_eal/common/include/arch/x86/rte_atomic.h
@@ -55,7 +55,7 @@ extern "C" {
  *
  * As pointed by Java guys, that makes possible to use lock-prefixed
  * instructions to get the same effect as mfence and on most modern HW
- * that gives a better perfomance then using mfence:
+ * that gives a better performance then using mfence:
  * https://shipilev.net/blog/2014/on-the-fence-with-dependencies/
  * Basic idea is to use lock prefixed add with some dummy memory location
  * as the destination. From their experiments 128B(2 cache lines) below
diff --git a/dpdk/lib/librte_eal/common/include/arch/x86/rte_memcpy.h b/dpdk/lib/librte_eal/common/include/arch/x86/rte_memcpy.h
index ba44c4a328..d01832fa15 100644
--- a/dpdk/lib/librte_eal/common/include/arch/x86/rte_memcpy.h
+++ b/dpdk/lib/librte_eal/common/include/arch/x86/rte_memcpy.h
@@ -22,6 +22,11 @@
 extern "C" {
 #endif
 
+#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION >= 100000)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
+
 /**
  * Copy bytes from one location to another. The locations must not overlap.
  *
@@ -40,7 +45,7 @@ extern "C" {
 static __rte_always_inline void *
 rte_memcpy(void *dst, const void *src, size_t n);
 
-#ifdef RTE_MACHINE_CPUFLAG_AVX512F
+#if defined RTE_MACHINE_CPUFLAG_AVX512F && defined RTE_MEMCPY_AVX512
 
 #define ALIGNMENT_MASK 0x3F
 
@@ -869,6 +874,10 @@ rte_memcpy(void *dst, const void *src, size_t n)
 		return rte_memcpy_generic(dst, src, n);
 }
 
+#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION >= 100000)
+#pragma GCC diagnostic pop
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/dpdk/lib/librte_eal/common/include/generic/rte_byteorder.h b/dpdk/lib/librte_eal/common/include/generic/rte_byteorder.h
index 38e8cfd32b..9ca960932f 100644
--- a/dpdk/lib/librte_eal/common/include/generic/rte_byteorder.h
+++ b/dpdk/lib/librte_eal/common/include/generic/rte_byteorder.h
@@ -93,9 +93,9 @@
 #define RTE_BE16(v) (rte_be16_t)(RTE_STATIC_BSWAP16(v))
 #define RTE_BE32(v) (rte_be32_t)(RTE_STATIC_BSWAP32(v))
 #define RTE_BE64(v) (rte_be64_t)(RTE_STATIC_BSWAP64(v))
-#define RTE_LE16(v) (rte_be16_t)(v)
-#define RTE_LE32(v) (rte_be32_t)(v)
-#define RTE_LE64(v) (rte_be64_t)(v)
+#define RTE_LE16(v) (rte_le16_t)(v)
+#define RTE_LE32(v) (rte_le32_t)(v)
+#define RTE_LE64(v) (rte_le64_t)(v)
 #else
 #error Unsupported endianness.
 #endif
diff --git a/dpdk/lib/librte_eal/common/include/generic/rte_mcslock.h b/dpdk/lib/librte_eal/common/include/generic/rte_mcslock.h
index 2bef28351c..896dfbf10f 100644
--- a/dpdk/lib/librte_eal/common/include/generic/rte_mcslock.h
+++ b/dpdk/lib/librte_eal/common/include/generic/rte_mcslock.h
@@ -22,6 +22,7 @@
 #include <rte_lcore.h>
 #include <rte_common.h>
 #include <rte_pause.h>
+#include <rte_branch_prediction.h>
 
 /**
  * The rte_mcslock_t type.
@@ -68,7 +69,14 @@ rte_mcslock_lock(rte_mcslock_t **msl, rte_mcslock_t *me)
 		 */
 		return;
 	}
-	__atomic_store_n(&prev->next, me, __ATOMIC_RELAXED);
+	/* The store to me->next above should also complete before the node is
+	 * visible to predecessor thread releasing the lock. Hence, the store
+	 * prev->next also requires release semantics. Note that, for example,
+	 * on ARM, the release semantics in the exchange operation is not
+	 * strong as a release fence and is not sufficient to enforce the
+	 * desired order here.
+	 */
+	__atomic_store_n(&prev->next, me, __ATOMIC_RELEASE);
 
 	/* The while-load of me->locked should not move above the previous
 	 * store to prev->next. Otherwise it will cause a deadlock. Need a
diff --git a/dpdk/lib/librte_eal/common/include/generic/rte_memcpy.h b/dpdk/lib/librte_eal/common/include/generic/rte_memcpy.h
index 701e550c31..e7f0f8eaa9 100644
--- a/dpdk/lib/librte_eal/common/include/generic/rte_memcpy.h
+++ b/dpdk/lib/librte_eal/common/include/generic/rte_memcpy.h
@@ -95,6 +95,10 @@ rte_mov256(uint8_t *dst, const uint8_t *src);
  * @note This is implemented as a macro, so it's address should not be taken
  * and care is needed as parameter expressions may be evaluated multiple times.
  *
+ * @note For x86 platforms to enable the AVX-512 memcpy implementation, set
+ * -DRTE_MEMCPY_AVX512 macro in CFLAGS, or define the RTE_MEMCPY_AVX512 macro
+ * explicitly in the source file before including the rte_memcpy header file.
+ *
  * @param dst
  *   Pointer to the destination of the data.
  * @param src
diff --git a/dpdk/lib/librte_eal/common/include/rte_common.h b/dpdk/lib/librte_eal/common/include/rte_common.h
index 459d082d14..fe7539af26 100644
--- a/dpdk/lib/librte_eal/common/include/rte_common.h
+++ b/dpdk/lib/librte_eal/common/include/rte_common.h
@@ -245,7 +245,7 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  * than the first parameter.
  */
 #define RTE_ALIGN_MUL_CEIL(v, mul) \
-	(((v + (typeof(v))(mul) - 1) / ((typeof(v))(mul))) * (typeof(v))(mul))
+	((((v) + (typeof(v))(mul) - 1) / ((typeof(v))(mul))) * (typeof(v))(mul))
 
 /**
  * Macro to align a value to the multiple of given value. The resultant
@@ -253,7 +253,7 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
  * than the first parameter.
  */
 #define RTE_ALIGN_MUL_FLOOR(v, mul) \
-	((v / ((typeof(v))(mul))) * (typeof(v))(mul))
+	(((v) / ((typeof(v))(mul))) * (typeof(v))(mul))
 
 /**
  * Macro to align value to the nearest multiple of the given value.
@@ -264,7 +264,7 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
 	({							\
 		typeof(v) ceil = RTE_ALIGN_MUL_CEIL(v, mul);	\
 		typeof(v) floor = RTE_ALIGN_MUL_FLOOR(v, mul);	\
-		(ceil - v) > (v - floor) ? floor : ceil;	\
+		(ceil - (v)) > ((v) - floor) ? floor : ceil;	\
 	})
 
 /**
@@ -347,7 +347,7 @@ typedef uint64_t rte_iova_t;
  *    The combined value.
  */
 static inline uint32_t
-rte_combine32ms1b(register uint32_t x)
+rte_combine32ms1b(uint32_t x)
 {
 	x |= x >> 1;
 	x |= x >> 2;
@@ -369,7 +369,7 @@ rte_combine32ms1b(register uint32_t x)
  *    The combined value.
  */
 static inline uint64_t
-rte_combine64ms1b(register uint64_t v)
+rte_combine64ms1b(uint64_t v)
 {
 	v |= v >> 1;
 	v |= v >> 2;
@@ -538,6 +538,9 @@ rte_bsf32_safe(uint64_t v, uint32_t *pos)
 /**
  * Return the rounded-up log2 of a integer.
  *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u32(0) == 0 and not -inf.
+ *
  * @param v
  *     The input parameter.
  * @return
@@ -632,6 +635,9 @@ rte_fls_u64(uint64_t x)
 /**
  * Return the rounded-up log2 of a 64-bit integer.
  *
+ * @note Contrary to the logarithm mathematical operation,
+ * rte_log2_u64(0) == 0 and not -inf.
+ *
  * @param v
  *     The input parameter.
  * @return
diff --git a/dpdk/lib/librte_eal/common/include/rte_eal.h b/dpdk/lib/librte_eal/common/include/rte_eal.h
index 2f9ed298de..58f41d329f 100644
--- a/dpdk/lib/librte_eal/common/include/rte_eal.h
+++ b/dpdk/lib/librte_eal/common/include/rte_eal.h
@@ -138,8 +138,9 @@ int rte_eal_init(int argc, char **argv);
  * be made. It is expected that common usage of this function is to call it
  * just before terminating the process.
  *
- * @return 0 Successfully released all internal EAL resources
- * @return -EFAULT There was an error in releasing all resources.
+ * @return
+ *  - 0 Successfully released all internal EAL resources.
+ *  - -EFAULT There was an error in releasing all resources.
  */
 int rte_eal_cleanup(void);
 
diff --git a/dpdk/lib/librte_eal/common/include/rte_reciprocal.h b/dpdk/lib/librte_eal/common/include/rte_reciprocal.h
index 63e16fde0a..735adb029b 100644
--- a/dpdk/lib/librte_eal/common/include/rte_reciprocal.h
+++ b/dpdk/lib/librte_eal/common/include/rte_reciprocal.h
@@ -27,6 +27,8 @@
 
 #include <stdint.h>
 
+#include <rte_common.h>
+
 struct rte_reciprocal {
 	uint32_t m;
 	uint8_t sh1, sh2;
diff --git a/dpdk/lib/librte_eal/common/include/rte_service.h b/dpdk/lib/librte_eal/common/include/rte_service.h
index d8701dd4cf..e2d0a6dd32 100644
--- a/dpdk/lib/librte_eal/common/include/rte_service.h
+++ b/dpdk/lib/librte_eal/common/include/rte_service.h
@@ -104,12 +104,16 @@ int32_t rte_service_probe_capability(uint32_t id, uint32_t capability);
  * Each core can be added or removed from running a specific service. This
  * function enables or disables *lcore* to run *service_id*.
  *
- * If multiple cores are enabled on a service, an atomic is used to ensure that
- * only one cores runs the service at a time. The exception to this is when
+ * If multiple cores are enabled on a service, a lock is used to ensure that
+ * only one core runs the service at a time. The exception to this is when
  * a service indicates that it is multi-thread safe by setting the capability
  * called RTE_SERVICE_CAP_MT_SAFE. With the multi-thread safe capability set,
  * the service function can be run on multiple threads at the same time.
  *
+ * If the service is known to be mapped to a single lcore, setting the
+ * capability of the service to RTE_SERVICE_CAP_MT_SAFE can achieve
+ * better performance by avoiding the use of lock.
+ *
  * @param service_id the service to apply the lcore to
  * @param lcore The lcore that will be mapped to service
  * @param enable Zero to unmap or disable the core, non-zero to enable
@@ -300,6 +304,10 @@ int32_t rte_service_lcore_count(void);
  * from duty, just unmaps all services / cores, and stops() the service cores.
  * The runstate of services is not modified.
  *
+ * The cores that are stopped with this call, are in FINISHED state and
+ * the application must take care of bringing them back to a launchable state:
+ * e.g. call *rte_eal_lcore_wait* on the lcore_id.
+ *
  * @retval 0 Success
  */
 int32_t rte_service_lcore_reset_all(void);
diff --git a/dpdk/lib/librte_eal/common/include/rte_service_component.h b/dpdk/lib/librte_eal/common/include/rte_service_component.h
index 16eab79eea..9e66ee7e29 100644
--- a/dpdk/lib/librte_eal/common/include/rte_service_component.h
+++ b/dpdk/lib/librte_eal/common/include/rte_service_component.h
@@ -9,6 +9,11 @@
  * Include this file if you are writing a component that requires CPU cycles to
  * operate, and you wish to run the component using service cores
  */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <rte_compat.h>
 #include <rte_service.h>
 
@@ -43,7 +48,7 @@ struct rte_service_spec {
 /**
  * Register a new service.
  *
- * A service represents a component that the requires CPU time periodically to
+ * A service represents a component that requires CPU time periodically to
  * achieve its purpose.
  *
  * For example the eventdev SW PMD requires CPU cycles to perform its
@@ -56,6 +61,10 @@ struct rte_service_spec {
  * *rte_service_component_runstate_set*, which indicates that the service
  * component is ready to be executed.
  *
+ * If the service is known to be mapped to a single lcore, setting the
+ * capability of the service to RTE_SERVICE_CAP_MT_SAFE can achieve
+ * better performance.
+ *
  * @param spec The specification of the service to register
  * @param[out] service_id A pointer to a uint32_t, which will be filled in
  *             during registration of the service. It is set to the integers
@@ -126,4 +135,8 @@ int32_t rte_service_init(void);
  */
 void rte_service_finalize(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _SERVICE_PRIVATE_H_ */
diff --git a/dpdk/lib/librte_eal/common/include/rte_uuid.h b/dpdk/lib/librte_eal/common/include/rte_uuid.h
index 044afbdfab..8b42e070af 100644
--- a/dpdk/lib/librte_eal/common/include/rte_uuid.h
+++ b/dpdk/lib/librte_eal/common/include/rte_uuid.h
@@ -15,6 +15,8 @@ extern "C" {
 #endif
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
 
 /**
  * Struct describing a Universal Unique Identifier
diff --git a/dpdk/lib/librte_eal/common/malloc_elem.c b/dpdk/lib/librte_eal/common/malloc_elem.c
index 885d00424b..a0f2d22774 100644
--- a/dpdk/lib/librte_eal/common/malloc_elem.c
+++ b/dpdk/lib/librte_eal/common/malloc_elem.c
@@ -171,7 +171,7 @@ malloc_elem_insert(struct malloc_elem *elem)
 		next_elem = NULL;
 		heap->last = elem;
 	} else {
-		/* the new memory is somewhere inbetween start and end */
+		/* the new memory is somewhere between start and end */
 		uint64_t dist_from_start, dist_from_end;
 
 		dist_from_end = RTE_PTR_DIFF(heap->last, elem);
@@ -382,14 +382,14 @@ malloc_elem_free_list_index(size_t size)
 		return 0;
 
 	/* Find next power of 2 >= size. */
-	log2 = sizeof(size) * 8 - __builtin_clzl(size-1);
+	log2 = sizeof(size) * 8 - __builtin_clzl(size - 1);
 
 	/* Compute freelist index, based on log2(size). */
 	index = (log2 - MALLOC_MINSIZE_LOG2 + MALLOC_LOG2_INCREMENT - 1) /
-	        MALLOC_LOG2_INCREMENT;
+			MALLOC_LOG2_INCREMENT;
 
-	return index <= RTE_HEAP_NUM_FREELISTS-1?
-	        index: RTE_HEAP_NUM_FREELISTS-1;
+	return index <= RTE_HEAP_NUM_FREELISTS - 1 ?
+			index : RTE_HEAP_NUM_FREELISTS - 1;
 }
 
 /*
diff --git a/dpdk/lib/librte_eal/common/malloc_heap.c b/dpdk/lib/librte_eal/common/malloc_heap.c
index 842eb9de75..bd5065698d 100644
--- a/dpdk/lib/librte_eal/common/malloc_heap.c
+++ b/dpdk/lib/librte_eal/common/malloc_heap.c
@@ -241,6 +241,9 @@ heap_alloc(struct malloc_heap *heap, const char *type __rte_unused, size_t size,
 	size = RTE_CACHE_LINE_ROUNDUP(size);
 	align = RTE_CACHE_LINE_ROUNDUP(align);
 
+	/* roundup might cause an overflow */
+	if (size == 0)
+		return NULL;
 	elem = find_suitable_element(heap, size, flags, align, bound, contig);
 	if (elem != NULL) {
 		elem = malloc_elem_alloc(elem, size, align, bound, contig);
diff --git a/dpdk/lib/librte_eal/common/rte_random.c b/dpdk/lib/librte_eal/common/rte_random.c
index 57ec8fb2b3..b7a089ac4f 100644
--- a/dpdk/lib/librte_eal/common/rte_random.c
+++ b/dpdk/lib/librte_eal/common/rte_random.c
@@ -198,7 +198,7 @@ __rte_random_initial_seed(void)
 		return (uint64_t)rdseed_low | ((uint64_t)rdseed_high << 32);
 #endif
 	/* second fallback: seed using rdtsc */
-	return rte_get_timer_cycles();
+	return rte_get_tsc_cycles();
 }
 
 RTE_INIT(rte_rand_init)
diff --git a/dpdk/lib/librte_eal/common/rte_service.c b/dpdk/lib/librte_eal/common/rte_service.c
index 79235c03f8..8fcccac85c 100644
--- a/dpdk/lib/librte_eal/common/rte_service.c
+++ b/dpdk/lib/librte_eal/common/rte_service.c
@@ -50,6 +50,10 @@ struct rte_service_spec_impl {
 	uint8_t internal_flags;
 
 	/* per service statistics */
+	/* Indicates how many cores the service is mapped to run on.
+	 * It does not indicate the number of cores the service is running
+	 * on currently.
+	 */
 	rte_atomic32_t num_mapped_cores;
 	uint64_t calls;
 	uint64_t cycles_spent;
@@ -122,6 +126,9 @@ rte_service_finalize(void)
 	if (!rte_service_library_initialized)
 		return;
 
+	rte_service_lcore_reset_all();
+	rte_eal_mp_wait_lcore();
+
 	rte_free(rte_services);
 	rte_free(lcore_states);
 
@@ -137,6 +144,12 @@ service_valid(uint32_t id)
 	return !!(rte_services[id].internal_flags & SERVICE_F_REGISTERED);
 }
 
+static struct rte_service_spec_impl *
+service_get(uint32_t id)
+{
+	return &rte_services[id];
+}
+
 /* validate ID and retrieve service pointer, or return error value */
 #define SERVICE_VALID_GET_OR_ERR_RET(id, service, retval) do {          \
 	if (id >= RTE_SERVICE_NUM_MAX || !service_valid(id))            \
@@ -327,8 +340,8 @@ rte_service_runstate_get(uint32_t id)
 }
 
 static inline void
-rte_service_runner_do_callback(struct rte_service_spec_impl *s,
-			       struct core_state *cs, uint32_t service_idx)
+service_runner_do_callback(struct rte_service_spec_impl *s,
+			   struct core_state *cs, uint32_t service_idx)
 {
 	void *userdata = s->spec.callback_userdata;
 
@@ -344,12 +357,14 @@ rte_service_runner_do_callback(struct rte_service_spec_impl *s,
 }
 
 
-static inline int32_t
-service_run(uint32_t i, struct core_state *cs, uint64_t service_mask)
+/* Expects the service 's' is valid. */
+static int32_t
+service_run(uint32_t i, struct core_state *cs, uint64_t service_mask,
+	    struct rte_service_spec_impl *s, uint32_t serialize_mt_unsafe)
 {
-	if (!service_valid(i))
+	if (!s)
 		return -EINVAL;
-	struct rte_service_spec_impl *s = &rte_services[i];
+
 	if (s->comp_runstate != RUNSTATE_RUNNING ||
 			s->app_runstate != RUNSTATE_RUNNING ||
 			!(service_mask & (UINT64_C(1) << i))) {
@@ -359,19 +374,14 @@ service_run(uint32_t i, struct core_state *cs, uint64_t service_mask)
 
 	cs->service_active_on_lcore[i] = 1;
 
-	/* check do we need cmpset, if MT safe or <= 1 core
-	 * mapped, atomic ops are not required.
-	 */
-	const int use_atomics = (service_mt_safe(s) == 0) &&
-				(rte_atomic32_read(&s->num_mapped_cores) > 1);
-	if (use_atomics) {
+	if ((service_mt_safe(s) == 0) && (serialize_mt_unsafe == 1)) {
 		if (!rte_atomic32_cmpset((uint32_t *)&s->execute_lock, 0, 1))
 			return -EBUSY;
 
-		rte_service_runner_do_callback(s, cs, i);
+		service_runner_do_callback(s, cs, i);
 		rte_atomic32_clear(&s->execute_lock);
 	} else
-		rte_service_runner_do_callback(s, cs, i);
+		service_runner_do_callback(s, cs, i);
 
 	return 0;
 }
@@ -383,11 +393,11 @@ rte_service_may_be_active(uint32_t id)
 	int32_t lcore_count = rte_service_lcore_list(ids, RTE_MAX_LCORE);
 	int i;
 
-	if (!service_valid(id))
+	if (id >= RTE_SERVICE_NUM_MAX || !service_valid(id))
 		return -EINVAL;
 
 	for (i = 0; i < lcore_count; i++) {
-		if (lcore_states[i].service_active_on_lcore[id])
+		if (lcore_states[ids[i]].service_active_on_lcore[id])
 			return 1;
 	}
 
@@ -397,49 +407,39 @@ rte_service_may_be_active(uint32_t id)
 int32_t
 rte_service_run_iter_on_app_lcore(uint32_t id, uint32_t serialize_mt_unsafe)
 {
-	/* run service on calling core, using all-ones as the service mask */
-	if (!service_valid(id))
-		return -EINVAL;
-
 	struct core_state *cs = &lcore_states[rte_lcore_id()];
-	struct rte_service_spec_impl *s = &rte_services[id];
+	struct rte_service_spec_impl *s;
 
-	/* Atomically add this core to the mapped cores first, then examine if
-	 * we can run the service. This avoids a race condition between
-	 * checking the value, and atomically adding to the mapped count.
-	 */
-	if (serialize_mt_unsafe)
-		rte_atomic32_inc(&s->num_mapped_cores);
+	SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
 
-	if (service_mt_safe(s) == 0 &&
-			rte_atomic32_read(&s->num_mapped_cores) > 1) {
-		if (serialize_mt_unsafe)
-			rte_atomic32_dec(&s->num_mapped_cores);
-		return -EBUSY;
-	}
+	/* Increment num_mapped_cores to reflect that this core is
+	 * now mapped capable of running the service.
+	 */
+	rte_atomic32_inc(&s->num_mapped_cores);
 
-	int ret = service_run(id, cs, UINT64_MAX);
+	int ret = service_run(id, cs, UINT64_MAX, s, serialize_mt_unsafe);
 
-	if (serialize_mt_unsafe)
-		rte_atomic32_dec(&s->num_mapped_cores);
+	rte_atomic32_dec(&s->num_mapped_cores);
 
 	return ret;
 }
 
 static int32_t
-rte_service_runner_func(void *arg)
+service_runner_func(void *arg)
 {
 	RTE_SET_USED(arg);
 	uint32_t i;
 	const int lcore = rte_lcore_id();
 	struct core_state *cs = &lcore_states[lcore];
 
-	while (lcore_states[lcore].runstate == RUNSTATE_RUNNING) {
+	while (cs->runstate == RUNSTATE_RUNNING) {
 		const uint64_t service_mask = cs->service_mask;
 
 		for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
+			if (!service_valid(i))
+				continue;
 			/* return value ignored as no change to code flow */
-			service_run(i, cs, service_mask);
+			service_run(i, cs, service_mask, service_get(i), 1);
 		}
 
 		cs->loops++;
@@ -447,8 +447,6 @@ rte_service_runner_func(void *arg)
 		rte_smp_rmb();
 	}
 
-	lcore_config[lcore].state = WAIT;
-
 	return 0;
 }
 
@@ -693,9 +691,9 @@ rte_service_lcore_start(uint32_t lcore)
 	/* set core to run state first, and then launch otherwise it will
 	 * return immediately as runstate keeps it in the service poll loop
 	 */
-	lcore_states[lcore].runstate = RUNSTATE_RUNNING;
+	cs->runstate = RUNSTATE_RUNNING;
 
-	int ret = rte_eal_remote_launch(rte_service_runner_func, 0, lcore);
+	int ret = rte_eal_remote_launch(service_runner_func, 0, lcore);
 	/* returns -EBUSY if the core is already launched, 0 on success */
 	return ret;
 }
@@ -774,13 +772,9 @@ rte_service_lcore_attr_get(uint32_t lcore, uint32_t attr_id,
 }
 
 static void
-rte_service_dump_one(FILE *f, struct rte_service_spec_impl *s,
-		     uint64_t all_cycles, uint32_t reset)
+service_dump_one(FILE *f, struct rte_service_spec_impl *s, uint32_t reset)
 {
 	/* avoid divide by zero */
-	if (all_cycles == 0)
-		all_cycles = 1;
-
 	int calls = 1;
 	if (s->calls != 0)
 		calls = s->calls;
@@ -807,7 +801,7 @@ rte_service_attr_reset_all(uint32_t id)
 	SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
 
 	int reset = 1;
-	rte_service_dump_one(NULL, s, 0, reset);
+	service_dump_one(NULL, s, reset);
 	return 0;
 }
 
@@ -851,21 +845,13 @@ rte_service_dump(FILE *f, uint32_t id)
 	uint32_t i;
 	int print_one = (id != UINT32_MAX);
 
-	uint64_t total_cycles = 0;
-
-	for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
-		if (!service_valid(i))
-			continue;
-		total_cycles += rte_services[i].cycles_spent;
-	}
-
 	/* print only the specified service */
 	if (print_one) {
 		struct rte_service_spec_impl *s;
 		SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
 		fprintf(f, "Service %s Summary\n", s->spec.name);
 		uint32_t reset = 0;
-		rte_service_dump_one(f, s, total_cycles, reset);
+		service_dump_one(f, s, reset);
 		return 0;
 	}
 
@@ -875,7 +861,7 @@ rte_service_dump(FILE *f, uint32_t id)
 		if (!service_valid(i))
 			continue;
 		uint32_t reset = 0;
-		rte_service_dump_one(f, &rte_services[i], total_cycles, reset);
+		service_dump_one(f, &rte_services[i], reset);
 	}
 
 	fprintf(f, "Service Cores Summary\n");
diff --git a/dpdk/lib/librte_eal/freebsd/eal/eal.c b/dpdk/lib/librte_eal/freebsd/eal/eal.c
index 6ae37e7e69..2a995ee3f4 100644
--- a/dpdk/lib/librte_eal/freebsd/eal/eal.c
+++ b/dpdk/lib/librte_eal/freebsd/eal/eal.c
@@ -949,7 +949,7 @@ rte_eal_init(int argc, char **argv)
 	 * place, so no cleanup needed.
 	 */
 	if (!internal_config.no_shconf && eal_clean_runtime_dir() < 0) {
-		rte_eal_init_alert("Cannot clear runtime directory\n");
+		rte_eal_init_alert("Cannot clear runtime directory");
 		return -1;
 	}
 
diff --git a/dpdk/lib/librte_eal/freebsd/eal/eal_interrupts.c b/dpdk/lib/librte_eal/freebsd/eal/eal_interrupts.c
index f6831b7902..3fee762be9 100644
--- a/dpdk/lib/librte_eal/freebsd/eal/eal_interrupts.c
+++ b/dpdk/lib/librte_eal/freebsd/eal/eal_interrupts.c
@@ -83,9 +83,9 @@ int
 rte_intr_callback_register(const struct rte_intr_handle *intr_handle,
 		rte_intr_callback_fn cb, void *cb_arg)
 {
-	struct rte_intr_callback *callback = NULL;
-	struct rte_intr_source *src = NULL;
-	int ret, add_event;
+	struct rte_intr_callback *callback;
+	struct rte_intr_source *src;
+	int ret, add_event = 0;
 
 	/* first do parameter checking */
 	if (intr_handle == NULL || intr_handle->fd < 0 || cb == NULL) {
@@ -98,47 +98,53 @@ rte_intr_callback_register(const struct rte_intr_handle *intr_handle,
 		return -ENODEV;
 	}
 
-	/* allocate a new interrupt callback entity */
-	callback = calloc(1, sizeof(*callback));
-	if (callback == NULL) {
-		RTE_LOG(ERR, EAL, "Can not allocate memory\n");
-		return -ENOMEM;
-	}
-	callback->cb_fn = cb;
-	callback->cb_arg = cb_arg;
-	callback->pending_delete = 0;
-	callback->ucb_fn = NULL;
-
 	rte_spinlock_lock(&intr_lock);
 
-	/* check if there is at least one callback registered for the fd */
+	/* find the source for this intr_handle */
 	TAILQ_FOREACH(src, &intr_sources, next) {
-		if (src->intr_handle.fd == intr_handle->fd) {
-			/* we had no interrupts for this */
-			if (TAILQ_EMPTY(&src->callbacks))
-				add_event = 1;
-
-			TAILQ_INSERT_TAIL(&(src->callbacks), callback, next);
-			ret = 0;
+		if (src->intr_handle.fd == intr_handle->fd)
 			break;
-		}
 	}
 
-	/* no existing callbacks for this - add new source */
-	if (src == NULL) {
-		src = calloc(1, sizeof(*src));
-		if (src == NULL) {
+	/* if this is an alarm interrupt and it already has a callback,
+	 * then we don't want to create a new callback because the only
+	 * thing on the list should be eal_alarm_callback() and we may
+	 * be called just to reset the timer.
+	 */
+	if (src != NULL && src->intr_handle.type == RTE_INTR_HANDLE_ALARM &&
+		 !TAILQ_EMPTY(&src->callbacks)) {
+		callback = NULL;
+	} else {
+		/* allocate a new interrupt callback entity */
+		callback = calloc(1, sizeof(*callback));
+		if (callback == NULL) {
 			RTE_LOG(ERR, EAL, "Can not allocate memory\n");
 			ret = -ENOMEM;
 			goto fail;
-		} else {
-			src->intr_handle = *intr_handle;
-			TAILQ_INIT(&src->callbacks);
-			TAILQ_INSERT_TAIL(&(src->callbacks), callback, next);
-			TAILQ_INSERT_TAIL(&intr_sources, src, next);
-			add_event = 1;
-			ret = 0;
 		}
+		callback->cb_fn = cb;
+		callback->cb_arg = cb_arg;
+		callback->pending_delete = 0;
+		callback->ucb_fn = NULL;
+
+		if (src == NULL) {
+			src = calloc(1, sizeof(*src));
+			if (src == NULL) {
+				RTE_LOG(ERR, EAL, "Can not allocate memory\n");
+				ret = -ENOMEM;
+				goto fail;
+			} else {
+				src->intr_handle = *intr_handle;
+				TAILQ_INIT(&src->callbacks);
+				TAILQ_INSERT_TAIL(&intr_sources, src, next);
+			}
+		}
+
+		/* we had no interrupts for this */
+		if (TAILQ_EMPTY(&src->callbacks))
+			add_event = 1;
+
+		TAILQ_INSERT_TAIL(&(src->callbacks), callback, next);
 	}
 
 	/* add events to the queue. timer events are special as we need to
@@ -178,11 +184,12 @@ rte_intr_callback_register(const struct rte_intr_handle *intr_handle,
 	}
 	rte_spinlock_unlock(&intr_lock);
 
-	return ret;
+	return 0;
 fail:
 	/* clean up */
 	if (src != NULL) {
-		TAILQ_REMOVE(&(src->callbacks), callback, next);
+		if (callback != NULL)
+			TAILQ_REMOVE(&(src->callbacks), callback, next);
 		if (TAILQ_EMPTY(&(src->callbacks))) {
 			TAILQ_REMOVE(&intr_sources, src, next);
 			free(src);
diff --git a/dpdk/lib/librte_eal/freebsd/eal/eal_memory.c b/dpdk/lib/librte_eal/freebsd/eal/eal_memory.c
index a97d8f0f0c..fb1549fbe6 100644
--- a/dpdk/lib/librte_eal/freebsd/eal/eal_memory.c
+++ b/dpdk/lib/librte_eal/freebsd/eal/eal_memory.c
@@ -193,7 +193,7 @@ rte_eal_hugepage_init(void)
 			if (msl_idx == RTE_MAX_MEMSEG_LISTS) {
 				RTE_LOG(ERR, EAL, "Could not find space for memseg. Please increase %s and/or %s in configuration.\n",
 					RTE_STR(CONFIG_RTE_MAX_MEMSEG_PER_TYPE),
-					RTE_STR(CONFIG_RTE_MAX_MEM_PER_TYPE));
+					RTE_STR(CONFIG_RTE_MAX_MEM_MB_PER_TYPE));
 				return -1;
 			}
 			arr = &msl->memseg_arr;
@@ -449,7 +449,7 @@ memseg_primary_init(void)
 		 *
 		 * we need (N*2)-1 segments because we cannot guarantee that
 		 * each segment will be IOVA-contiguous with the previous one,
-		 * so we will allocate more and put spaces inbetween segments
+		 * so we will allocate more and put spaces between segments
 		 * that are non-contiguous.
 		 */
 		avail_segs = (hpi->num_pages[0] * 2) - 1;
diff --git a/dpdk/lib/librte_eal/linux/eal/eal.c b/dpdk/lib/librte_eal/linux/eal/eal.c
index c4233ec3c8..8f1bcab390 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal.c
@@ -25,6 +25,7 @@
 #if defined(RTE_ARCH_X86)
 #include <sys/io.h>
 #endif
+#include <linux/version.h>
 
 #include <rte_compat.h>
 #include <rte_common.h>
@@ -1076,7 +1077,7 @@ rte_eal_init(int argc, char **argv)
 #if defined(RTE_LIBRTE_KNI) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)
 			} else if (rte_eal_check_module("rte_kni") == 1) {
 				iova_mode = RTE_IOVA_PA;
-				RTE_LOG(DEBUG, EAL, "KNI is loaded, selecting IOVA as PA mode for better KNI perfomance.\n");
+				RTE_LOG(DEBUG, EAL, "KNI is loaded, selecting IOVA as PA mode for better KNI performance.\n");
 #endif
 			} else if (is_iommu_enabled()) {
 				/* we have an IOMMU, pick IOVA as VA mode */
@@ -1287,7 +1288,7 @@ rte_eal_init(int argc, char **argv)
 	 * place, so no cleanup needed.
 	 */
 	if (!internal_config.no_shconf && eal_clean_runtime_dir() < 0) {
-		rte_eal_init_alert("Cannot clear runtime directory\n");
+		rte_eal_init_alert("Cannot clear runtime directory");
 		return -1;
 	}
 
diff --git a/dpdk/lib/librte_eal/linux/eal/eal_dev.c b/dpdk/lib/librte_eal/linux/eal/eal_dev.c
index 83c9cd6607..803979ff46 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal_dev.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal_dev.c
@@ -189,7 +189,7 @@ dev_uev_parse(const char *buf, struct rte_dev_event *event, int length)
 	else if (!strncmp(subsystem, "vfio", 4))
 		event->subsystem = EAL_DEV_EVENT_SUBSYSTEM_VFIO;
 	else
-		return -1;
+		goto err;
 
 	/* parse the action type */
 	if (!strncmp(action, "add", 3))
@@ -197,8 +197,11 @@ dev_uev_parse(const char *buf, struct rte_dev_event *event, int length)
 	else if (!strncmp(action, "remove", 6))
 		event->type = RTE_DEV_EVENT_REMOVE;
 	else
-		return -1;
+		goto err;
 	return 0;
+err:
+	free(event->devname);
+	return -1;
 }
 
 static void
@@ -234,8 +237,7 @@ dev_uev_handler(__rte_unused void *param)
 
 	ret = dev_uev_parse(buf, &uevent, EAL_UEV_MSG_LEN);
 	if (ret < 0) {
-		RTE_LOG(DEBUG, EAL, "It is not an valid event "
-			"that need to be handle.\n");
+		RTE_LOG(DEBUG, EAL, "Ignoring uevent '%s'\n", buf);
 		return;
 	}
 
@@ -277,12 +279,14 @@ dev_uev_handler(__rte_unused void *param)
 			rte_spinlock_unlock(&failure_handle_lock);
 		}
 		rte_dev_event_callback_process(uevent.devname, uevent.type);
+		free(uevent.devname);
 	}
 
 	return;
 
 failure_handle_err:
 	rte_spinlock_unlock(&failure_handle_lock);
+	free(uevent.devname);
 }
 
 int
diff --git a/dpdk/lib/librte_eal/linux/eal/eal_interrupts.c b/dpdk/lib/librte_eal/linux/eal/eal_interrupts.c
index 1955324d30..e570c0684e 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal_interrupts.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal_interrupts.c
@@ -984,7 +984,7 @@ eal_intr_process_interrupts(struct epoll_event *events, int nfds)
 		}
 
 		/* notify the pipe fd waited by epoll_wait to rebuild the wait list */
-		if (rv >= 0 && write(intr_pipe.writefd, "1", 1) < 0) {
+		if (rv > 0 && write(intr_pipe.writefd, "1", 1) < 0) {
 			rte_spinlock_unlock(&intr_lock);
 			return -EPIPE;
 		}
@@ -1045,8 +1045,6 @@ eal_intr_handle_interrupts(int pfd, unsigned totalfds)
 static __attribute__((noreturn)) void *
 eal_intr_thread_main(__rte_unused void *arg)
 {
-	struct epoll_event ev;
-
 	/* host thread, never break out */
 	for (;;) {
 		/* build up the epoll fd with all descriptors we are to
@@ -1078,8 +1076,11 @@ eal_intr_thread_main(__rte_unused void *arg)
 		rte_spinlock_lock(&intr_lock);
 
 		TAILQ_FOREACH(src, &intr_sources, next) {
+			struct epoll_event ev;
+
 			if (src->callbacks.tqh_first == NULL)
 				continue; /* skip those with no callbacks */
+			memset(&ev, 0, sizeof(ev));
 			ev.events = EPOLLIN | EPOLLPRI | EPOLLRDHUP | EPOLLHUP;
 			ev.data.fd = src->intr_handle.fd;
 
@@ -1204,7 +1205,7 @@ eal_epoll_process_event(struct epoll_event *evs, unsigned int n,
 		events[count].status        = RTE_EPOLL_VALID;
 		events[count].fd            = rev->fd;
 		events[count].epfd          = rev->epfd;
-		events[count].epdata.event  = rev->epdata.event;
+		events[count].epdata.event  = evs[i].events;
 		events[count].epdata.data   = rev->epdata.data;
 		if (rev->epdata.cb_fun)
 			rev->epdata.cb_fun(rev->fd,
diff --git a/dpdk/lib/librte_eal/linux/eal/eal_memalloc.c b/dpdk/lib/librte_eal/linux/eal/eal_memalloc.c
index af6d0d023a..22f1ff68eb 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal_memalloc.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal_memalloc.c
@@ -325,6 +325,21 @@ get_seg_fd(char *path, int buflen, struct hugepage_info *hi,
 		fd = fd_list[list_idx].fds[seg_idx];
 
 		if (fd < 0) {
+			/* A primary process is the only one creating these
+			 * files. If there is a leftover that was not cleaned
+			 * by clear_hugedir(), we must *now* make sure to drop
+			 * the file or we will remap old stuff while the rest
+			 * of the code is built on the assumption that a new
+			 * page is clean.
+			 */
+			if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
+					unlink(path) == -1 &&
+					errno != ENOENT) {
+				RTE_LOG(DEBUG, EAL, "%s(): could not remove '%s': %s\n",
+					__func__, path, strerror(errno));
+				return -1;
+			}
+
 			fd = open(path, O_CREAT | O_RDWR, 0600);
 			if (fd < 0) {
 				RTE_LOG(DEBUG, EAL, "%s(): open failed: %s\n",
@@ -599,17 +614,25 @@ alloc_seg(struct rte_memseg *ms, void *addr, int socket_id,
 	}
 
 #ifdef RTE_EAL_NUMA_AWARE_HUGEPAGES
-	ret = get_mempolicy(&cur_socket_id, NULL, 0, addr,
-			    MPOL_F_NODE | MPOL_F_ADDR);
-	if (ret < 0) {
-		RTE_LOG(DEBUG, EAL, "%s(): get_mempolicy: %s\n",
-			__func__, strerror(errno));
-		goto mapped;
-	} else if (cur_socket_id != socket_id) {
-		RTE_LOG(DEBUG, EAL,
-				"%s(): allocation happened on wrong socket (wanted %d, got %d)\n",
-			__func__, socket_id, cur_socket_id);
-		goto mapped;
+	/*
+	 * If the kernel has been built without NUMA support, get_mempolicy()
+	 * will return an error. If check_numa() returns false, memory
+	 * allocation is not NUMA aware and the socket_id should not be
+	 * checked.
+	 */
+	if (check_numa()) {
+		ret = get_mempolicy(&cur_socket_id, NULL, 0, addr,
+					MPOL_F_NODE | MPOL_F_ADDR);
+		if (ret < 0) {
+			RTE_LOG(DEBUG, EAL, "%s(): get_mempolicy: %s\n",
+				__func__, strerror(errno));
+			goto mapped;
+		} else if (cur_socket_id != socket_id) {
+			RTE_LOG(DEBUG, EAL,
+					"%s(): allocation happened on wrong socket (wanted %d, got %d)\n",
+				__func__, socket_id, cur_socket_id);
+			goto mapped;
+		}
 	}
 #else
 	if (rte_socket_count() > 1)
@@ -680,13 +703,16 @@ free_seg(struct rte_memseg *ms, struct hugepage_info *hi,
 	/* erase page data */
 	memset(ms->addr, 0, ms->len);
 
-	if (mmap(ms->addr, ms->len, PROT_READ,
+	if (mmap(ms->addr, ms->len, PROT_NONE,
 			MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) ==
 				MAP_FAILED) {
 		RTE_LOG(DEBUG, EAL, "couldn't unmap page\n");
 		return -1;
 	}
 
+	if (madvise(ms->addr, ms->len, MADV_DONTDUMP) != 0)
+		RTE_LOG(DEBUG, EAL, "madvise failed: %s\n", strerror(errno));
+
 	exit_early = false;
 
 	/* if we're using anonymous hugepages, nothing to be done */
diff --git a/dpdk/lib/librte_eal/linux/eal/eal_memory.c b/dpdk/lib/librte_eal/linux/eal/eal_memory.c
index 43e4ffc757..c93d9bb2b8 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal_memory.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal_memory.c
@@ -703,7 +703,7 @@ remap_segment(struct hugepage_file *hugepages, int seg_start, int seg_end)
 	if (msl_idx == RTE_MAX_MEMSEG_LISTS) {
 		RTE_LOG(ERR, EAL, "Could not find space for memseg. Please increase %s and/or %s in configuration.\n",
 				RTE_STR(CONFIG_RTE_MAX_MEMSEG_PER_TYPE),
-				RTE_STR(CONFIG_RTE_MAX_MEM_PER_TYPE));
+				RTE_STR(CONFIG_RTE_MAX_MEM_MB_PER_TYPE));
 		return -1;
 	}
 
@@ -1340,6 +1340,8 @@ eal_legacy_hugepage_init(void)
 
 	/* hugetlbfs can be disabled */
 	if (internal_config.no_hugetlbfs) {
+		void *prealloc_addr;
+		size_t mem_sz;
 		struct rte_memseg_list *msl;
 		int n_segs, cur_seg, fd, flags;
 #ifdef MEMFD_SUPPORTED
@@ -1395,17 +1397,31 @@ eal_legacy_hugepage_init(void)
 			}
 		}
 #endif
-		addr = mmap(NULL, internal_config.memory, PROT_READ | PROT_WRITE,
-				flags, fd, 0);
-		if (addr == MAP_FAILED) {
+		/* preallocate address space for the memory, so that it can be
+		 * fit into the DMA mask.
+		 */
+		mem_sz = internal_config.memory;
+		prealloc_addr = eal_get_virtual_area(
+				NULL, &mem_sz, page_sz, 0, 0);
+		if (prealloc_addr == NULL) {
+			RTE_LOG(ERR, EAL,
+					"%s: reserving memory area failed: "
+					"%s\n",
+					__func__, strerror(errno));
+			return -1;
+		}
+		addr = mmap(prealloc_addr, mem_sz, PROT_READ | PROT_WRITE,
+				flags | MAP_FIXED, fd, 0);
+		if (addr == MAP_FAILED || addr != prealloc_addr) {
 			RTE_LOG(ERR, EAL, "%s: mmap() failed: %s\n", __func__,
 					strerror(errno));
+			munmap(prealloc_addr, mem_sz);
 			return -1;
 		}
 		msl->base_va = addr;
 		msl->page_sz = page_sz;
 		msl->socket_id = 0;
-		msl->len = internal_config.memory;
+		msl->len = mem_sz;
 		msl->heap = 1;
 
 		/* we're in single-file segments mode, so only the segment list
@@ -1928,7 +1944,7 @@ eal_legacy_hugepage_attach(void)
 		if (flock(fd, LOCK_SH) < 0) {
 			RTE_LOG(DEBUG, EAL, "%s(): Locking file failed: %s\n",
 				__func__, strerror(errno));
-			goto fd_error;
+			goto mmap_error;
 		}
 
 		/* find segment data */
@@ -1936,13 +1952,13 @@ eal_legacy_hugepage_attach(void)
 		if (msl == NULL) {
 			RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg list\n",
 				__func__);
-			goto fd_error;
+			goto mmap_error;
 		}
 		ms = rte_mem_virt2memseg(map_addr, msl);
 		if (ms == NULL) {
 			RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg\n",
 				__func__);
-			goto fd_error;
+			goto mmap_error;
 		}
 
 		msl_idx = msl - mcfg->memsegs;
@@ -1950,7 +1966,7 @@ eal_legacy_hugepage_attach(void)
 		if (ms_idx < 0) {
 			RTE_LOG(DEBUG, EAL, "%s(): Cannot find memseg idx\n",
 				__func__);
-			goto fd_error;
+			goto mmap_error;
 		}
 
 		/* store segment fd internally */
@@ -1963,18 +1979,15 @@ eal_legacy_hugepage_attach(void)
 	close(fd_hugepage);
 	return 0;
 
+mmap_error:
+	munmap(hp[i].final_va, hp[i].size);
 fd_error:
 	close(fd);
 error:
-	/* map all segments into memory to make sure we get the addrs */
-	cur_seg = 0;
-	for (cur_seg = 0; cur_seg < i; cur_seg++) {
-		struct hugepage_file *hf = &hp[i];
-		size_t map_sz = hf->size;
-		void *map_addr = hf->final_va;
+	/* unwind mmap's done so far */
+	for (cur_seg = 0; cur_seg < i; cur_seg++)
+		munmap(hp[cur_seg].final_va, hp[cur_seg].size);
 
-		munmap(map_addr, map_sz);
-	}
 	if (hp != NULL && hp != MAP_FAILED)
 		munmap(hp, size);
 	if (fd_hugepage >= 0)
diff --git a/dpdk/lib/librte_eal/linux/eal/eal_vfio.c b/dpdk/lib/librte_eal/linux/eal/eal_vfio.c
index 95f615c2e3..1be02e7f13 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal_vfio.c
@@ -293,7 +293,7 @@ vfio_open_group_fd(int iommu_group_num)
 							strerror(errno));
 					return -1;
 				}
-				return 0;
+				return -ENOENT;
 			}
 			/* noiommu group found */
 		}
@@ -318,12 +318,12 @@ vfio_open_group_fd(int iommu_group_num)
 			vfio_group_fd = mp_rep->fds[0];
 		} else if (p->result == SOCKET_NO_FD) {
 			RTE_LOG(ERR, EAL, "  bad VFIO group fd\n");
-			vfio_group_fd = 0;
+			vfio_group_fd = -ENOENT;
 		}
 	}
 
 	free(mp_reply.msgs);
-	if (vfio_group_fd < 0)
+	if (vfio_group_fd < 0 && vfio_group_fd != -ENOENT)
 		RTE_LOG(ERR, EAL, "  cannot request group fd\n");
 	return vfio_group_fd;
 }
@@ -381,7 +381,7 @@ vfio_get_group_fd(struct vfio_config *vfio_cfg,
 	vfio_group_fd = vfio_open_group_fd(iommu_group_num);
 	if (vfio_group_fd < 0) {
 		RTE_LOG(ERR, EAL, "Failed to open group %d\n", iommu_group_num);
-		return -1;
+		return vfio_group_fd;
 	}
 
 	cur_grp->group_num = iommu_group_num;
@@ -514,9 +514,11 @@ static void
 vfio_mem_event_callback(enum rte_mem_event type, const void *addr, size_t len,
 		void *arg __rte_unused)
 {
+	rte_iova_t iova_start, iova_expected;
 	struct rte_memseg_list *msl;
 	struct rte_memseg *ms;
 	size_t cur_len = 0;
+	uint64_t va_start;
 
 	msl = rte_mem_virt2memseg_list(addr);
 
@@ -532,25 +534,88 @@ vfio_mem_event_callback(enum rte_mem_event type, const void *addr, size_t len,
 		return;
 	}
 
+#ifdef RTE_ARCH_PPC_64
+	ms = rte_mem_virt2memseg(addr, msl);
+	while (cur_len < len) {
+		int idx = rte_fbarray_find_idx(&msl->memseg_arr, ms);
+
+		rte_fbarray_set_free(&msl->memseg_arr, idx);
+		cur_len += ms->len;
+		++ms;
+	}
+	cur_len = 0;
+#endif
 	/* memsegs are contiguous in memory */
 	ms = rte_mem_virt2memseg(addr, msl);
+
+	/*
+	 * This memory is not guaranteed to be contiguous, but it still could
+	 * be, or it could have some small contiguous chunks. Since the number
+	 * of VFIO mappings is limited, and VFIO appears to not concatenate
+	 * adjacent mappings, we have to do this ourselves.
+	 *
+	 * So, find contiguous chunks, then map them.
+	 */
+	va_start = ms->addr_64;
+	iova_start = iova_expected = ms->iova;
 	while (cur_len < len) {
+		bool new_contig_area = ms->iova != iova_expected;
+		bool last_seg = (len - cur_len) == ms->len;
+		bool skip_last = false;
+
+		/* only do mappings when current contiguous area ends */
+		if (new_contig_area) {
+			if (type == RTE_MEM_EVENT_ALLOC)
+				vfio_dma_mem_map(default_vfio_cfg, va_start,
+						iova_start,
+						iova_expected - iova_start, 1);
+			else
+				vfio_dma_mem_map(default_vfio_cfg, va_start,
+						iova_start,
+						iova_expected - iova_start, 0);
+			va_start = ms->addr_64;
+			iova_start = ms->iova;
+		}
 		/* some memory segments may have invalid IOVA */
 		if (ms->iova == RTE_BAD_IOVA) {
 			RTE_LOG(DEBUG, EAL, "Memory segment at %p has bad IOVA, skipping\n",
 					ms->addr);
-			goto next;
+			skip_last = true;
 		}
-		if (type == RTE_MEM_EVENT_ALLOC)
-			vfio_dma_mem_map(default_vfio_cfg, ms->addr_64,
-					ms->iova, ms->len, 1);
-		else
-			vfio_dma_mem_map(default_vfio_cfg, ms->addr_64,
-					ms->iova, ms->len, 0);
-next:
+		iova_expected = ms->iova + ms->len;
+		cur_len += ms->len;
+		++ms;
+
+		/*
+		 * don't count previous segment, and don't attempt to
+		 * dereference a potentially invalid pointer.
+		 */
+		if (skip_last && !last_seg) {
+			iova_expected = iova_start = ms->iova;
+			va_start = ms->addr_64;
+		} else if (!skip_last && last_seg) {
+			/* this is the last segment and we're not skipping */
+			if (type == RTE_MEM_EVENT_ALLOC)
+				vfio_dma_mem_map(default_vfio_cfg, va_start,
+						iova_start,
+						iova_expected - iova_start, 1);
+			else
+				vfio_dma_mem_map(default_vfio_cfg, va_start,
+						iova_start,
+						iova_expected - iova_start, 0);
+		}
+	}
+#ifdef RTE_ARCH_PPC_64
+	cur_len = 0;
+	ms = rte_mem_virt2memseg(addr, msl);
+	while (cur_len < len) {
+		int idx = rte_fbarray_find_idx(&msl->memseg_arr, ms);
+
+		rte_fbarray_set_used(&msl->memseg_arr, idx);
 		cur_len += ms->len;
 		++ms;
 	}
+#endif
 }
 
 static int
@@ -663,11 +728,14 @@ rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
 
 	/* get the actual group fd */
 	vfio_group_fd = rte_vfio_get_group_fd(iommu_group_num);
-	if (vfio_group_fd < 0)
+	if (vfio_group_fd < 0 && vfio_group_fd != -ENOENT)
 		return -1;
 
-	/* if group_fd == 0, that means the device isn't managed by VFIO */
-	if (vfio_group_fd == 0) {
+	/*
+	 * if vfio_group_fd == -ENOENT, that means the device
+	 * isn't managed by VFIO
+	 */
+	if (vfio_group_fd == -ENOENT) {
 		RTE_LOG(WARNING, EAL, " %s not managed by VFIO driver, skipping\n",
 				dev_addr);
 		return 1;
@@ -864,9 +932,6 @@ int
 rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 		    int vfio_dev_fd)
 {
-	struct vfio_group_status group_status = {
-			.argsz = sizeof(group_status)
-	};
 	struct vfio_config *vfio_cfg;
 	int vfio_group_fd;
 	int iommu_group_num;
@@ -890,10 +955,10 @@ rte_vfio_release_device(const char *sysfs_base, const char *dev_addr,
 
 	/* get the actual group fd */
 	vfio_group_fd = rte_vfio_get_group_fd(iommu_group_num);
-	if (vfio_group_fd <= 0) {
+	if (vfio_group_fd < 0) {
 		RTE_LOG(INFO, EAL, "rte_vfio_get_group_fd failed for %s\n",
 				   dev_addr);
-		ret = -1;
+		ret = vfio_group_fd;
 		goto out;
 	}
 
@@ -1027,6 +1092,7 @@ vfio_get_default_container_fd(void)
 	struct rte_mp_reply mp_reply = {0};
 	struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
 	struct vfio_mp_param *p = (struct vfio_mp_param *)mp_req.param;
+	int container_fd;
 
 	if (default_vfio_cfg->vfio_enabled)
 		return default_vfio_cfg->vfio_container_fd;
@@ -1049,8 +1115,9 @@ vfio_get_default_container_fd(void)
 		mp_rep = &mp_reply.msgs[0];
 		p = (struct vfio_mp_param *)mp_rep->param;
 		if (p->result == SOCKET_OK && mp_rep->num_fds == 1) {
+			container_fd = mp_rep->fds[0];
 			free(mp_reply.msgs);
-			return mp_rep->fds[0];
+			return container_fd;
 		}
 	}
 
@@ -1416,16 +1483,11 @@ vfio_spapr_dma_do_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
 	return 0;
 }
 
-struct spapr_remap_walk_param {
-	int vfio_container_fd;
-	uint64_t addr_64;
-};
-
 static int
 vfio_spapr_map_walk(const struct rte_memseg_list *msl,
 		const struct rte_memseg *ms, void *arg)
 {
-	struct spapr_remap_walk_param *param = arg;
+	int *vfio_container_fd = arg;
 
 	/* skip external memory that isn't a heap */
 	if (msl->external && !msl->heap)
@@ -1435,10 +1497,7 @@ vfio_spapr_map_walk(const struct rte_memseg_list *msl,
 	if (ms->iova == RTE_BAD_IOVA)
 		return 0;
 
-	if (ms->addr_64 == param->addr_64)
-		return 0;
-
-	return vfio_spapr_dma_do_map(param->vfio_container_fd, ms->addr_64, ms->iova,
+	return vfio_spapr_dma_do_map(*vfio_container_fd, ms->addr_64, ms->iova,
 			ms->len, 1);
 }
 
@@ -1446,7 +1505,7 @@ static int
 vfio_spapr_unmap_walk(const struct rte_memseg_list *msl,
 		const struct rte_memseg *ms, void *arg)
 {
-	struct spapr_remap_walk_param *param = arg;
+	int *vfio_container_fd = arg;
 
 	/* skip external memory that isn't a heap */
 	if (msl->external && !msl->heap)
@@ -1456,17 +1515,13 @@ vfio_spapr_unmap_walk(const struct rte_memseg_list *msl,
 	if (ms->iova == RTE_BAD_IOVA)
 		return 0;
 
-	if (ms->addr_64 == param->addr_64)
-		return 0;
-
-	return vfio_spapr_dma_do_map(param->vfio_container_fd, ms->addr_64, ms->iova,
+	return vfio_spapr_dma_do_map(*vfio_container_fd, ms->addr_64, ms->iova,
 			ms->len, 0);
 }
 
 struct spapr_walk_param {
 	uint64_t window_size;
 	uint64_t hugepage_sz;
-	uint64_t addr_64;
 };
 
 static int
@@ -1484,10 +1539,6 @@ vfio_spapr_window_size_walk(const struct rte_memseg_list *msl,
 	if (ms->iova == RTE_BAD_IOVA)
 		return 0;
 
-	/* do not iterate ms we haven't mapped yet  */
-	if (param->addr_64 && ms->addr_64 == param->addr_64)
-		return 0;
-
 	if (max > param->window_size) {
 		param->hugepage_sz = ms->hugepage_sz;
 		param->window_size = max;
@@ -1531,20 +1582,11 @@ vfio_spapr_create_new_dma_window(int vfio_container_fd,
 		/* try possible page_shift and levels for workaround */
 		uint32_t levels;
 
-		for (levels = 1; levels <= info.ddw.levels; levels++) {
-			uint32_t pgsizes = info.ddw.pgsizes;
-
-			while (pgsizes != 0) {
-				create->page_shift = 31 - __builtin_clz(pgsizes);
-				create->levels = levels;
-				ret = ioctl(vfio_container_fd,
-					VFIO_IOMMU_SPAPR_TCE_CREATE, create);
-				if (!ret)
-					break;
-				pgsizes &= ~(1 << create->page_shift);
-			}
-			if (!ret)
-				break;
+		for (levels = create->levels + 1;
+			ret && levels <= info.ddw.levels; levels++) {
+			create->levels = levels;
+			ret = ioctl(vfio_container_fd,
+				VFIO_IOMMU_SPAPR_TCE_CREATE, create);
 		}
 #endif
 		if (ret) {
@@ -1585,7 +1627,6 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
 
 	/* check if window size needs to be adjusted */
 	memset(&param, 0, sizeof(param));
-	param.addr_64 = vaddr;
 
 	/* we're inside a callback so use thread-unsafe version */
 	if (rte_memseg_walk_thread_unsafe(vfio_spapr_window_size_walk,
@@ -1610,14 +1651,9 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
 	if (do_map) {
 		/* re-create window and remap the entire memory */
 		if (iova + len > create.window_size) {
-			struct spapr_remap_walk_param remap_param = {
-				.vfio_container_fd = vfio_container_fd,
-				.addr_64 = vaddr,
-			};
-
 			/* release all maps before recreating the window */
 			if (rte_memseg_walk_thread_unsafe(vfio_spapr_unmap_walk,
-					&remap_param) < 0) {
+					&vfio_container_fd) < 0) {
 				RTE_LOG(ERR, EAL, "Could not release DMA maps\n");
 				ret = -1;
 				goto out;
@@ -1644,7 +1680,7 @@ vfio_spapr_dma_mem_map(int vfio_container_fd, uint64_t vaddr, uint64_t iova,
 			/* we're inside a callback, so use thread-unsafe version
 			 */
 			if (rte_memseg_walk_thread_unsafe(vfio_spapr_map_walk,
-					&remap_param) < 0) {
+					&vfio_container_fd) < 0) {
 				RTE_LOG(ERR, EAL, "Could not recreate DMA maps\n");
 				ret = -1;
 				goto out;
@@ -1691,7 +1727,6 @@ vfio_spapr_dma_map(int vfio_container_fd)
 	struct spapr_walk_param param;
 
 	memset(&param, 0, sizeof(param));
-	param.addr_64 = 0UL;
 
 	/* create DMA window from 0 to max(phys_addr + len) */
 	rte_memseg_walk(vfio_spapr_window_size_walk, &param);
diff --git a/dpdk/lib/librte_eal/linux/eal/eal_vfio_mp_sync.c b/dpdk/lib/librte_eal/linux/eal/eal_vfio_mp_sync.c
index 5f2a5fc1d9..6254696ae5 100644
--- a/dpdk/lib/librte_eal/linux/eal/eal_vfio_mp_sync.c
+++ b/dpdk/lib/librte_eal/linux/eal/eal_vfio_mp_sync.c
@@ -44,9 +44,9 @@ vfio_mp_primary(const struct rte_mp_msg *msg, const void *peer)
 		r->req = SOCKET_REQ_GROUP;
 		r->group_num = m->group_num;
 		fd = rte_vfio_get_group_fd(m->group_num);
-		if (fd < 0)
+		if (fd < 0 && fd != -ENOENT)
 			r->result = SOCKET_ERR;
-		else if (fd == 0)
+		else if (fd == -ENOENT)
 			/* if VFIO group exists but isn't bound to VFIO driver */
 			r->result = SOCKET_NO_FD;
 		else {
diff --git a/dpdk/lib/librte_eal/rte_eal_exports.def b/dpdk/lib/librte_eal/rte_eal_exports.def
index 12a6c79d6a..c1bdee1c40 100644
--- a/dpdk/lib/librte_eal/rte_eal_exports.def
+++ b/dpdk/lib/librte_eal/rte_eal_exports.def
@@ -1,6 +1,5 @@
 EXPORTS
 	__rte_panic
-	rte_eal_get_configuration
 	rte_eal_init
 	rte_eal_mp_remote_launch
 	rte_eal_mp_wait_lcore
diff --git a/dpdk/lib/librte_eal/windows/eal/include/sched.h b/dpdk/lib/librte_eal/windows/eal/include/sched.h
index 257060594c..29868c93d1 100644
--- a/dpdk/lib/librte_eal/windows/eal/include/sched.h
+++ b/dpdk/lib/librte_eal/windows/eal/include/sched.h
@@ -14,8 +14,8 @@
 extern "C" {
 #endif
 
-#ifndef CPU_SET_SIZE
-#define CPU_SET_SIZE RTE_MAX_LCORE
+#ifndef CPU_SETSIZE
+#define CPU_SETSIZE RTE_MAX_LCORE
 #endif
 
 #define _BITS_PER_SET (sizeof(long long) * 8)
@@ -26,7 +26,7 @@ extern "C" {
 #define _WHICH_BIT(b) ((b) & (_BITS_PER_SET - 1))
 
 typedef struct _rte_cpuset_s {
-	long long _bits[_NUM_SETS(CPU_SET_SIZE)];
+	long long _bits[_NUM_SETS(CPU_SETSIZE)];
 } rte_cpuset_t;
 
 #define CPU_SET(b, s) ((s)->_bits[_WHICH_SET(b)] |= (1LL << _WHICH_BIT(b)))
@@ -35,7 +35,7 @@ typedef struct _rte_cpuset_s {
 	do {								\
 		unsigned int _i;					\
 									\
-		for (_i = 0; _i < _NUM_SETS(CPU_SET_SIZE); _i++)	\
+		for (_i = 0; _i < _NUM_SETS(CPU_SETSIZE); _i++)		\
 			(s)->_bits[_i] = 0LL;				\
 	} while (0)
 
diff --git a/dpdk/lib/librte_efd/rte_efd.c b/dpdk/lib/librte_efd/rte_efd.c
index 4deeb17924..3fd1f1c97b 100644
--- a/dpdk/lib/librte_efd/rte_efd.c
+++ b/dpdk/lib/librte_efd/rte_efd.c
@@ -707,6 +707,7 @@ rte_efd_create(const char *name, uint32_t max_num_rules, uint32_t key_len,
 
 error_unlock_exit:
 	rte_mcfg_tailq_write_unlock();
+	rte_free(te);
 	rte_efd_free(table);
 
 	return NULL;
diff --git a/dpdk/lib/librte_ethdev/ethdev_profile.h b/dpdk/lib/librte_ethdev/ethdev_profile.h
index 65031e6f3f..e5ee4df824 100644
--- a/dpdk/lib/librte_ethdev/ethdev_profile.h
+++ b/dpdk/lib/librte_ethdev/ethdev_profile.h
@@ -24,4 +24,13 @@
 int
 __rte_eth_dev_profile_init(uint16_t port_id, struct rte_eth_dev *dev);
 
+#ifdef RTE_ETHDEV_PROFILE_WITH_VTUNE
+
+uint16_t
+profile_hook_rx_burst_cb(uint16_t port_id, uint16_t queue_id,
+	struct rte_mbuf *pkts[], uint16_t nb_pkts,
+	uint16_t max_pkts, void *user_param);
+
+#endif /* RTE_ETHDEV_PROFILE_WITH_VTUNE */
+
 #endif
diff --git a/dpdk/lib/librte_ethdev/rte_eth_ctrl.h b/dpdk/lib/librte_ethdev/rte_eth_ctrl.h
index 1416c371fb..906cd4f458 100644
--- a/dpdk/lib/librte_ethdev/rte_eth_ctrl.h
+++ b/dpdk/lib/librte_ethdev/rte_eth_ctrl.h
@@ -9,6 +9,7 @@
 #include <rte_common.h>
 #include <rte_ether.h>
 #include "rte_flow.h"
+#include "rte_ethdev.h"
 
 /**
  * @deprecated Please use rte_flow API instead of this legacy one.
diff --git a/dpdk/lib/librte_ethdev/rte_ethdev.c b/dpdk/lib/librte_ethdev/rte_ethdev.c
index 6e9cb243ea..fb0912a4a8 100644
--- a/dpdk/lib/librte_ethdev/rte_ethdev.c
+++ b/dpdk/lib/librte_ethdev/rte_ethdev.c
@@ -279,7 +279,7 @@ rte_eth_iterator_init(struct rte_dev_iterator *iter, const char *devargs_str)
 
 error:
 	if (ret == -ENOTSUP)
-		RTE_LOG(ERR, EAL, "Bus %s does not support iterating.\n",
+		RTE_ETHDEV_LOG(ERR, "Bus %s does not support iterating.\n",
 				iter->bus->name);
 	free(devargs.args);
 	free(bus_str);
@@ -408,7 +408,9 @@ is_allocated(const struct rte_eth_dev *ethdev)
 static struct rte_eth_dev *
 _rte_eth_dev_allocated(const char *name)
 {
-	unsigned i;
+	uint16_t i;
+
+	RTE_BUILD_BUG_ON(RTE_MAX_ETHPORTS >= UINT16_MAX);
 
 	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
 		if (rte_eth_devices[i].data != NULL &&
@@ -437,7 +439,7 @@ rte_eth_dev_allocated(const char *name)
 static uint16_t
 rte_eth_dev_find_free_port(void)
 {
-	unsigned i;
+	uint16_t i;
 
 	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
 		/* Using shared name field to find a free port. */
@@ -800,7 +802,7 @@ rte_eth_dev_get_name_by_port(uint16_t port_id, char *name)
 int
 rte_eth_dev_get_port_by_name(const char *name, uint16_t *port_id)
 {
-	uint32_t pid;
+	uint16_t pid;
 
 	if (name == NULL) {
 		RTE_ETHDEV_LOG(ERR, "Null pointer is specified\n");
@@ -1166,14 +1168,14 @@ check_lro_pkt_size(uint16_t port_id, uint32_t config_size,
 
 /*
  * Validate offloads that are requested through rte_eth_dev_configure against
- * the offloads successfuly set by the ethernet device.
+ * the offloads successfully set by the ethernet device.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
  * @param req_offloads
  *   The offloads that have been requested through `rte_eth_dev_configure`.
  * @param set_offloads
- *   The offloads successfuly set by the ethernet device.
+ *   The offloads successfully set by the ethernet device.
  * @param offload_type
  *   The offload type i.e. Rx/Tx string.
  * @param offload_name
@@ -1202,7 +1204,7 @@ validate_offloads(uint16_t port_id, uint64_t req_offloads,
 			ret = -EINVAL;
 		}
 
-		/* Chech if offload couldn't be disabled. */
+		/* Check if offload couldn't be disabled. */
 		if (offload & set_offloads) {
 			RTE_ETHDEV_LOG(DEBUG,
 				"Port %u %s offload %s is not requested but enabled\n",
@@ -1222,8 +1224,10 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 	struct rte_eth_dev *dev;
 	struct rte_eth_dev_info dev_info;
 	struct rte_eth_conf orig_conf;
+	uint16_t overhead_len;
 	int diag;
 	int ret;
+	uint16_t old_mtu;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
 
@@ -1249,10 +1253,20 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 		memcpy(&dev->data->dev_conf, dev_conf,
 		       sizeof(dev->data->dev_conf));
 
+	/* Backup mtu for rollback */
+	old_mtu = dev->data->mtu;
+
 	ret = rte_eth_dev_info_get(port_id, &dev_info);
 	if (ret != 0)
 		goto rollback;
 
+	/* Get the real Ethernet overhead length */
+	if (dev_info.max_mtu != UINT16_MAX &&
+	    dev_info.max_rx_pktlen > dev_info.max_mtu)
+		overhead_len = dev_info.max_rx_pktlen - dev_info.max_mtu;
+	else
+		overhead_len = RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN;
+
 	/* If number of queues specified by application for both Rx and Tx is
 	 * zero, use driver preferred values. This cannot be done individually
 	 * as it is valid for either Tx or Rx (but not both) to be zero.
@@ -1339,12 +1353,17 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 			ret = -EINVAL;
 			goto rollback;
 		}
+
+		/* Scale the MTU size to adapt max_rx_pkt_len */
+		dev->data->mtu = dev->data->dev_conf.rxmode.max_rx_pkt_len -
+				overhead_len;
 	} else {
-		if (dev_conf->rxmode.max_rx_pkt_len < RTE_ETHER_MIN_LEN ||
-			dev_conf->rxmode.max_rx_pkt_len > RTE_ETHER_MAX_LEN)
+		uint16_t pktlen = dev_conf->rxmode.max_rx_pkt_len;
+		if (pktlen < RTE_ETHER_MIN_MTU + overhead_len ||
+		    pktlen > RTE_ETHER_MTU + overhead_len)
 			/* Use default value */
 			dev->data->dev_conf.rxmode.max_rx_pkt_len =
-							RTE_ETHER_MAX_LEN;
+						RTE_ETHER_MTU + overhead_len;
 	}
 
 	/*
@@ -1478,6 +1497,8 @@ rte_eth_dev_configure(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q,
 	rte_eth_dev_tx_queue_config(dev, 0);
 rollback:
 	memcpy(&dev->data->dev_conf, &orig_conf, sizeof(dev->data->dev_conf));
+	if (old_mtu != dev->data->mtu)
+		dev->data->mtu = old_mtu;
 
 	return ret;
 }
@@ -1814,7 +1835,7 @@ rte_eth_rx_queue_setup(uint16_t port_id, uint16_t rx_queue_id,
 	}
 	mbp_buf_size = rte_pktmbuf_data_room_size(mp);
 
-	if ((mbp_buf_size - RTE_PKTMBUF_HEADROOM) < dev_info.min_rx_bufsize) {
+	if (mbp_buf_size < dev_info.min_rx_bufsize + RTE_PKTMBUF_HEADROOM) {
 		RTE_ETHDEV_LOG(ERR,
 			"%s mbuf_data_room_size %d < %d (RTE_PKTMBUF_HEADROOM=%d + min_rx_bufsize(dev)=%d)\n",
 			mp->name, (int)mbp_buf_size,
@@ -2968,6 +2989,7 @@ rte_eth_dev_info_get(uint16_t port_id, struct rte_eth_dev_info *dev_info)
 	 * return status and does not know if get is successful or not.
 	 */
 	memset(dev_info, 0, sizeof(struct rte_eth_dev_info));
+	dev_info->switch_info.domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
@@ -3248,58 +3270,60 @@ rte_eth_dev_set_vlan_ether_type(uint16_t port_id,
 int
 rte_eth_dev_set_vlan_offload(uint16_t port_id, int offload_mask)
 {
+	struct rte_eth_dev_info dev_info;
 	struct rte_eth_dev *dev;
 	int ret = 0;
 	int mask = 0;
 	int cur, org = 0;
 	uint64_t orig_offloads;
-	uint64_t *dev_offloads;
+	uint64_t dev_offloads;
+	uint64_t new_offloads;
 
 	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
 	dev = &rte_eth_devices[port_id];
 
 	/* save original values in case of failure */
 	orig_offloads = dev->data->dev_conf.rxmode.offloads;
-	dev_offloads = &dev->data->dev_conf.rxmode.offloads;
+	dev_offloads = orig_offloads;
 
-	/*check which option changed by application*/
+	/* check which option changed by application */
 	cur = !!(offload_mask & ETH_VLAN_STRIP_OFFLOAD);
-	org = !!(*dev_offloads & DEV_RX_OFFLOAD_VLAN_STRIP);
+	org = !!(dev_offloads & DEV_RX_OFFLOAD_VLAN_STRIP);
 	if (cur != org) {
 		if (cur)
-			*dev_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
+			dev_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
 		else
-			*dev_offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
+			dev_offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
 		mask |= ETH_VLAN_STRIP_MASK;
 	}
 
 	cur = !!(offload_mask & ETH_VLAN_FILTER_OFFLOAD);
-	org = !!(*dev_offloads & DEV_RX_OFFLOAD_VLAN_FILTER);
+	org = !!(dev_offloads & DEV_RX_OFFLOAD_VLAN_FILTER);
 	if (cur != org) {
 		if (cur)
-			*dev_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
+			dev_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
 		else
-			*dev_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
+			dev_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
 		mask |= ETH_VLAN_FILTER_MASK;
 	}
 
 	cur = !!(offload_mask & ETH_VLAN_EXTEND_OFFLOAD);
-	org = !!(*dev_offloads & DEV_RX_OFFLOAD_VLAN_EXTEND);
+	org = !!(dev_offloads & DEV_RX_OFFLOAD_VLAN_EXTEND);
 	if (cur != org) {
 		if (cur)
-			*dev_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND;
+			dev_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND;
 		else
-			*dev_offloads &= ~DEV_RX_OFFLOAD_VLAN_EXTEND;
+			dev_offloads &= ~DEV_RX_OFFLOAD_VLAN_EXTEND;
 		mask |= ETH_VLAN_EXTEND_MASK;
 	}
 
 	cur = !!(offload_mask & ETH_QINQ_STRIP_OFFLOAD);
-	org = !!(*dev_offloads & DEV_RX_OFFLOAD_QINQ_STRIP);
+	org = !!(dev_offloads & DEV_RX_OFFLOAD_QINQ_STRIP);
 	if (cur != org) {
 		if (cur)
-			*dev_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
+			dev_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
 		else
-			*dev_offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP;
+			dev_offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP;
 		mask |= ETH_QINQ_STRIP_MASK;
 	}
 
@@ -3307,11 +3331,28 @@ rte_eth_dev_set_vlan_offload(uint16_t port_id, int offload_mask)
 	if (mask == 0)
 		return ret;
 
+	ret = rte_eth_dev_info_get(port_id, &dev_info);
+	if (ret != 0)
+		return ret;
+
+	/* Rx VLAN offloading must be within its device capabilities */
+	if ((dev_offloads & dev_info.rx_offload_capa) != dev_offloads) {
+		new_offloads = dev_offloads & ~orig_offloads;
+		RTE_ETHDEV_LOG(ERR,
+			"Ethdev port_id=%u requested new added VLAN offloads "
+			"0x%" PRIx64 " must be within Rx offloads capabilities "
+			"0x%" PRIx64 " in %s()\n",
+			port_id, new_offloads, dev_info.rx_offload_capa,
+			__func__);
+		return -EINVAL;
+	}
+
 	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_offload_set, -ENOTSUP);
+	dev->data->dev_conf.rxmode.offloads = dev_offloads;
 	ret = (*dev->dev_ops->vlan_offload_set)(dev, mask);
 	if (ret) {
 		/* hit an error restore  original values */
-		*dev_offloads = orig_offloads;
+		dev->data->dev_conf.rxmode.offloads = orig_offloads;
 	}
 
 	return eth_err(port_id, ret);
@@ -3934,7 +3975,7 @@ rte_eth_mirror_rule_reset(uint16_t port_id, uint8_t rule_id)
 
 RTE_INIT(eth_dev_init_cb_lists)
 {
-	int i;
+	uint16_t i;
 
 	for (i = 0; i < RTE_MAX_ETHPORTS; i++)
 		TAILQ_INIT(&rte_eth_devices[i].link_intr_cbs);
@@ -3947,7 +3988,7 @@ rte_eth_dev_callback_register(uint16_t port_id,
 {
 	struct rte_eth_dev *dev;
 	struct rte_eth_dev_callback *user_cb;
-	uint32_t next_port; /* size is 32-bit to prevent loop wrap-around */
+	uint16_t next_port;
 	uint16_t last_port;
 
 	if (!cb_fn)
@@ -4010,7 +4051,7 @@ rte_eth_dev_callback_unregister(uint16_t port_id,
 	int ret;
 	struct rte_eth_dev *dev;
 	struct rte_eth_dev_callback *cb, *next;
-	uint32_t next_port; /* size is 32-bit to prevent loop wrap-around */
+	uint16_t next_port;
 	uint16_t last_port;
 
 	if (!cb_fn)
@@ -4039,7 +4080,7 @@ rte_eth_dev_callback_unregister(uint16_t port_id,
 			next = TAILQ_NEXT(cb, next);
 
 			if (cb->cb_fn != cb_fn || cb->event != event ||
-			    (cb->cb_arg != (void *)-1 && cb->cb_arg != cb_arg))
+			    (cb_arg != (void *)-1 && cb->cb_arg != cb_arg))
 				continue;
 
 			/*
@@ -4219,7 +4260,8 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 				device->numa_node);
 
 			if (!ethdev->data->dev_private) {
-				RTE_LOG(ERR, EAL, "failed to allocate private data");
+				RTE_ETHDEV_LOG(ERR,
+					"failed to allocate private data\n");
 				retval = -ENOMEM;
 				goto probe_failed;
 			}
@@ -4227,8 +4269,8 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 	} else {
 		ethdev = rte_eth_dev_attach_secondary(name);
 		if (!ethdev) {
-			RTE_LOG(ERR, EAL, "secondary process attach failed, "
-				"ethdev doesn't exist");
+			RTE_ETHDEV_LOG(ERR,
+				"secondary process attach failed, ethdev doesn't exist\n");
 			return  -ENODEV;
 		}
 	}
@@ -4238,15 +4280,15 @@ rte_eth_dev_create(struct rte_device *device, const char *name,
 	if (ethdev_bus_specific_init) {
 		retval = ethdev_bus_specific_init(ethdev, bus_init_params);
 		if (retval) {
-			RTE_LOG(ERR, EAL,
-				"ethdev bus specific initialisation failed");
+			RTE_ETHDEV_LOG(ERR,
+				"ethdev bus specific initialisation failed\n");
 			goto probe_failed;
 		}
 	}
 
 	retval = ethdev_init(ethdev, init_params);
 	if (retval) {
-		RTE_LOG(ERR, EAL, "ethdev initialisation failed");
+		RTE_ETHDEV_LOG(ERR, "ethdev initialisation failed\n");
 		goto probe_failed;
 	}
 
@@ -4414,12 +4456,20 @@ rte_eth_add_rx_callback(uint16_t port_id, uint16_t queue_id,
 		rte_eth_devices[port_id].post_rx_burst_cbs[queue_id];
 
 	if (!tail) {
-		rte_eth_devices[port_id].post_rx_burst_cbs[queue_id] = cb;
+		/* Stores to cb->fn and cb->param should complete before
+		 * cb is visible to data plane.
+		 */
+		__atomic_store_n(
+			&rte_eth_devices[port_id].post_rx_burst_cbs[queue_id],
+			cb, __ATOMIC_RELEASE);
 
 	} else {
 		while (tail->next)
 			tail = tail->next;
-		tail->next = cb;
+		/* Stores to cb->fn and cb->param should complete before
+		 * cb is visible to data plane.
+		 */
+		__atomic_store_n(&tail->next, cb, __ATOMIC_RELEASE);
 	}
 	rte_spinlock_unlock(&rte_eth_rx_cb_lock);
 
@@ -4452,7 +4502,7 @@ rte_eth_add_first_rx_callback(uint16_t port_id, uint16_t queue_id,
 	cb->param = user_param;
 
 	rte_spinlock_lock(&rte_eth_rx_cb_lock);
-	/* Add the callbacks at fisrt position*/
+	/* Add the callbacks at first position */
 	cb->next = rte_eth_devices[port_id].post_rx_burst_cbs[queue_id];
 	rte_smp_wmb();
 	rte_eth_devices[port_id].post_rx_burst_cbs[queue_id] = cb;
@@ -4500,12 +4550,20 @@ rte_eth_add_tx_callback(uint16_t port_id, uint16_t queue_id,
 		rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id];
 
 	if (!tail) {
-		rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id] = cb;
+		/* Stores to cb->fn and cb->param should complete before
+		 * cb is visible to data plane.
+		 */
+		__atomic_store_n(
+			&rte_eth_devices[port_id].pre_tx_burst_cbs[queue_id],
+			cb, __ATOMIC_RELEASE);
 
 	} else {
 		while (tail->next)
 			tail = tail->next;
-		tail->next = cb;
+		/* Stores to cb->fn and cb->param should complete before
+		 * cb is visible to data plane.
+		 */
+		__atomic_store_n(&tail->next, cb, __ATOMIC_RELEASE);
 	}
 	rte_spinlock_unlock(&rte_eth_tx_cb_lock);
 
@@ -4536,7 +4594,7 @@ rte_eth_remove_rx_callback(uint16_t port_id, uint16_t queue_id,
 		cb = *prev_cb;
 		if (cb == user_cb) {
 			/* Remove the user cb from the callback list. */
-			*prev_cb = cb->next;
+			__atomic_store_n(prev_cb, cb->next, __ATOMIC_RELAXED);
 			ret = 0;
 			break;
 		}
@@ -4570,7 +4628,7 @@ rte_eth_remove_tx_callback(uint16_t port_id, uint16_t queue_id,
 		cb = *prev_cb;
 		if (cb == user_cb) {
 			/* Remove the user cb from the callback list. */
-			*prev_cb = cb->next;
+			__atomic_store_n(prev_cb, cb->next, __ATOMIC_RELAXED);
 			ret = 0;
 			break;
 		}
@@ -5060,12 +5118,11 @@ static struct rte_eth_dev_switch {
 int
 rte_eth_switch_domain_alloc(uint16_t *domain_id)
 {
-	unsigned int i;
+	uint16_t i;
 
 	*domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
 
-	for (i = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID + 1;
-		i < RTE_MAX_ETHPORTS; i++) {
+	for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
 		if (rte_eth_switch_domains[i].state ==
 			RTE_ETH_SWITCH_DOMAIN_UNUSED) {
 			rte_eth_switch_domains[i].state =
diff --git a/dpdk/lib/librte_ethdev/rte_ethdev.h b/dpdk/lib/librte_ethdev/rte_ethdev.h
index 18a9defc24..017459e595 100644
--- a/dpdk/lib/librte_ethdev/rte_ethdev.h
+++ b/dpdk/lib/librte_ethdev/rte_ethdev.h
@@ -1160,17 +1160,20 @@ struct rte_eth_conf {
 #define DEV_TX_OFFLOAD_IP_TNL_TSO       0x00080000
 /** Device supports outer UDP checksum */
 #define DEV_TX_OFFLOAD_OUTER_UDP_CKSUM  0x00100000
-
-#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001
-/**< Device supports Rx queue setup after device started*/
-#define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002
-/**< Device supports Tx queue setup after device started*/
-
 /*
  * If new Tx offload capabilities are defined, they also must be
  * mentioned in rte_tx_offload_names in rte_ethdev.c file.
  */
 
+/**@{@name Device capabilities
+ * Non-offload capabilities reported in rte_eth_dev_info.dev_capa.
+ */
+/** Device supports Rx queue setup after device started. */
+#define RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP 0x00000001
+/** Device supports Tx queue setup after device started. */
+#define RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP 0x00000002
+/**@}*/
+
 /*
  * Fallback default preferred Rx/Tx port parameters.
  * These are used if an application requests default parameters
@@ -1196,7 +1199,7 @@ struct rte_eth_dev_portconf {
  * Default values for switch domain id when ethdev does not support switch
  * domain definitions.
  */
-#define RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID	(0)
+#define RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID	(UINT16_MAX)
 
 /**
  * Ethernet device associated switch information
@@ -3612,7 +3615,8 @@ struct rte_eth_rxtx_callback;
  *   The callback function
  * @param user_param
  *   A generic pointer parameter which will be passed to each invocation of the
- *   callback function on this port and queue.
+ *   callback function on this port and queue. Inter-thread synchronization
+ *   of any user data changes is the responsibility of the user.
  *
  * @return
  *   NULL on error.
@@ -3641,7 +3645,8 @@ rte_eth_add_rx_callback(uint16_t port_id, uint16_t queue_id,
  *   The callback function
  * @param user_param
  *   A generic pointer parameter which will be passed to each invocation of the
- *   callback function on this port and queue.
+ *   callback function on this port and queue. Inter-thread synchronization
+ *   of any user data changes is the responsibility of the user.
  *
  * @return
  *   NULL on error.
@@ -3669,7 +3674,8 @@ rte_eth_add_first_rx_callback(uint16_t port_id, uint16_t queue_id,
  *   The callback function
  * @param user_param
  *   A generic pointer parameter which will be passed to each invocation of the
- *   callback function on this port and queue.
+ *   callback function on this port and queue. Inter-thread synchronization
+ *   of any user data changes is the responsibility of the user.
  *
  * @return
  *   NULL on error.
@@ -3694,7 +3700,9 @@ rte_eth_add_tx_callback(uint16_t port_id, uint16_t queue_id,
  *   on that queue.
  *
  * - After a short delay - where the delay is sufficient to allow any
- *   in-flight callbacks to complete.
+ *   in-flight callbacks to complete. Alternately, the RCU mechanism can be
+ *   used to detect when data plane threads have ceased referencing the
+ *   callback memory.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
@@ -3727,7 +3735,9 @@ int rte_eth_remove_rx_callback(uint16_t port_id, uint16_t queue_id,
  *   on that queue.
  *
  * - After a short delay - where the delay is sufficient to allow any
- *   in-flight callbacks to complete.
+ *   in-flight callbacks to complete. Alternately, the RCU mechanism can be
+ *   used to detect when data plane threads have ceased referencing the
+ *   callback memory.
  *
  * @param port_id
  *   The port identifier of the Ethernet device.
@@ -4388,10 +4398,18 @@ rte_eth_rx_burst(uint16_t port_id, uint16_t queue_id,
 				     rx_pkts, nb_pkts);
 
 #ifdef RTE_ETHDEV_RXTX_CALLBACKS
-	if (unlikely(dev->post_rx_burst_cbs[queue_id] != NULL)) {
-		struct rte_eth_rxtx_callback *cb =
-				dev->post_rx_burst_cbs[queue_id];
+	struct rte_eth_rxtx_callback *cb;
+
+	/* __ATOMIC_RELEASE memory order was used when the
+	 * call back was inserted into the list.
+	 * Since there is a clear dependency between loading
+	 * cb and cb->fn/cb->next, __ATOMIC_ACQUIRE memory order is
+	 * not required.
+	 */
+	cb = __atomic_load_n(&dev->post_rx_burst_cbs[queue_id],
+				__ATOMIC_RELAXED);
 
+	if (unlikely(cb != NULL)) {
 		do {
 			nb_rx = cb->fn.rx(port_id, queue_id, rx_pkts, nb_rx,
 						nb_pkts, cb->param);
@@ -4652,7 +4670,16 @@ rte_eth_tx_burst(uint16_t port_id, uint16_t queue_id,
 #endif
 
 #ifdef RTE_ETHDEV_RXTX_CALLBACKS
-	struct rte_eth_rxtx_callback *cb = dev->pre_tx_burst_cbs[queue_id];
+	struct rte_eth_rxtx_callback *cb;
+
+	/* __ATOMIC_RELEASE memory order was used when the
+	 * call back was inserted into the list.
+	 * Since there is a clear dependency between loading
+	 * cb and cb->fn/cb->next, __ATOMIC_ACQUIRE memory order is
+	 * not required.
+	 */
+	cb = __atomic_load_n(&dev->pre_tx_burst_cbs[queue_id],
+				__ATOMIC_RELAXED);
 
 	if (unlikely(cb != NULL)) {
 		do {
diff --git a/dpdk/lib/librte_ethdev/rte_ethdev_pci.h b/dpdk/lib/librte_ethdev/rte_ethdev_pci.h
index ccdbb46ec0..d44a8e2a39 100644
--- a/dpdk/lib/librte_ethdev/rte_ethdev_pci.h
+++ b/dpdk/lib/librte_ethdev/rte_ethdev_pci.h
@@ -3,32 +3,6 @@
  *
  *   Copyright(c) 2017 Brocade Communications Systems, Inc.
  *   Author: Jan Blunck <jblunck@infradead.org>
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of the copyright holder nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _RTE_ETHDEV_PCI_H_
@@ -42,6 +16,8 @@
 
 /**
  * Copy pci device info to the Ethernet device data.
+ * Shared memory (eth_dev->data) only updated by primary process, so it is safe
+ * to call this function from both primary and secondary processes.
  *
  * @param eth_dev
  * The *eth_dev* pointer is the address of the *rte_eth_dev* structure.
@@ -60,14 +36,16 @@ rte_eth_copy_pci_info(struct rte_eth_dev *eth_dev,
 
 	eth_dev->intr_handle = &pci_dev->intr_handle;
 
-	eth_dev->data->dev_flags = 0;
-	if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
-		eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
-	if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_RMV)
-		eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV;
-
-	eth_dev->data->kdrv = pci_dev->kdrv;
-	eth_dev->data->numa_node = pci_dev->device.numa_node;
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		eth_dev->data->dev_flags = 0;
+		if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_LSC)
+			eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
+		if (pci_dev->driver->drv_flags & RTE_PCI_DRV_INTR_RMV)
+			eth_dev->data->dev_flags |= RTE_ETH_DEV_INTR_RMV;
+
+		eth_dev->data->kdrv = pci_dev->kdrv;
+		eth_dev->data->numa_node = pci_dev->device.numa_node;
+	}
 }
 
 static inline int
diff --git a/dpdk/lib/librte_ethdev/rte_ethdev_vdev.h b/dpdk/lib/librte_ethdev/rte_ethdev_vdev.h
index 259feda3f7..0abce0d21c 100644
--- a/dpdk/lib/librte_ethdev/rte_ethdev_vdev.h
+++ b/dpdk/lib/librte_ethdev/rte_ethdev_vdev.h
@@ -3,32 +3,6 @@
  *
  *   Copyright(c) 2017 Brocade Communications Systems, Inc.
  *   Author: Jan Blunck <jblunck@infradead.org>
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of the copyright holder nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef _RTE_ETHDEV_VDEV_H_
diff --git a/dpdk/lib/librte_ethdev/rte_flow.c b/dpdk/lib/librte_ethdev/rte_flow.c
index 87a3e8c4c6..9964a241cb 100644
--- a/dpdk/lib/librte_ethdev/rte_flow.c
+++ b/dpdk/lib/librte_ethdev/rte_flow.c
@@ -19,7 +19,7 @@
 #include "rte_flow.h"
 
 /* Mbuf dynamic field name for metadata. */
-int rte_flow_dynf_metadata_offs = -1;
+int32_t rte_flow_dynf_metadata_offs = -1;
 
 /* Mbuf dynamic field flag bit number for metadata. */
 uint64_t rte_flow_dynf_metadata_mask;
@@ -241,6 +241,8 @@ rte_flow_expand_rss_item_complete(const struct rte_flow_item *item)
 			ret = RTE_FLOW_ITEM_TYPE_IPV6;
 		else if (rte_be_to_cpu_16(ether_type) == RTE_ETHER_TYPE_VLAN)
 			ret = RTE_FLOW_ITEM_TYPE_VLAN;
+		else
+			ret = RTE_FLOW_ITEM_TYPE_END;
 		break;
 	case RTE_FLOW_ITEM_TYPE_VLAN:
 		if (item->mask)
@@ -258,6 +260,8 @@ rte_flow_expand_rss_item_complete(const struct rte_flow_item *item)
 			ret = RTE_FLOW_ITEM_TYPE_IPV6;
 		else if (rte_be_to_cpu_16(ether_type) == RTE_ETHER_TYPE_VLAN)
 			ret = RTE_FLOW_ITEM_TYPE_VLAN;
+		else
+			ret = RTE_FLOW_ITEM_TYPE_END;
 		break;
 	case RTE_FLOW_ITEM_TYPE_IPV4:
 		if (item->mask)
@@ -278,6 +282,8 @@ rte_flow_expand_rss_item_complete(const struct rte_flow_item *item)
 			ret = RTE_FLOW_ITEM_TYPE_IPV4;
 		else if (ip_next_proto == IPPROTO_IPV6)
 			ret = RTE_FLOW_ITEM_TYPE_IPV6;
+		else
+			ret = RTE_FLOW_ITEM_TYPE_END;
 		break;
 	case RTE_FLOW_ITEM_TYPE_IPV6:
 		if (item->mask)
@@ -298,6 +304,8 @@ rte_flow_expand_rss_item_complete(const struct rte_flow_item *item)
 			ret = RTE_FLOW_ITEM_TYPE_IPV4;
 		else if (ip_next_proto == IPPROTO_IPV6)
 			ret = RTE_FLOW_ITEM_TYPE_IPV6;
+		else
+			ret = RTE_FLOW_ITEM_TYPE_END;
 		break;
 	default:
 		ret = RTE_FLOW_ITEM_TYPE_VOID;
@@ -613,7 +621,7 @@ rte_flow_conv_action_conf(void *buf, const size_t size,
 			   }),
 			   size > sizeof(*dst.rss) ? sizeof(*dst.rss) : size);
 		off = sizeof(*dst.rss);
-		if (src.rss->key_len) {
+		if (src.rss->key_len && src.rss->key) {
 			off = RTE_ALIGN_CEIL(off, sizeof(*dst.rss->key));
 			tmp = sizeof(*src.rss->key) * src.rss->key_len;
 			if (size >= off + tmp)
@@ -1104,10 +1112,14 @@ rte_flow_expand_rss(struct rte_flow_expand_rss *buf, size_t size,
 	memset(flow_items, 0, sizeof(flow_items));
 	user_pattern_size -= sizeof(*item);
 	/*
-	 * Check if the last valid item has spec set
-	 * and need complete pattern.
+	 * Check if the last valid item has spec set, need complete pattern,
+	 * and the pattern can be used for expansion.
 	 */
 	missed_item.type = rte_flow_expand_rss_item_complete(last_item);
+	if (missed_item.type == RTE_FLOW_ITEM_TYPE_END) {
+		/* Item type END indicates expansion is not required. */
+		return lsize;
+	}
 	if (missed_item.type != RTE_FLOW_ITEM_TYPE_VOID) {
 		next = NULL;
 		missed = 1;
diff --git a/dpdk/lib/librte_ethdev/rte_flow.h b/dpdk/lib/librte_ethdev/rte_flow.h
index 452d359a16..693824da8a 100644
--- a/dpdk/lib/librte_ethdev/rte_flow.h
+++ b/dpdk/lib/librte_ethdev/rte_flow.h
@@ -502,7 +502,7 @@ enum rte_flow_item_type {
 	 */
 	RTE_FLOW_ITEM_TYPE_HIGIG2,
 
-	/*
+	/**
 	 * [META]
 	 *
 	 * Matches a tag value.
@@ -2531,7 +2531,7 @@ struct rte_flow_action_set_meta {
 };
 
 /* Mbuf dynamic field offset for metadata. */
-extern int rte_flow_dynf_metadata_offs;
+extern int32_t rte_flow_dynf_metadata_offs;
 
 /* Mbuf dynamic field flag mask for metadata. */
 extern uint64_t rte_flow_dynf_metadata_mask;
diff --git a/dpdk/lib/librte_eventdev/rte_event_crypto_adapter.c b/dpdk/lib/librte_eventdev/rte_event_crypto_adapter.c
index 22d9108168..db9af8c200 100644
--- a/dpdk/lib/librte_eventdev/rte_event_crypto_adapter.c
+++ b/dpdk/lib/librte_eventdev/rte_event_crypto_adapter.c
@@ -240,6 +240,7 @@ rte_event_crypto_adapter_create_ext(uint8_t id, uint8_t dev_id,
 	if (ret < 0) {
 		RTE_EDEV_LOG_ERR("Failed to get info for eventdev %d: %s!",
 				 dev_id, dev_info.driver_name);
+		rte_free(adapter);
 		return ret;
 	}
 
diff --git a/dpdk/lib/librte_eventdev/rte_event_eth_tx_adapter.c b/dpdk/lib/librte_eventdev/rte_event_eth_tx_adapter.c
index d02ef57f4e..8a1573e75f 100644
--- a/dpdk/lib/librte_eventdev/rte_event_eth_tx_adapter.c
+++ b/dpdk/lib/librte_eventdev/rte_event_eth_tx_adapter.c
@@ -733,6 +733,8 @@ txa_service_queue_add(uint8_t id,
 
 		qdone = rte_zmalloc(txa->mem_name,
 				nb_queues * sizeof(*qdone), 0);
+		if (qdone == NULL)
+			return -ENOMEM;
 		j = 0;
 		for (i = 0; i < nb_queues; i++) {
 			if (txa_service_is_queue_added(txa, eth_dev, i))
diff --git a/dpdk/lib/librte_eventdev/rte_event_timer_adapter.c b/dpdk/lib/librte_eventdev/rte_event_timer_adapter.c
index 161e21a685..36c13fe3b5 100644
--- a/dpdk/lib/librte_eventdev/rte_event_timer_adapter.c
+++ b/dpdk/lib/librte_eventdev/rte_event_timer_adapter.c
@@ -550,7 +550,7 @@ struct swtim {
 	uint32_t timer_data_id;
 	/* Track which cores have actually armed a timer */
 	struct {
-		rte_atomic16_t v;
+		uint16_t v;
 	} __rte_cache_aligned in_use[RTE_MAX_LCORE];
 	/* Track which cores' timer lists should be polled */
 	unsigned int poll_lcores[RTE_MAX_LCORE];
@@ -579,6 +579,7 @@ swtim_callback(struct rte_timer *tim)
 	uint16_t nb_evs_invalid = 0;
 	uint64_t opaque;
 	int ret;
+	int n_lcores;
 
 	opaque = evtim->impl_opaque[1];
 	adapter = (struct rte_event_timer_adapter *)(uintptr_t)opaque;
@@ -601,8 +602,13 @@ swtim_callback(struct rte_timer *tim)
 				      "with immediate expiry value");
 		}
 
-		if (unlikely(rte_atomic16_test_and_set(&sw->in_use[lcore].v)))
-			sw->poll_lcores[sw->n_poll_lcores++] = lcore;
+		if (unlikely(sw->in_use[lcore].v == 0)) {
+			sw->in_use[lcore].v = 1;
+			n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,
+						     __ATOMIC_RELAXED);
+			__atomic_store_n(&sw->poll_lcores[n_lcores], lcore,
+					__ATOMIC_RELAXED);
+		}
 	} else {
 		EVTIM_BUF_LOG_DBG("buffered an event timer expiry event");
 
@@ -619,7 +625,8 @@ swtim_callback(struct rte_timer *tim)
 		sw->expired_timers[sw->n_expired_timers++] = tim;
 		sw->stats.evtim_exp_count++;
 
-		evtim->state = RTE_EVENT_TIMER_NOT_ARMED;
+		__atomic_store_n(&evtim->state, RTE_EVENT_TIMER_NOT_ARMED,
+				__ATOMIC_RELEASE);
 	}
 
 	if (event_buffer_batch_ready(&sw->buffer)) {
@@ -825,7 +832,7 @@ swtim_init(struct rte_event_timer_adapter *adapter)
 
 	/* Initialize the variables that track in-use timer lists */
 	for (i = 0; i < RTE_MAX_LCORE; i++)
-		rte_atomic16_init(&sw->in_use[i].v);
+		sw->in_use[i].v = 0;
 
 	/* Initialize the timer subsystem and allocate timer data instance */
 	ret = rte_timer_subsystem_init();
@@ -1007,6 +1014,10 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
 	uint32_t lcore_id = rte_lcore_id();
 	struct rte_timer *tim, *tims[nb_evtims];
 	uint64_t cycles;
+	int n_lcores;
+	/* Timer list for this lcore is not in use. */
+	uint16_t exp_state = 0;
+	enum rte_event_timer_state n_state;
 
 #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
 	/* Check that the service is running. */
@@ -1025,12 +1036,18 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
 	/* If this is the first time we're arming an event timer on this lcore,
 	 * mark this lcore as "in use"; this will cause the service
 	 * function to process the timer list that corresponds to this lcore.
+	 * The atomic compare-and-swap operation can prevent the race condition
+	 * on in_use flag between multiple non-EAL threads.
 	 */
-	if (unlikely(rte_atomic16_test_and_set(&sw->in_use[lcore_id].v))) {
+	if (unlikely(__atomic_compare_exchange_n(&sw->in_use[lcore_id].v,
+			&exp_state, 1, 0,
+			__ATOMIC_RELAXED, __ATOMIC_RELAXED))) {
 		EVTIM_LOG_DBG("Adding lcore id = %u to list of lcores to poll",
 			      lcore_id);
-		sw->poll_lcores[sw->n_poll_lcores] = lcore_id;
-		++sw->n_poll_lcores;
+		n_lcores = __atomic_fetch_add(&sw->n_poll_lcores, 1,
+					     __ATOMIC_RELAXED);
+		__atomic_store_n(&sw->poll_lcores[n_lcores], lcore_id,
+				__ATOMIC_RELAXED);
 	}
 
 	ret = rte_mempool_get_bulk(sw->tim_pool, (void **)tims,
@@ -1041,30 +1058,36 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
 	}
 
 	for (i = 0; i < nb_evtims; i++) {
-		/* Don't modify the event timer state in these cases */
-		if (evtims[i]->state == RTE_EVENT_TIMER_ARMED) {
+		n_state = __atomic_load_n(&evtims[i]->state, __ATOMIC_ACQUIRE);
+		if (n_state == RTE_EVENT_TIMER_ARMED) {
 			rte_errno = EALREADY;
 			break;
-		} else if (!(evtims[i]->state == RTE_EVENT_TIMER_NOT_ARMED ||
-			     evtims[i]->state == RTE_EVENT_TIMER_CANCELED)) {
+		} else if (!(n_state == RTE_EVENT_TIMER_NOT_ARMED ||
+			     n_state == RTE_EVENT_TIMER_CANCELED)) {
 			rte_errno = EINVAL;
 			break;
 		}
 
 		ret = check_timeout(evtims[i], adapter);
 		if (unlikely(ret == -1)) {
-			evtims[i]->state = RTE_EVENT_TIMER_ERROR_TOOLATE;
+			__atomic_store_n(&evtims[i]->state,
+					RTE_EVENT_TIMER_ERROR_TOOLATE,
+					__ATOMIC_RELAXED);
 			rte_errno = EINVAL;
 			break;
 		} else if (unlikely(ret == -2)) {
-			evtims[i]->state = RTE_EVENT_TIMER_ERROR_TOOEARLY;
+			__atomic_store_n(&evtims[i]->state,
+					RTE_EVENT_TIMER_ERROR_TOOEARLY,
+					__ATOMIC_RELAXED);
 			rte_errno = EINVAL;
 			break;
 		}
 
 		if (unlikely(check_destination_event_queue(evtims[i],
 							   adapter) < 0)) {
-			evtims[i]->state = RTE_EVENT_TIMER_ERROR;
+			__atomic_store_n(&evtims[i]->state,
+					RTE_EVENT_TIMER_ERROR,
+					__ATOMIC_RELAXED);
 			rte_errno = EINVAL;
 			break;
 		}
@@ -1080,13 +1103,18 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
 					  SINGLE, lcore_id, NULL, evtims[i]);
 		if (ret < 0) {
 			/* tim was in RUNNING or CONFIG state */
-			evtims[i]->state = RTE_EVENT_TIMER_ERROR;
+			__atomic_store_n(&evtims[i]->state,
+					RTE_EVENT_TIMER_ERROR,
+					__ATOMIC_RELEASE);
 			break;
 		}
 
-		rte_smp_wmb();
 		EVTIM_LOG_DBG("armed an event timer");
-		evtims[i]->state = RTE_EVENT_TIMER_ARMED;
+		/* RELEASE ordering guarantees the adapter specific value
+		 * changes observed before the update of state.
+		 */
+		__atomic_store_n(&evtims[i]->state, RTE_EVENT_TIMER_ARMED,
+				__ATOMIC_RELEASE);
 	}
 
 	if (i < nb_evtims)
@@ -1113,6 +1141,7 @@ swtim_cancel_burst(const struct rte_event_timer_adapter *adapter,
 	struct rte_timer *timp;
 	uint64_t opaque;
 	struct swtim *sw = swtim_pmd_priv(adapter);
+	enum rte_event_timer_state n_state;
 
 #ifdef RTE_LIBRTE_EVENTDEV_DEBUG
 	/* Check that the service is running. */
@@ -1124,16 +1153,18 @@ swtim_cancel_burst(const struct rte_event_timer_adapter *adapter,
 
 	for (i = 0; i < nb_evtims; i++) {
 		/* Don't modify the event timer state in these cases */
-		if (evtims[i]->state == RTE_EVENT_TIMER_CANCELED) {
+		/* ACQUIRE ordering guarantees the access of implementation
+		 * specific opaque data under the correct state.
+		 */
+		n_state = __atomic_load_n(&evtims[i]->state, __ATOMIC_ACQUIRE);
+		if (n_state == RTE_EVENT_TIMER_CANCELED) {
 			rte_errno = EALREADY;
 			break;
-		} else if (evtims[i]->state != RTE_EVENT_TIMER_ARMED) {
+		} else if (n_state != RTE_EVENT_TIMER_ARMED) {
 			rte_errno = EINVAL;
 			break;
 		}
 
-		rte_smp_rmb();
-
 		opaque = evtims[i]->impl_opaque[0];
 		timp = (struct rte_timer *)(uintptr_t)opaque;
 		RTE_ASSERT(timp != NULL);
@@ -1147,11 +1178,12 @@ swtim_cancel_burst(const struct rte_event_timer_adapter *adapter,
 
 		rte_mempool_put(sw->tim_pool, (void **)timp);
 
-		evtims[i]->state = RTE_EVENT_TIMER_CANCELED;
-		evtims[i]->impl_opaque[0] = 0;
-		evtims[i]->impl_opaque[1] = 0;
-
-		rte_smp_wmb();
+		/* The RELEASE ordering here pairs with atomic ordering
+		 * to make sure the state update data observed between
+		 * threads.
+		 */
+		__atomic_store_n(&evtims[i]->state, RTE_EVENT_TIMER_CANCELED,
+				__ATOMIC_RELEASE);
 	}
 
 	return i;
diff --git a/dpdk/lib/librte_eventdev/rte_eventdev.c b/dpdk/lib/librte_eventdev/rte_eventdev.c
index b987e07454..9aca7fbd52 100644
--- a/dpdk/lib/librte_eventdev/rte_eventdev.c
+++ b/dpdk/lib/librte_eventdev/rte_eventdev.c
@@ -1364,14 +1364,17 @@ rte_event_pmd_allocate(const char *name, int socket_id)
 
 		eventdev->data = eventdev_data;
 
-		strlcpy(eventdev->data->name, name, RTE_EVENTDEV_NAME_MAX_LEN);
+		if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
 
-		eventdev->data->dev_id = dev_id;
-		eventdev->data->socket_id = socket_id;
-		eventdev->data->dev_started = 0;
+			strlcpy(eventdev->data->name, name,
+				RTE_EVENTDEV_NAME_MAX_LEN);
 
-		eventdev->attached = RTE_EVENTDEV_ATTACHED;
+			eventdev->data->dev_id = dev_id;
+			eventdev->data->socket_id = socket_id;
+			eventdev->data->dev_started = 0;
+		}
 
+		eventdev->attached = RTE_EVENTDEV_ATTACHED;
 		eventdev_globals.nb_devs++;
 	}
 
diff --git a/dpdk/lib/librte_eventdev/rte_eventdev_pmd.h b/dpdk/lib/librte_eventdev/rte_eventdev_pmd.h
index d118b9e5ba..c5d41ddad8 100644
--- a/dpdk/lib/librte_eventdev/rte_eventdev_pmd.h
+++ b/dpdk/lib/librte_eventdev/rte_eventdev_pmd.h
@@ -155,9 +155,6 @@ rte_event_pmd_is_valid_dev(uint8_t dev_id)
  *   Event device pointer
  * @param dev_info
  *   Event device information structure
- *
- * @return
- *   Returns 0 on success
  */
 typedef void (*eventdev_info_get_t)(struct rte_eventdev *dev,
 		struct rte_event_dev_info *dev_info);
diff --git a/dpdk/lib/librte_eventdev/rte_eventdev_pmd_pci.h b/dpdk/lib/librte_eventdev/rte_eventdev_pmd_pci.h
index 8fb61386fd..443cd38c23 100644
--- a/dpdk/lib/librte_eventdev/rte_eventdev_pmd_pci.h
+++ b/dpdk/lib/librte_eventdev/rte_eventdev_pmd_pci.h
@@ -112,9 +112,11 @@ rte_event_pmd_pci_remove(struct rte_pci_device *pci_dev,
 	if (eventdev == NULL)
 		return -ENODEV;
 
-	ret = rte_event_dev_close(eventdev->data->dev_id);
-	if (ret < 0)
-		return ret;
+	if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+		ret = rte_event_dev_close(eventdev->data->dev_id);
+		if (ret < 0)
+			return ret;
+	}
 
 	/* Invoke PMD device un-init function */
 	if (devuninit)
diff --git a/dpdk/lib/librte_fib/rte_fib.h b/dpdk/lib/librte_fib/rte_fib.h
index d06c5ef55a..04c490ed6e 100644
--- a/dpdk/lib/librte_fib/rte_fib.h
+++ b/dpdk/lib/librte_fib/rte_fib.h
@@ -8,12 +8,25 @@
 
 /**
  * @file
+ *
+ * RTE FIB library.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
  * FIB (Forwarding information base) implementation
  * for IPv4 Longest Prefix Match
  */
 
+#include <stdint.h>
+
 #include <rte_compat.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct rte_fib;
 struct rte_rib;
 
@@ -185,4 +198,8 @@ __rte_experimental
 struct rte_rib *
 rte_fib_get_rib(struct rte_fib *fib);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _RTE_FIB_H_ */
diff --git a/dpdk/lib/librte_fib/rte_fib6.h b/dpdk/lib/librte_fib/rte_fib6.h
index 4268704038..9228d87149 100644
--- a/dpdk/lib/librte_fib/rte_fib6.h
+++ b/dpdk/lib/librte_fib/rte_fib6.h
@@ -8,12 +8,25 @@
 
 /**
  * @file
+ *
+ * RTE FIB6 library.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
  * FIB (Forwarding information base) implementation
  * for IPv6 Longest Prefix Match
  */
 
+#include <stdint.h>
+
 #include <rte_compat.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define RTE_FIB6_IPV6_ADDR_SIZE		16
 /** Maximum depth value possible for IPv6 FIB. */
 #define RTE_FIB6_MAXDEPTH       128
@@ -190,4 +203,8 @@ __rte_experimental
 struct rte_rib6 *
 rte_fib6_get_rib(struct rte_fib6 *fib);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _RTE_FIB6_H_ */
diff --git a/dpdk/lib/librte_fib/trie.c b/dpdk/lib/librte_fib/trie.c
index 124aa8b98b..2ae2add4f3 100644
--- a/dpdk/lib/librte_fib/trie.c
+++ b/dpdk/lib/librte_fib/trie.c
@@ -240,9 +240,8 @@ tbl8_alloc(struct rte_trie_tbl *dp, uint64_t nh)
 	tbl8_idx = tbl8_get(dp);
 	if (tbl8_idx < 0)
 		return tbl8_idx;
-	tbl8_ptr = (uint8_t *)dp->tbl8 +
-		((tbl8_idx * TRIE_TBL8_GRP_NUM_ENT) <<
-		dp->nh_sz);
+	tbl8_ptr = get_tbl_p_by_idx(dp->tbl8,
+		tbl8_idx * TRIE_TBL8_GRP_NUM_ENT, dp->nh_sz);
 	/*Init tbl8 entries with nexthop from tbl24*/
 	write_to_dp((void *)tbl8_ptr, nh, dp->nh_sz,
 		TRIE_TBL8_GRP_NUM_ENT);
@@ -317,7 +316,7 @@ get_idx(const uint8_t *ip, uint32_t prev_idx, int bytes, int first_byte)
 		bitshift = (int8_t)(((first_byte + bytes - 1) - i)*BYTE_SIZE);
 		idx |= ip[i] <<  bitshift;
 	}
-	return (prev_idx * 256) + idx;
+	return (prev_idx * TRIE_TBL8_GRP_NUM_ENT) + idx;
 }
 
 static inline uint64_t
@@ -354,8 +353,8 @@ recycle_root_path(struct rte_trie_tbl *dp, const uint8_t *ip_part,
 		return;
 
 	if (common_tbl8 != 0) {
-		p = get_tbl_p_by_idx(dp->tbl8, (val >> 1) * 256 + *ip_part,
-			dp->nh_sz);
+		p = get_tbl_p_by_idx(dp->tbl8, (val >> 1) *
+			TRIE_TBL8_GRP_NUM_ENT + *ip_part, dp->nh_sz);
 		recycle_root_path(dp, ip_part + 1, common_tbl8 - 1, p);
 	}
 	tbl8_recycle(dp, prev, val >> 1);
@@ -388,7 +387,8 @@ build_common_root(struct rte_trie_tbl *dp, const uint8_t *ip,
 		j = i;
 		cur_tbl = dp->tbl8;
 	}
-	*tbl = get_tbl_p_by_idx(cur_tbl, prev_idx * 256, dp->nh_sz);
+	*tbl = get_tbl_p_by_idx(cur_tbl, prev_idx * TRIE_TBL8_GRP_NUM_ENT,
+		dp->nh_sz);
 	return 0;
 }
 
@@ -411,8 +411,8 @@ write_edge(struct rte_trie_tbl *dp, const uint8_t *ip_part, uint64_t next_hop,
 				return tbl8_idx;
 			val = (tbl8_idx << 1)|TRIE_EXT_ENT;
 		}
-		p = get_tbl_p_by_idx(dp->tbl8, (tbl8_idx * 256) + *ip_part,
-			dp->nh_sz);
+		p = get_tbl_p_by_idx(dp->tbl8, (tbl8_idx *
+			TRIE_TBL8_GRP_NUM_ENT) + *ip_part, dp->nh_sz);
 		ret = write_edge(dp, ip_part + 1, next_hop, len - 1, edge, p);
 		if (ret < 0)
 			return ret;
@@ -420,8 +420,8 @@ write_edge(struct rte_trie_tbl *dp, const uint8_t *ip_part, uint64_t next_hop,
 			write_to_dp((uint8_t *)p + (1 << dp->nh_sz),
 				next_hop << 1, dp->nh_sz, UINT8_MAX - *ip_part);
 		} else {
-			write_to_dp(get_tbl_p_by_idx(dp->tbl8, tbl8_idx * 256,
-				dp->nh_sz),
+			write_to_dp(get_tbl_p_by_idx(dp->tbl8, tbl8_idx *
+				TRIE_TBL8_GRP_NUM_ENT, dp->nh_sz),
 				next_hop << 1, dp->nh_sz, *ip_part);
 		}
 		tbl8_recycle(dp, &val, tbl8_idx);
diff --git a/dpdk/lib/librte_flow_classify/rte_flow_classify.h b/dpdk/lib/librte_flow_classify/rte_flow_classify.h
index 74d1ecaf50..82ea92b6a6 100644
--- a/dpdk/lib/librte_flow_classify/rte_flow_classify.h
+++ b/dpdk/lib/librte_flow_classify/rte_flow_classify.h
@@ -8,9 +8,11 @@
 /**
  * @file
  *
- * RTE Flow Classify Library
+ * RTE Flow Classify Library.
  *
- * @b EXPERIMENTAL: this API may change without prior notice
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
  *
  * This library provides flow record information with some measured properties.
  *
diff --git a/dpdk/lib/librte_gro/rte_gro.c b/dpdk/lib/librte_gro/rte_gro.c
index 6618f4d32d..24e413d8ea 100644
--- a/dpdk/lib/librte_gro/rte_gro.c
+++ b/dpdk/lib/librte_gro/rte_gro.c
@@ -27,18 +27,21 @@ static gro_tbl_pkt_count_fn tbl_pkt_count_fn[RTE_GRO_TYPE_MAX_NUM] = {
 			NULL};
 
 #define IS_IPV4_TCP_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \
-		((ptype & RTE_PTYPE_L4_TCP) == RTE_PTYPE_L4_TCP))
+		((ptype & RTE_PTYPE_L4_TCP) == RTE_PTYPE_L4_TCP) && \
+		(RTE_ETH_IS_TUNNEL_PKT(ptype) == 0))
 
 #define IS_IPV4_VXLAN_TCP4_PKT(ptype) (RTE_ETH_IS_IPV4_HDR(ptype) && \
 		((ptype & RTE_PTYPE_L4_UDP) == RTE_PTYPE_L4_UDP) && \
 		((ptype & RTE_PTYPE_TUNNEL_VXLAN) == \
 		 RTE_PTYPE_TUNNEL_VXLAN) && \
-		 ((ptype & RTE_PTYPE_INNER_L4_TCP) == \
-		  RTE_PTYPE_INNER_L4_TCP) && \
-		  (((ptype & RTE_PTYPE_INNER_L3_MASK) & \
-		    (RTE_PTYPE_INNER_L3_IPV4 | \
-		     RTE_PTYPE_INNER_L3_IPV4_EXT | \
-		     RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN)) != 0))
+		((ptype & RTE_PTYPE_INNER_L4_TCP) == \
+		 RTE_PTYPE_INNER_L4_TCP) && \
+		(((ptype & RTE_PTYPE_INNER_L3_MASK) == \
+		  RTE_PTYPE_INNER_L3_IPV4) || \
+		 ((ptype & RTE_PTYPE_INNER_L3_MASK) == \
+		  RTE_PTYPE_INNER_L3_IPV4_EXT) || \
+		 ((ptype & RTE_PTYPE_INNER_L3_MASK) == \
+		  RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN)))
 
 /*
  * GRO context structure. It keeps the table structures, which are
diff --git a/dpdk/lib/librte_gso/gso_udp4.c b/dpdk/lib/librte_gso/gso_udp4.c
index 21fea09273..6fa68f243a 100644
--- a/dpdk/lib/librte_gso/gso_udp4.c
+++ b/dpdk/lib/librte_gso/gso_udp4.c
@@ -69,7 +69,10 @@ gso_udp4_segment(struct rte_mbuf *pkt,
 		return 1;
 	}
 
-	pyld_unit_size = gso_size - hdr_offset;
+	/* pyld_unit_size must be a multiple of 8 because frag_off
+	 * uses 8 bytes as unit.
+	 */
+	pyld_unit_size = (gso_size - hdr_offset) & ~7U;
 
 	/* Segment the payload */
 	ret = gso_do_segment(pkt, hdr_offset, pyld_unit_size, direct_pool,
diff --git a/dpdk/lib/librte_hash/meson.build b/dpdk/lib/librte_hash/meson.build
index 5d02b3084f..bce11ad9e0 100644
--- a/dpdk/lib/librte_hash/meson.build
+++ b/dpdk/lib/librte_hash/meson.build
@@ -1,10 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2017 Intel Corporation
 
-headers = files('rte_cmp_arm64.h',
-	'rte_cmp_x86.h',
-	'rte_crc_arm64.h',
-	'rte_cuckoo_hash.h',
+headers = files('rte_crc_arm64.h',
 	'rte_fbk_hash.h',
 	'rte_hash_crc.h',
 	'rte_hash.h',
diff --git a/dpdk/lib/librte_hash/rte_cuckoo_hash.c b/dpdk/lib/librte_hash/rte_cuckoo_hash.c
index 87a4c01f2f..51ebae9cd9 100644
--- a/dpdk/lib/librte_hash/rte_cuckoo_hash.c
+++ b/dpdk/lib/librte_hash/rte_cuckoo_hash.c
@@ -144,6 +144,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	unsigned int no_free_on_del = 0;
 	uint32_t *ext_bkt_to_free = NULL;
 	uint32_t *tbl_chng_cnt = NULL;
+	struct lcore_cache *local_free_slots = NULL;
 	unsigned int readwrite_concur_lf_support = 0;
 
 	rte_hash_function default_hash_func = (rte_hash_function)rte_jhash;
@@ -369,9 +370,13 @@ rte_hash_create(const struct rte_hash_parameters *params)
 #endif
 
 	if (use_local_cache) {
-		h->local_free_slots = rte_zmalloc_socket(NULL,
+		local_free_slots = rte_zmalloc_socket(NULL,
 				sizeof(struct lcore_cache) * RTE_MAX_LCORE,
 				RTE_CACHE_LINE_SIZE, params->socket_id);
+		if (local_free_slots == NULL) {
+			RTE_LOG(ERR, HASH, "local free slots memory allocation failed\n");
+			goto err_unlock;
+		}
 	}
 
 	/* Default hash function */
@@ -402,6 +407,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	*h->tbl_chng_cnt = 0;
 	h->hw_trans_mem_support = hw_trans_mem_support;
 	h->use_local_cache = use_local_cache;
+	h->local_free_slots = local_free_slots;
 	h->readwrite_concur_support = readwrite_concur_support;
 	h->ext_table_support = ext_table_support;
 	h->writer_takes_lock = writer_takes_lock;
@@ -447,6 +453,7 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	rte_ring_free(r);
 	rte_ring_free(r_ext);
 	rte_free(te);
+	rte_free(local_free_slots);
 	rte_free(h);
 	rte_free(buckets);
 	rte_free(buckets_ext);
diff --git a/dpdk/lib/librte_hash/rte_hash.h b/dpdk/lib/librte_hash/rte_hash.h
index 0d73370dc4..ab7be1d528 100644
--- a/dpdk/lib/librte_hash/rte_hash.h
+++ b/dpdk/lib/librte_hash/rte_hash.h
@@ -51,8 +51,6 @@ extern "C" {
 
 /** Flag to support lock free reader writer concurrency. Both single writer
  * and multi writer use cases are supported.
- * Currently, extendable bucket table feature is not supported with
- * this feature.
  */
 #define RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF 0x20
 
diff --git a/dpdk/lib/librte_ip_frag/rte_ipv4_reassembly.c b/dpdk/lib/librte_ip_frag/rte_ipv4_reassembly.c
index 1dda8aca02..69666c8b82 100644
--- a/dpdk/lib/librte_ip_frag/rte_ipv4_reassembly.c
+++ b/dpdk/lib/librte_ip_frag/rte_ipv4_reassembly.c
@@ -104,6 +104,7 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 	const unaligned_uint64_t *psd;
 	uint16_t flag_offset, ip_ofs, ip_flag;
 	int32_t ip_len;
+	int32_t trim;
 
 	flag_offset = rte_be_to_cpu_16(ip_hdr->fragment_offset);
 	ip_ofs = (uint16_t)(flag_offset & RTE_IPV4_HDR_OFFSET_MASK);
@@ -117,14 +118,15 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 
 	ip_ofs *= RTE_IPV4_HDR_OFFSET_UNITS;
 	ip_len = rte_be_to_cpu_16(ip_hdr->total_length) - mb->l3_len;
+	trim = mb->pkt_len - (ip_len + mb->l3_len + mb->l2_len);
 
 	IP_FRAG_LOG(DEBUG, "%s:%d:\n"
-		"mbuf: %p, tms: %" PRIu64
-		", key: <%" PRIx64 ", %#x>, ofs: %u, len: %d, flags: %#x\n"
+		"mbuf: %p, tms: %" PRIu64 ", key: <%" PRIx64 ", %#x>"
+		"ofs: %u, len: %d, padding: %d, flags: %#x\n"
 		"tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, "
 		"max_entries: %u, use_entries: %u\n\n",
 		__func__, __LINE__,
-		mb, tms, key.src_dst[0], key.id, ip_ofs, ip_len, ip_flag,
+		mb, tms, key.src_dst[0], key.id, ip_ofs, ip_len, trim, ip_flag,
 		tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries,
 		tbl->use_entries);
 
@@ -134,6 +136,9 @@ rte_ipv4_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 		return NULL;
 	}
 
+	if (unlikely(trim > 0))
+		rte_pktmbuf_trim(mb, trim);
+
 	/* try to find/add entry into the fragment's table. */
 	if ((fp = ip_frag_find(tbl, dr, &key, tms)) == NULL) {
 		IP_FRAG_MBUF2DR(dr, mb);
diff --git a/dpdk/lib/librte_ip_frag/rte_ipv6_reassembly.c b/dpdk/lib/librte_ip_frag/rte_ipv6_reassembly.c
index ad01055184..6bc0bf792a 100644
--- a/dpdk/lib/librte_ip_frag/rte_ipv6_reassembly.c
+++ b/dpdk/lib/librte_ip_frag/rte_ipv6_reassembly.c
@@ -142,6 +142,7 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 	struct ip_frag_key key;
 	uint16_t ip_ofs;
 	int32_t ip_len;
+	int32_t trim;
 
 	rte_memcpy(&key.src_dst[0], ip_hdr->src_addr, 16);
 	rte_memcpy(&key.src_dst[2], ip_hdr->dst_addr, 16);
@@ -158,16 +159,17 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 	 * this is what we remove from the payload len.
 	 */
 	ip_len = rte_be_to_cpu_16(ip_hdr->payload_len) - sizeof(*frag_hdr);
+	trim = mb->pkt_len - (ip_len + mb->l3_len + mb->l2_len);
 
 	IP_FRAG_LOG(DEBUG, "%s:%d:\n"
 		"mbuf: %p, tms: %" PRIu64
 		", key: <" IPv6_KEY_BYTES_FMT ", %#x>, "
-		"ofs: %u, len: %d, flags: %#x\n"
+		"ofs: %u, len: %d, padding: %d, flags: %#x\n"
 		"tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, "
 		"max_entries: %u, use_entries: %u\n\n",
 		__func__, __LINE__,
 		mb, tms, IPv6_KEY_BYTES(key.src_dst), key.id, ip_ofs, ip_len,
-		RTE_IPV6_GET_MF(frag_hdr->frag_data),
+		trim, RTE_IPV6_GET_MF(frag_hdr->frag_data),
 		tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries,
 		tbl->use_entries);
 
@@ -177,6 +179,9 @@ rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,
 		return NULL;
 	}
 
+	if (unlikely(trim > 0))
+		rte_pktmbuf_trim(mb, trim);
+
 	/* try to find/add entry into the fragment's table. */
 	fp = ip_frag_find(tbl, dr, &key, tms);
 	if (fp == NULL) {
diff --git a/dpdk/lib/librte_ipsec/ipsec_sad.c b/dpdk/lib/librte_ipsec/ipsec_sad.c
index db2c44c804..31b5956d89 100644
--- a/dpdk/lib/librte_ipsec/ipsec_sad.c
+++ b/dpdk/lib/librte_ipsec/ipsec_sad.c
@@ -94,6 +94,8 @@ add_specific(struct rte_ipsec_sad *sad, const void *key,
 
 	/* Update a counter for a given SPI */
 	ret = rte_hash_lookup(sad->hash[RTE_IPSEC_SAD_SPI_ONLY], key);
+	if (ret < 0)
+		return ret;
 	if (key_type == RTE_IPSEC_SAD_SPI_DIP)
 		sad->cnt_arr[ret].cnt_dip += notexist;
 	else
diff --git a/dpdk/lib/librte_ipsec/rte_ipsec.h b/dpdk/lib/librte_ipsec/rte_ipsec.h
index f3b1f936b9..f2da7ace9c 100644
--- a/dpdk/lib/librte_ipsec/rte_ipsec.h
+++ b/dpdk/lib/librte_ipsec/rte_ipsec.h
@@ -7,9 +7,13 @@
 
 /**
  * @file rte_ipsec.h
- * @b EXPERIMENTAL: this API may change without prior notice
  *
  * RTE IPsec support.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
  * librte_ipsec provides a framework for data-path IPsec protocol
  * processing (ESP/AH).
  */
diff --git a/dpdk/lib/librte_ipsec/rte_ipsec_sad.h b/dpdk/lib/librte_ipsec/rte_ipsec_sad.h
index 8386f73df7..cf50a11cb4 100644
--- a/dpdk/lib/librte_ipsec/rte_ipsec_sad.h
+++ b/dpdk/lib/librte_ipsec/rte_ipsec_sad.h
@@ -6,6 +6,8 @@
 #ifndef _RTE_IPSEC_SAD_H_
 #define _RTE_IPSEC_SAD_H_
 
+#include <stdint.h>
+
 #include <rte_compat.h>
 
 /**
diff --git a/dpdk/lib/librte_ipsec/sa.h b/dpdk/lib/librte_ipsec/sa.h
index 51e69ad05a..0cfe82f634 100644
--- a/dpdk/lib/librte_ipsec/sa.h
+++ b/dpdk/lib/librte_ipsec/sa.h
@@ -113,7 +113,7 @@ struct rte_ipsec_sa {
 	 * sqn and replay window
 	 * In case of SA handled by multiple threads *sqn* cacheline
 	 * could be shared by multiple cores.
-	 * To minimise perfomance impact, we try to locate in a separate
+	 * To minimise performance impact, we try to locate in a separate
 	 * place from other frequently accesed data.
 	 */
 	union {
diff --git a/dpdk/lib/librte_kni/rte_kni.c b/dpdk/lib/librte_kni/rte_kni.c
index e388751e33..bcf82cc2d5 100644
--- a/dpdk/lib/librte_kni/rte_kni.c
+++ b/dpdk/lib/librte_kni/rte_kni.c
@@ -145,31 +145,38 @@ kni_reserve_mz(struct rte_kni *kni)
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_TX_Q_MZ_NAME_FMT, kni->name);
-	kni->m_tx_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_tx_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_tx_q == NULL, tx_q_fail);
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_RX_Q_MZ_NAME_FMT, kni->name);
-	kni->m_rx_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_rx_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_rx_q == NULL, rx_q_fail);
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_ALLOC_Q_MZ_NAME_FMT, kni->name);
-	kni->m_alloc_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_alloc_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_alloc_q == NULL, alloc_q_fail);
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_FREE_Q_MZ_NAME_FMT, kni->name);
-	kni->m_free_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_free_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_free_q == NULL, free_q_fail);
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_REQ_Q_MZ_NAME_FMT, kni->name);
-	kni->m_req_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_req_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_req_q == NULL, req_q_fail);
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_RESP_Q_MZ_NAME_FMT, kni->name);
-	kni->m_resp_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_resp_q = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_resp_q == NULL, resp_q_fail);
 
 	snprintf(mz_name, RTE_MEMZONE_NAMESIZE, KNI_SYNC_ADDR_MZ_NAME_FMT, kni->name);
-	kni->m_sync_addr = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY, 0);
+	kni->m_sync_addr = rte_memzone_reserve(mz_name, KNI_FIFO_SIZE, SOCKET_ID_ANY,
+			RTE_MEMZONE_IOVA_CONTIG);
 	KNI_MEM_CHECK(kni->m_sync_addr == NULL, sync_addr_fail);
 
 	return 0;
diff --git a/dpdk/lib/librte_kni/rte_kni.h b/dpdk/lib/librte_kni/rte_kni.h
index f1bb782c68..855facd1a3 100644
--- a/dpdk/lib/librte_kni/rte_kni.h
+++ b/dpdk/lib/librte_kni/rte_kni.h
@@ -212,7 +212,7 @@ const char *rte_kni_get_name(const struct rte_kni *kni);
 
 /**
  * Register KNI request handling for a specified port,and it can
- * be called by master process or slave process.
+ * be called by primary process or secondary process.
  *
  * @param kni
  *  pointer to struct rte_kni.
diff --git a/dpdk/lib/librte_kvargs/rte_kvargs.c b/dpdk/lib/librte_kvargs/rte_kvargs.c
index d39332999e..285081c86c 100644
--- a/dpdk/lib/librte_kvargs/rte_kvargs.c
+++ b/dpdk/lib/librte_kvargs/rte_kvargs.c
@@ -50,6 +50,8 @@ rte_kvargs_tokenize(struct rte_kvargs *kvlist, const char *params)
 			/* Find the end of the list. */
 			while (str[strlen(str) - 1] != ']') {
 				/* Restore the comma erased by strtok_r(). */
+				if (ctx1 == NULL || ctx1[0] == '\0')
+					return -1; /* no closing bracket */
 				str[strlen(str)] = ',';
 				/* Parse until next comma. */
 				str = strtok_r(NULL, RTE_KVARGS_PAIRS_DELIM, &ctx1);
diff --git a/dpdk/lib/librte_kvargs/rte_kvargs.h b/dpdk/lib/librte_kvargs/rte_kvargs.h
index 1946195de4..eff598e08b 100644
--- a/dpdk/lib/librte_kvargs/rte_kvargs.h
+++ b/dpdk/lib/librte_kvargs/rte_kvargs.h
@@ -171,7 +171,7 @@ unsigned rte_kvargs_count(const struct rte_kvargs *kvlist,
  *   0 if the strings match.
  *   !0 otherwise or on error.
  *
- *   Unless strcmp, comparison ordering is not kept.
+ *   Unlike strcmp, comparison ordering is not kept.
  *   In order for rte_kvargs_process to stop processing on match error,
  *   a negative value is returned even if strcmp had returned a positive one.
  */
diff --git a/dpdk/lib/librte_latencystats/rte_latencystats.c b/dpdk/lib/librte_latencystats/rte_latencystats.c
index 98e018939e..ba2fff3bcb 100644
--- a/dpdk/lib/librte_latencystats/rte_latencystats.c
+++ b/dpdk/lib/librte_latencystats/rte_latencystats.c
@@ -42,6 +42,7 @@ struct rte_latency_stats {
 	float avg_latency; /**< Average latency in nano seconds */
 	float max_latency; /**< Maximum latency in nano seconds */
 	float jitter; /** Latency variation */
+	rte_spinlock_t lock; /** Latency calculation lock */
 };
 
 static struct rte_latency_stats *glob_stats;
@@ -164,6 +165,7 @@ calc_latency(uint16_t pid __rte_unused,
 			latency[cnt++] = now - pkts[i]->timestamp;
 	}
 
+	rte_spinlock_lock(&glob_stats->lock);
 	for (i = 0; i < cnt; i++) {
 		/*
 		 * The jitter is calculated as statistical mean of interpacket
@@ -193,6 +195,7 @@ calc_latency(uint16_t pid __rte_unused,
 			alpha * (latency[i] - glob_stats->avg_latency);
 		prev_latency = latency[i];
 	}
+	rte_spinlock_unlock(&glob_stats->lock);
 
 	return nb_pkts;
 }
@@ -223,6 +226,7 @@ rte_latencystats_init(uint64_t app_samp_intvl,
 	}
 
 	glob_stats = mz->addr;
+	rte_spinlock_init(&glob_stats->lock);
 	samp_intvl = app_samp_intvl * latencystat_cycles_per_ns();
 
 	/** Register latency stats with stats library */
diff --git a/dpdk/lib/librte_lpm/meson.build b/dpdk/lib/librte_lpm/meson.build
index 27ce45b531..021ac6d8d4 100644
--- a/dpdk/lib/librte_lpm/meson.build
+++ b/dpdk/lib/librte_lpm/meson.build
@@ -7,4 +7,3 @@ headers = files('rte_lpm.h', 'rte_lpm6.h')
 # without worrying about which architecture we actually need
 headers += files('rte_lpm_altivec.h', 'rte_lpm_neon.h', 'rte_lpm_sse.h')
 deps += ['hash']
-use_function_versioning = true
diff --git a/dpdk/lib/librte_lpm/rte_lpm.c b/dpdk/lib/librte_lpm/rte_lpm.c
index b78c487447..2687564194 100644
--- a/dpdk/lib/librte_lpm/rte_lpm.c
+++ b/dpdk/lib/librte_lpm/rte_lpm.c
@@ -22,7 +22,6 @@
 #include <rte_rwlock.h>
 #include <rte_spinlock.h>
 #include <rte_tailq.h>
-#include <rte_function_versioning.h>
 
 #include "rte_lpm.h"
 
diff --git a/dpdk/lib/librte_lpm/rte_lpm6.c b/dpdk/lib/librte_lpm/rte_lpm6.c
index c46e557e23..6e1b18d6fd 100644
--- a/dpdk/lib/librte_lpm/rte_lpm6.c
+++ b/dpdk/lib/librte_lpm/rte_lpm6.c
@@ -25,7 +25,6 @@
 #include <assert.h>
 #include <rte_jhash.h>
 #include <rte_tailq.h>
-#include <rte_function_versioning.h>
 
 #include "rte_lpm6.h"
 
@@ -727,7 +726,8 @@ add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl,
 			tbl8_group_start = tbl8_gindex *
 					RTE_LPM6_TBL8_GROUP_NUM_ENTRIES;
 			memset(&lpm->tbl8[tbl8_group_start], 0,
-					  RTE_LPM6_TBL8_GROUP_NUM_ENTRIES);
+					RTE_LPM6_TBL8_GROUP_NUM_ENTRIES *
+					sizeof(struct rte_lpm6_tbl_entry));
 
 			/* init the new table's header:
 			 *   save the reference to the owner table
@@ -814,7 +814,7 @@ add_step(struct rte_lpm6 *lpm, struct rte_lpm6_tbl_entry *tbl,
  *
  *	Returns:
  *    0 on success
- *    -ENOSPC not enought tbl8 left
+ *    -ENOSPC not enough tbl8 left
  */
 static int
 simulate_add(struct rte_lpm6 *lpm, const uint8_t *masked_ip, uint8_t depth)
@@ -844,7 +844,7 @@ simulate_add(struct rte_lpm6 *lpm, const uint8_t *masked_ip, uint8_t depth)
 	}
 
 	if (tbl8_available(lpm) < total_need_tbl_nb)
-		/* not enought tbl8 to add a rule */
+		/* not enough tbl8 to add a rule */
 		return -ENOSPC;
 
 	return 0;
@@ -1212,7 +1212,7 @@ rule_find_range(struct rte_lpm6 *lpm, const uint8_t *ip, uint8_t depth,
 		/* minus top level */
 		depth -= 24;
 
-		/* interate through levels (tbl8s)
+		/* iterate through levels (tbl8s)
 		 * until we reach the last one
 		 */
 		while (depth > 8) {
diff --git a/dpdk/lib/librte_lpm/rte_lpm_altivec.h b/dpdk/lib/librte_lpm/rte_lpm_altivec.h
index 228c41b38e..4fbc1b595d 100644
--- a/dpdk/lib/librte_lpm/rte_lpm_altivec.h
+++ b/dpdk/lib/librte_lpm/rte_lpm_altivec.h
@@ -88,28 +88,28 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
 	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[0] = i8.u32[0] +
-			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[0] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
 		tbl[0] = *ptbl;
 	}
 	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[1] = i8.u32[1] +
-			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[1] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
 		tbl[1] = *ptbl;
 	}
 	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[2] = i8.u32[2] +
-			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[2] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
 		tbl[2] = *ptbl;
 	}
 	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[3] = i8.u32[3] +
-			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[3] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
 		tbl[3] = *ptbl;
 	}
diff --git a/dpdk/lib/librte_lpm/rte_lpm_neon.h b/dpdk/lib/librte_lpm/rte_lpm_neon.h
index 6c131d3125..4642a866f1 100644
--- a/dpdk/lib/librte_lpm/rte_lpm_neon.h
+++ b/dpdk/lib/librte_lpm/rte_lpm_neon.h
@@ -81,28 +81,28 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
 	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[0] = i8.u32[0] +
-			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[0] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
 		tbl[0] = *ptbl;
 	}
 	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[1] = i8.u32[1] +
-			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[1] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
 		tbl[1] = *ptbl;
 	}
 	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[2] = i8.u32[2] +
-			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[2] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
 		tbl[2] = *ptbl;
 	}
 	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[3] = i8.u32[3] +
-			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[3] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
 		tbl[3] = *ptbl;
 	}
diff --git a/dpdk/lib/librte_lpm/rte_lpm_sse.h b/dpdk/lib/librte_lpm/rte_lpm_sse.h
index 44770b6ff8..eaa863c522 100644
--- a/dpdk/lib/librte_lpm/rte_lpm_sse.h
+++ b/dpdk/lib/librte_lpm/rte_lpm_sse.h
@@ -82,28 +82,28 @@ rte_lpm_lookupx4(const struct rte_lpm *lpm, xmm_t ip, uint32_t hop[4],
 	if (unlikely((pt & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[0] = i8.u32[0] +
-			(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[0] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[0]];
 		tbl[0] = *ptbl;
 	}
 	if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[1] = i8.u32[1] +
-			(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[1] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[1]];
 		tbl[1] = *ptbl;
 	}
 	if (unlikely((pt2 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[2] = i8.u32[2] +
-			(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[2] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[2]];
 		tbl[2] = *ptbl;
 	}
 	if (unlikely((pt2 >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
 			RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
 		i8.u32[3] = i8.u32[3] +
-			(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
+			(tbl[3] & 0x00FFFFFF) * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
 		ptbl = (const uint32_t *)&lpm->tbl8[i8.u32[3]];
 		tbl[3] = *ptbl;
 	}
diff --git a/dpdk/lib/librte_mbuf/rte_mbuf.h b/dpdk/lib/librte_mbuf/rte_mbuf.h
index 219b110b76..6d080527f6 100644
--- a/dpdk/lib/librte_mbuf/rte_mbuf.h
+++ b/dpdk/lib/librte_mbuf/rte_mbuf.h
@@ -1535,7 +1535,7 @@ static inline int rte_pktmbuf_trim(struct rte_mbuf *m, uint16_t len)
 static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m)
 {
 	__rte_mbuf_sanity_check(m, 1);
-	return !!(m->nb_segs == 1);
+	return m->nb_segs == 1;
 }
 
 /**
diff --git a/dpdk/lib/librte_mbuf/rte_mbuf_core.h b/dpdk/lib/librte_mbuf/rte_mbuf_core.h
index 9a8557d1cc..e7f38422e7 100644
--- a/dpdk/lib/librte_mbuf/rte_mbuf_core.h
+++ b/dpdk/lib/librte_mbuf/rte_mbuf_core.h
@@ -15,7 +15,9 @@
  */
 
 #include <stdint.h>
+
 #include <rte_compat.h>
+#include <rte_byteorder.h>
 #include <generic/rte_atomic.h>
 
 #ifdef __cplusplus
diff --git a/dpdk/lib/librte_mbuf/rte_mbuf_dyn.c b/dpdk/lib/librte_mbuf/rte_mbuf_dyn.c
index d6931f8471..5762008b7e 100644
--- a/dpdk/lib/librte_mbuf/rte_mbuf_dyn.c
+++ b/dpdk/lib/librte_mbuf/rte_mbuf_dyn.c
@@ -19,7 +19,6 @@
 #define RTE_MBUF_DYN_MZNAME "rte_mbuf_dyn"
 
 struct mbuf_dynfield_elt {
-	TAILQ_ENTRY(mbuf_dynfield_elt) next;
 	struct rte_mbuf_dynfield params;
 	size_t offset;
 };
@@ -31,7 +30,6 @@ static struct rte_tailq_elem mbuf_dynfield_tailq = {
 EAL_REGISTER_TAILQ(mbuf_dynfield_tailq);
 
 struct mbuf_dynflag_elt {
-	TAILQ_ENTRY(mbuf_dynflag_elt) next;
 	struct rte_mbuf_dynflag params;
 	unsigned int bitnum;
 };
@@ -69,12 +67,16 @@ process_score(void)
 			shm->free_space[i] = 1;
 	}
 
-	for (off = 0; off < sizeof(struct rte_mbuf); off++) {
+	off = 0;
+	while (off < sizeof(struct rte_mbuf)) {
 		/* get the size of the free zone */
-		for (size = 0; shm->free_space[off + size]; size++)
+		for (size = 0; (off + size) < sizeof(struct rte_mbuf) &&
+			     shm->free_space[off + size]; size++)
 			;
-		if (size == 0)
+		if (size == 0) {
+			off++;
 			continue;
+		}
 
 		/* get the alignment of biggest object that can fit in
 		 * the zone at this offset.
@@ -85,8 +87,10 @@ process_score(void)
 			;
 
 		/* save it in free_space[] */
-		for (i = off; i < off + size; i++)
+		for (i = off; i < off + align; i++)
 			shm->free_space[i] = RTE_MAX(align, shm->free_space[i]);
+
+		off += align;
 	}
 }
 
@@ -168,7 +172,7 @@ __mbuf_dynfield_lookup(const char *name)
 			break;
 	}
 
-	if (te == NULL) {
+	if (te == NULL || mbuf_dynfield == NULL) {
 		rte_errno = ENOENT;
 		return NULL;
 	}
@@ -181,19 +185,15 @@ rte_mbuf_dynfield_lookup(const char *name, struct rte_mbuf_dynfield *params)
 {
 	struct mbuf_dynfield_elt *mbuf_dynfield;
 
-	if (shm == NULL) {
-		rte_errno = ENOENT;
-		return -1;
-	}
-
 	rte_mcfg_tailq_read_lock();
-	mbuf_dynfield = __mbuf_dynfield_lookup(name);
+	if (shm == NULL && init_shared_mem() < 0)
+		mbuf_dynfield = NULL;
+	else
+		mbuf_dynfield = __mbuf_dynfield_lookup(name);
 	rte_mcfg_tailq_read_unlock();
 
-	if (mbuf_dynfield == NULL) {
-		rte_errno = ENOENT;
+	if (mbuf_dynfield == NULL)
 		return -1;
-	}
 
 	if (params != NULL)
 		memcpy(params, &mbuf_dynfield->params, sizeof(*params));
@@ -279,12 +279,15 @@ __rte_mbuf_dynfield_register_offset(const struct rte_mbuf_dynfield *params,
 		mbuf_dynfield_tailq.head, mbuf_dynfield_list);
 
 	te = rte_zmalloc("MBUF_DYNFIELD_TAILQ_ENTRY", sizeof(*te), 0);
-	if (te == NULL)
+	if (te == NULL) {
+		rte_errno = ENOMEM;
 		return -1;
+	}
 
 	mbuf_dynfield = rte_zmalloc("mbuf_dynfield", sizeof(*mbuf_dynfield), 0);
 	if (mbuf_dynfield == NULL) {
 		rte_free(te);
+		rte_errno = ENOMEM;
 		return -1;
 	}
 
@@ -377,19 +380,15 @@ rte_mbuf_dynflag_lookup(const char *name,
 {
 	struct mbuf_dynflag_elt *mbuf_dynflag;
 
-	if (shm == NULL) {
-		rte_errno = ENOENT;
-		return -1;
-	}
-
 	rte_mcfg_tailq_read_lock();
-	mbuf_dynflag = __mbuf_dynflag_lookup(name);
+	if (shm == NULL && init_shared_mem() < 0)
+		mbuf_dynflag = NULL;
+	else
+		mbuf_dynflag = __mbuf_dynflag_lookup(name);
 	rte_mcfg_tailq_read_unlock();
 
-	if (mbuf_dynflag == NULL) {
-		rte_errno = ENOENT;
+	if (mbuf_dynflag == NULL)
 		return -1;
-	}
 
 	if (params != NULL)
 		memcpy(params, &mbuf_dynflag->params, sizeof(*params));
@@ -457,12 +456,15 @@ __rte_mbuf_dynflag_register_bitnum(const struct rte_mbuf_dynflag *params,
 		mbuf_dynflag_tailq.head, mbuf_dynflag_list);
 
 	te = rte_zmalloc("MBUF_DYNFLAG_TAILQ_ENTRY", sizeof(*te), 0);
-	if (te == NULL)
+	if (te == NULL) {
+		rte_errno = ENOMEM;
 		return -1;
+	}
 
 	mbuf_dynflag = rte_zmalloc("mbuf_dynflag", sizeof(*mbuf_dynflag), 0);
 	if (mbuf_dynflag == NULL) {
 		rte_free(te);
+		rte_errno = ENOMEM;
 		return -1;
 	}
 
@@ -542,7 +544,7 @@ void rte_mbuf_dyn_dump(FILE *out)
 			dynflag->params.name, dynflag->bitnum,
 			dynflag->params.flags);
 	}
-	fprintf(out, "Free space in mbuf (0 = free, value = zone alignment):\n");
+	fprintf(out, "Free space in mbuf (0 = occupied, value = free zone alignment):\n");
 	for (i = 0; i < sizeof(struct rte_mbuf); i++) {
 		if ((i % 8) == 0)
 			fprintf(out, "  %4.4zx: ", i);
diff --git a/dpdk/lib/librte_mbuf/rte_mbuf_dyn.h b/dpdk/lib/librte_mbuf/rte_mbuf_dyn.h
index 96c363137e..2a87ef9217 100644
--- a/dpdk/lib/librte_mbuf/rte_mbuf_dyn.h
+++ b/dpdk/lib/librte_mbuf/rte_mbuf_dyn.h
@@ -62,11 +62,20 @@
  * conventions than function names in dpdk:
  * - "rte_mbuf_dynfield_<name>" if defined in mbuf library
  * - "rte_<libname>_dynfield_<name>" if defined in another library
- * - "rte_net_<pmd>_dynfield_<name>" if defined in a in PMD
+ * - "rte_net_<pmd>_dynfield_<name>" if defined in a PMD
  * - any name that does not start with "rte_" in an application
  */
 
+#include <stdio.h>
+#include <stdint.h>
 #include <sys/types.h>
+
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * Maximum length of the dynamic field or flag string.
  */
@@ -250,4 +259,8 @@ void rte_mbuf_dyn_dump(FILE *out);
 #define RTE_MBUF_DYNFIELD_METADATA_NAME "rte_flow_dynfield_metadata"
 #define RTE_MBUF_DYNFLAG_METADATA_NAME "rte_flow_dynflag_metadata"
 
+#ifdef __cplusplus
+}
 #endif
+
+#endif /* _RTE_MBUF_DYN_H_ */
diff --git a/dpdk/lib/librte_mempool/rte_mempool.c b/dpdk/lib/librte_mempool/rte_mempool.c
index 78d8eb941e..89b6d39ac0 100644
--- a/dpdk/lib/librte_mempool/rte_mempool.c
+++ b/dpdk/lib/librte_mempool/rte_mempool.c
@@ -297,8 +297,8 @@ mempool_ops_alloc_once(struct rte_mempool *mp)
  * zone. Return the number of objects added, or a negative value
  * on error.
  */
-int
-rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
+static int
+__rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
 	rte_iova_t iova, size_t len, rte_mempool_memchunk_free_cb_t *free_cb,
 	void *opaque)
 {
@@ -332,7 +332,7 @@ rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
 		off = RTE_PTR_ALIGN_CEIL(vaddr, RTE_MEMPOOL_ALIGN) - vaddr;
 
 	if (off > len) {
-		ret = -EINVAL;
+		ret = 0;
 		goto fail;
 	}
 
@@ -343,7 +343,7 @@ rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
 
 	/* not enough room to store one object */
 	if (i == 0) {
-		ret = -EINVAL;
+		ret = 0;
 		goto fail;
 	}
 
@@ -356,6 +356,21 @@ rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
 	return ret;
 }
 
+int
+rte_mempool_populate_iova(struct rte_mempool *mp, char *vaddr,
+	rte_iova_t iova, size_t len, rte_mempool_memchunk_free_cb_t *free_cb,
+	void *opaque)
+{
+	int ret;
+
+	ret = __rte_mempool_populate_iova(mp, vaddr, iova, len, free_cb,
+					opaque);
+	if (ret == 0)
+		ret = -EINVAL;
+
+	return ret;
+}
+
 static rte_iova_t
 get_iova(void *addr)
 {
@@ -406,8 +421,10 @@ rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
 				break;
 		}
 
-		ret = rte_mempool_populate_iova(mp, addr + off, iova,
+		ret = __rte_mempool_populate_iova(mp, addr + off, iova,
 			phys_len, free_cb, opaque);
+		if (ret == 0)
+			continue;
 		if (ret < 0)
 			goto fail;
 		/* no need to call the free callback for next chunks */
@@ -415,6 +432,9 @@ rte_mempool_populate_virt(struct rte_mempool *mp, char *addr,
 		cnt += ret;
 	}
 
+	if (cnt == 0)
+		return -EINVAL;
+
 	return cnt;
 
  fail:
@@ -463,6 +483,7 @@ rte_mempool_populate_default(struct rte_mempool *mp)
 	unsigned mz_id, n;
 	int ret;
 	bool need_iova_contig_obj;
+	size_t max_alloc_size = SIZE_MAX;
 
 	ret = mempool_ops_alloc_once(mp);
 	if (ret != 0)
@@ -542,30 +563,24 @@ rte_mempool_populate_default(struct rte_mempool *mp)
 		if (min_chunk_size == (size_t)mem_size)
 			mz_flags |= RTE_MEMZONE_IOVA_CONTIG;
 
-		mz = rte_memzone_reserve_aligned(mz_name, mem_size,
+		/* Allocate a memzone, retrying with a smaller area on ENOMEM */
+		do {
+			mz = rte_memzone_reserve_aligned(mz_name,
+				RTE_MIN((size_t)mem_size, max_alloc_size),
 				mp->socket_id, mz_flags, align);
 
-		/* don't try reserving with 0 size if we were asked to reserve
-		 * IOVA-contiguous memory.
-		 */
-		if (min_chunk_size < (size_t)mem_size && mz == NULL) {
-			/* not enough memory, retry with the biggest zone we
-			 * have
-			 */
-			mz = rte_memzone_reserve_aligned(mz_name, 0,
-					mp->socket_id, mz_flags, align);
-		}
+			if (mz != NULL || rte_errno != ENOMEM)
+				break;
+
+			max_alloc_size = RTE_MIN(max_alloc_size,
+						(size_t)mem_size) / 2;
+		} while (mz == NULL && max_alloc_size >= min_chunk_size);
+
 		if (mz == NULL) {
 			ret = -rte_errno;
 			goto fail;
 		}
 
-		if (mz->len < min_chunk_size) {
-			rte_memzone_free(mz);
-			ret = -ENOMEM;
-			goto fail;
-		}
-
 		if (need_iova_contig_obj)
 			iova = mz->iova;
 		else
@@ -645,8 +660,10 @@ rte_mempool_populate_anon(struct rte_mempool *mp)
 	}
 
 	ret = mempool_ops_alloc_once(mp);
-	if (ret != 0)
-		return ret;
+	if (ret < 0) {
+		rte_errno = -ret;
+		return 0;
+	}
 
 	size = get_anon_size(mp);
 	if (size < 0) {
@@ -670,8 +687,10 @@ rte_mempool_populate_anon(struct rte_mempool *mp)
 
 	ret = rte_mempool_populate_virt(mp, addr, size, getpagesize(),
 		rte_mempool_memchunk_anon_free, addr);
-	if (ret == 0)
+	if (ret < 0) {
+		rte_errno = -ret;
 		goto fail;
+	}
 
 	return mp->populated_size;
 
@@ -1141,7 +1160,7 @@ mempool_audit_cache(const struct rte_mempool *mp)
 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
 		const struct rte_mempool_cache *cache;
 		cache = &mp->local_cache[lcore_id];
-		if (cache->len > cache->flushthresh) {
+		if (cache->len > RTE_DIM(cache->objs)) {
 			RTE_LOG(CRIT, MEMPOOL, "badness on cache[%u]\n",
 				lcore_id);
 			rte_panic("MEMPOOL: invalid cache len\n");
diff --git a/dpdk/lib/librte_mempool/rte_mempool.h b/dpdk/lib/librte_mempool/rte_mempool.h
index f81152af96..4907c0808e 100644
--- a/dpdk/lib/librte_mempool/rte_mempool.h
+++ b/dpdk/lib/librte_mempool/rte_mempool.h
@@ -1167,8 +1167,8 @@ int rte_mempool_populate_default(struct rte_mempool *mp);
  *   A pointer to the mempool structure.
  * @return
  *   The number of objects added on success.
- *   On error, the chunk is not added in the memory list of the
- *   mempool and a negative errno is returned.
+ *   On error, 0 is returned, rte_errno is set, and the chunk is not added in
+ *   the memory list of the mempool.
  */
 int rte_mempool_populate_anon(struct rte_mempool *mp);
 
@@ -1653,7 +1653,7 @@ rte_mempool_in_use_count(const struct rte_mempool *mp);
 static inline int
 rte_mempool_full(const struct rte_mempool *mp)
 {
-	return !!(rte_mempool_avail_count(mp) == mp->size);
+	return rte_mempool_avail_count(mp) == mp->size;
 }
 
 /**
@@ -1672,7 +1672,7 @@ rte_mempool_full(const struct rte_mempool *mp)
 static inline int
 rte_mempool_empty(const struct rte_mempool *mp)
 {
-	return !!(rte_mempool_avail_count(mp) == 0);
+	return rte_mempool_avail_count(mp) == 0;
 }
 
 /**
diff --git a/dpdk/lib/librte_mempool/rte_mempool_version.map b/dpdk/lib/librte_mempool/rte_mempool_version.map
index d002dfc46f..d67ed2e2b9 100644
--- a/dpdk/lib/librte_mempool/rte_mempool_version.map
+++ b/dpdk/lib/librte_mempool/rte_mempool_version.map
@@ -4,18 +4,14 @@ DPDK_20.0 {
 	rte_mempool_audit;
 	rte_mempool_avail_count;
 	rte_mempool_cache_create;
-	rte_mempool_cache_flush;
 	rte_mempool_cache_free;
 	rte_mempool_calc_obj_size;
 	rte_mempool_check_cookies;
 	rte_mempool_contig_blocks_check_cookies;
 	rte_mempool_create;
 	rte_mempool_create_empty;
-	rte_mempool_default_cache;
 	rte_mempool_dump;
 	rte_mempool_free;
-	rte_mempool_generic_get;
-	rte_mempool_generic_put;
 	rte_mempool_in_use_count;
 	rte_mempool_list_dump;
 	rte_mempool_lookup;
diff --git a/dpdk/lib/librte_meter/rte_meter_version.map b/dpdk/lib/librte_meter/rte_meter_version.map
index 46410b0369..3fc7ddd199 100644
--- a/dpdk/lib/librte_meter/rte_meter_version.map
+++ b/dpdk/lib/librte_meter/rte_meter_version.map
@@ -1,12 +1,8 @@
 DPDK_20.0 {
 	global:
 
-	rte_meter_srtcm_color_aware_check;
-	rte_meter_srtcm_color_blind_check;
 	rte_meter_srtcm_config;
 	rte_meter_srtcm_profile_config;
-	rte_meter_trtcm_color_aware_check;
-	rte_meter_trtcm_color_blind_check;
 	rte_meter_trtcm_config;
 	rte_meter_trtcm_profile_config;
 
@@ -16,8 +12,6 @@ DPDK_20.0 {
 EXPERIMENTAL {
 	global:
 
-	rte_meter_trtcm_rfc4115_color_aware_check;
-	rte_meter_trtcm_rfc4115_color_blind_check;
 	rte_meter_trtcm_rfc4115_config;
 	rte_meter_trtcm_rfc4115_profile_config;
 };
diff --git a/dpdk/lib/librte_net/rte_ip.h b/dpdk/lib/librte_net/rte_ip.h
index 1ceb7b7931..d34c0611f0 100644
--- a/dpdk/lib/librte_net/rte_ip.h
+++ b/dpdk/lib/librte_net/rte_ip.h
@@ -139,8 +139,11 @@ __rte_raw_cksum(const void *buf, size_t len, uint32_t sum)
 	}
 
 	/* if length is in odd bytes */
-	if (len == 1)
-		sum += *((const uint8_t *)u16_buf);
+	if (len == 1) {
+		uint16_t left = 0;
+		*(uint8_t *)&left = *(const uint8_t *)u16_buf;
+		sum += left;
+	}
 
 	return sum;
 }
@@ -222,6 +225,9 @@ rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
 			break;
 		off -= seglen;
 	}
+	RTE_ASSERT(seg != NULL);
+	if (seg == NULL)
+		return -1;
 	seglen -= off;
 	buf = rte_pktmbuf_mtod_offset(seg, const char *, off);
 	if (seglen >= len) {
@@ -267,7 +273,7 @@ rte_ipv4_cksum(const struct rte_ipv4_hdr *ipv4_hdr)
 {
 	uint16_t cksum;
 	cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct rte_ipv4_hdr));
-	return (cksum == 0xffff) ? cksum : (uint16_t)~cksum;
+	return (uint16_t)~cksum;
 }
 
 /**
@@ -324,8 +330,7 @@ rte_ipv4_phdr_cksum(const struct rte_ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
  * @param l4_hdr
  *   The pointer to the beginning of the L4 header.
  * @return
- *   The complemented checksum to set in the IP packet
- *   or 0 on error
+ *   The complemented checksum to set in the IP packet.
  */
 static inline uint16_t
 rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr)
@@ -344,7 +349,12 @@ rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr)
 
 	cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
 	cksum = (~cksum) & 0xffff;
-	if (cksum == 0)
+	/*
+	 * Per RFC 768:If the computed checksum is zero for UDP,
+	 * it is transmitted as all ones
+	 * (the equivalent in one's complement arithmetic).
+	 */
+	if (cksum == 0 && ipv4_hdr->next_proto_id == IPPROTO_UDP)
 		cksum = 0xffff;
 
 	return (uint16_t)cksum;
@@ -436,7 +446,12 @@ rte_ipv6_udptcp_cksum(const struct rte_ipv6_hdr *ipv6_hdr, const void *l4_hdr)
 
 	cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
 	cksum = (~cksum) & 0xffff;
-	if (cksum == 0)
+	/*
+	 * Per RFC 768: If the computed checksum is zero for UDP,
+	 * it is transmitted as all ones
+	 * (the equivalent in one's complement arithmetic).
+	 */
+	if (cksum == 0 && ipv6_hdr->proto == IPPROTO_UDP)
 		cksum = 0xffff;
 
 	return (uint16_t)cksum;
diff --git a/dpdk/lib/librte_net/rte_mpls.h b/dpdk/lib/librte_net/rte_mpls.h
index 32b6431219..14663f51b4 100644
--- a/dpdk/lib/librte_net/rte_mpls.h
+++ b/dpdk/lib/librte_net/rte_mpls.h
@@ -21,6 +21,7 @@ extern "C" {
 /**
  * MPLS header.
  */
+__extension__
 struct rte_mpls_hdr {
 	uint16_t tag_msb;   /**< Label(msb). */
 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
diff --git a/dpdk/lib/librte_pci/rte_pci.c b/dpdk/lib/librte_pci/rte_pci.c
index a753cf3eca..5f7726fa89 100644
--- a/dpdk/lib/librte_pci/rte_pci.c
+++ b/dpdk/lib/librte_pci/rte_pci.c
@@ -20,6 +20,7 @@
 #include <rte_eal.h>
 #include <rte_string_fns.h>
 #include <rte_common.h>
+#include <rte_debug.h>
 
 #include "rte_pci.h"
 
@@ -34,6 +35,12 @@ get_u8_pciaddr_field(const char *in, void *_u8, char dlm)
 	if (*in == '\0')
 		return NULL;
 
+	/* PCI field starting with spaces is forbidden.
+	 * Negative wrap-around is not reported as an error by strtoul.
+	 */
+	if (*in == ' ' || *in == '-')
+		return NULL;
+
 	errno = 0;
 	val = strtoul(in, &end, 16);
 	if (errno != 0 || end[0] != dlm || val > UINT8_MAX) {
@@ -69,11 +76,17 @@ pci_dbdf_parse(const char *input, struct rte_pci_addr *dev_addr)
 	unsigned long val;
 	char *end;
 
+	/* PCI id starting with spaces is forbidden.
+	 * Negative wrap-around is not reported as an error by strtoul.
+	 */
+	if (*in == ' ' || *in == '-')
+		return -EINVAL;
+
 	errno = 0;
 	val = strtoul(in, &end, 16);
-	if (errno != 0 || end[0] != ':' || val > UINT16_MAX)
+	if (errno != 0 || end[0] != ':' || val > UINT32_MAX)
 		return -EINVAL;
-	dev_addr->domain = (uint16_t)val;
+	dev_addr->domain = (uint32_t)val;
 	in = end + 1;
 	in = get_u8_pciaddr_field(in, &dev_addr->bus, ':');
 	if (in == NULL)
diff --git a/dpdk/lib/librte_pci/rte_pci.h b/dpdk/lib/librte_pci/rte_pci.h
index c87891405c..db83919653 100644
--- a/dpdk/lib/librte_pci/rte_pci.h
+++ b/dpdk/lib/librte_pci/rte_pci.h
@@ -17,18 +17,12 @@ extern "C" {
 #endif
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <limits.h>
-#include <errno.h>
 #include <sys/queue.h>
-#include <stdint.h>
 #include <inttypes.h>
 
-#include <rte_debug.h>
-#include <rte_interrupts.h>
-
 /** Formatting string for PCI device identifier: Ex: 0000:00:01.0 */
-#define PCI_PRI_FMT "%.4" PRIx16 ":%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8
+#define PCI_PRI_FMT "%.4" PRIx32 ":%.2" PRIx8 ":%.2" PRIx8 ".%" PRIx8
 #define PCI_PRI_STR_SIZE sizeof("XXXXXXXX:XX:XX.X")
 
 /** Short formatting string, without domain, for PCI device: Ex: 00:01.0 */
diff --git a/dpdk/lib/librte_port/rte_port_source_sink.c b/dpdk/lib/librte_port/rte_port_source_sink.c
index 74b7385a28..68575c9833 100644
--- a/dpdk/lib/librte_port/rte_port_source_sink.c
+++ b/dpdk/lib/librte_port/rte_port_source_sink.c
@@ -116,7 +116,7 @@ pcap_source_load(struct rte_port_source *port,
 	}
 
 	for (i = 0; i < n_pkts; i++) {
-		pkt = pcap_next(pcap_handle, &pcap_hdr);
+		pcap_next(pcap_handle, &pcap_hdr);
 		port->pkt_len[i] = RTE_MIN(max_len, pcap_hdr.len);
 		pkt_len_aligns[i] = RTE_CACHE_LINE_ROUNDUP(
 			port->pkt_len[i]);
diff --git a/dpdk/lib/librte_power/Makefile b/dpdk/lib/librte_power/Makefile
index 9a6db07e5f..16e384e446 100644
--- a/dpdk/lib/librte_power/Makefile
+++ b/dpdk/lib/librte_power/Makefile
@@ -19,6 +19,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_POWER) += rte_power_empty_poll.c
 SRCS-$(CONFIG_RTE_LIBRTE_POWER) += power_pstate_cpufreq.c
 
 # install this header file
-SYMLINK-$(CONFIG_RTE_LIBRTE_POWER)-include := rte_power.h  rte_power_empty_poll.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_POWER)-include := rte_power.h  rte_power_empty_poll.h rte_power_guest_channel.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/dpdk/lib/librte_power/channel_commands.h b/dpdk/lib/librte_power/channel_commands.h
deleted file mode 100644
index adc8e5ca27..0000000000
--- a/dpdk/lib/librte_power/channel_commands.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2014 Intel Corporation
- */
-
-#ifndef CHANNEL_COMMANDS_H_
-#define CHANNEL_COMMANDS_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-#include <stdbool.h>
-
-/* --- Incoming messages --- */
-
-/* Valid Commands */
-#define CPU_POWER               1
-#define CPU_POWER_CONNECT       2
-#define PKT_POLICY              3
-#define PKT_POLICY_REMOVE       4
-
-/* CPU Power Command Scaling */
-#define CPU_POWER_SCALE_UP      1
-#define CPU_POWER_SCALE_DOWN    2
-#define CPU_POWER_SCALE_MAX     3
-#define CPU_POWER_SCALE_MIN     4
-#define CPU_POWER_ENABLE_TURBO  5
-#define CPU_POWER_DISABLE_TURBO 6
-
-/* CPU Power Queries */
-#define CPU_POWER_QUERY_FREQ_LIST  7
-#define CPU_POWER_QUERY_FREQ       8
-#define CPU_POWER_QUERY_CAPS_LIST  9
-#define CPU_POWER_QUERY_CAPS       10
-
-/* --- Outgoing messages --- */
-
-/* Generic Power Command Response */
-#define CPU_POWER_CMD_ACK       1
-#define CPU_POWER_CMD_NACK      2
-
-/* CPU Power Query Responses */
-#define CPU_POWER_FREQ_LIST     3
-#define CPU_POWER_CAPS_LIST     4
-
-#define HOURS 24
-
-#define MAX_VFS 10
-#define VM_MAX_NAME_SZ 32
-
-#define MAX_VCPU_PER_VM         8
-
-struct t_boost_status {
-	bool tbEnabled;
-};
-
-struct timer_profile {
-	int busy_hours[HOURS];
-	int quiet_hours[HOURS];
-	int hours_to_use_traffic_profile[HOURS];
-};
-
-enum workload {HIGH, MEDIUM, LOW};
-enum policy_to_use {
-	TRAFFIC,
-	TIME,
-	WORKLOAD,
-	BRANCH_RATIO
-};
-
-struct traffic {
-	uint32_t min_packet_thresh;
-	uint32_t avg_max_packet_thresh;
-	uint32_t max_max_packet_thresh;
-};
-
-#define CORE_TYPE_VIRTUAL 0
-#define CORE_TYPE_PHYSICAL 1
-
-struct channel_packet {
-	uint64_t resource_id; /**< core_num, device */
-	uint32_t unit;        /**< scale down/up/min/max */
-	uint32_t command;     /**< Power, IO, etc */
-	char vm_name[VM_MAX_NAME_SZ];
-
-	uint64_t vfid[MAX_VFS];
-	int nb_mac_to_monitor;
-	struct traffic traffic_policy;
-	uint8_t vcpu_to_control[MAX_VCPU_PER_VM];
-	uint8_t num_vcpu;
-	struct timer_profile timer_policy;
-	bool core_type;
-	enum workload workload;
-	enum policy_to_use policy_to_use;
-	struct t_boost_status t_boost_status;
-};
-
-struct channel_packet_freq_list {
-	uint64_t resource_id; /**< core_num, device */
-	uint32_t unit;        /**< scale down/up/min/max */
-	uint32_t command;     /**< Power, IO, etc */
-	char vm_name[VM_MAX_NAME_SZ];
-
-	uint32_t freq_list[MAX_VCPU_PER_VM];
-	uint8_t num_vcpu;
-};
-
-struct channel_packet_caps_list {
-	uint64_t resource_id; /**< core_num, device */
-	uint32_t unit;        /**< scale down/up/min/max */
-	uint32_t command;     /**< Power, IO, etc */
-	char vm_name[VM_MAX_NAME_SZ];
-
-	uint64_t turbo[MAX_VCPU_PER_VM];
-	uint64_t priority[MAX_VCPU_PER_VM];
-	uint8_t num_vcpu;
-};
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* CHANNEL_COMMANDS_H_ */
diff --git a/dpdk/lib/librte_power/guest_channel.c b/dpdk/lib/librte_power/guest_channel.c
index b984d55bc8..4dadf5ef9f 100644
--- a/dpdk/lib/librte_power/guest_channel.c
+++ b/dpdk/lib/librte_power/guest_channel.c
@@ -14,9 +14,9 @@
 
 
 #include <rte_log.h>
+#include <rte_power.h>
 
 #include "guest_channel.h"
-#include "channel_commands.h"
 
 #define RTE_LOGTYPE_GUEST_CHANNEL RTE_LOGTYPE_USER1
 
@@ -29,7 +29,7 @@ int
 guest_channel_host_connect(const char *path, unsigned int lcore_id)
 {
 	int flags, ret;
-	struct channel_packet pkt;
+	struct rte_power_channel_packet pkt;
 	char fd_path[PATH_MAX];
 	int fd = -1;
 
@@ -74,7 +74,7 @@ guest_channel_host_connect(const char *path, unsigned int lcore_id)
 	/* Send a test packet, this command is ignored by the host, but a successful
 	 * send indicates that the host endpoint is monitoring.
 	 */
-	pkt.command = CPU_POWER_CONNECT;
+	pkt.command = RTE_POWER_CPU_POWER_CONNECT;
 	global_fds[lcore_id] = fd;
 	ret = guest_channel_send_msg(&pkt, lcore_id);
 	if (ret != 0) {
@@ -93,7 +93,8 @@ guest_channel_host_connect(const char *path, unsigned int lcore_id)
 }
 
 int
-guest_channel_send_msg(struct channel_packet *pkt, unsigned int lcore_id)
+guest_channel_send_msg(struct rte_power_channel_packet *pkt,
+		unsigned int lcore_id)
 {
 	int ret, buffer_len = sizeof(*pkt);
 	void *buffer = pkt;
@@ -123,7 +124,7 @@ guest_channel_send_msg(struct channel_packet *pkt, unsigned int lcore_id)
 	return 0;
 }
 
-int rte_power_guest_channel_send_msg(struct channel_packet *pkt,
+int rte_power_guest_channel_send_msg(struct rte_power_channel_packet *pkt,
 			unsigned int lcore_id)
 {
 	return guest_channel_send_msg(pkt, lcore_id);
diff --git a/dpdk/lib/librte_power/guest_channel.h b/dpdk/lib/librte_power/guest_channel.h
index 025961606c..b790f3661a 100644
--- a/dpdk/lib/librte_power/guest_channel.h
+++ b/dpdk/lib/librte_power/guest_channel.h
@@ -8,8 +8,6 @@
 extern "C" {
 #endif
 
-#include <channel_commands.h>
-
 /**
  * Connect to the Virtio-Serial VM end-point located in path. It is
  * thread safe for unique lcore_ids. This function must be only called once from
@@ -51,31 +49,16 @@ void guest_channel_host_disconnect(unsigned int lcore_id);
  *  - Negative on channel not connected.
  *  - errno on write to channel error.
  */
-int guest_channel_send_msg(struct channel_packet *pkt, unsigned int lcore_id);
-
-/**
- * Send a message contained in pkt over the Virtio-Serial to the host endpoint.
- *
- * @param pkt
- *  Pointer to a populated struct channel_packet
- *
- * @param lcore_id
- *  lcore_id.
- *
- * @return
- *  - 0 on success.
- *  - Negative on error.
- */
-int rte_power_guest_channel_send_msg(struct channel_packet *pkt,
-			unsigned int lcore_id);
+int guest_channel_send_msg(struct rte_power_channel_packet *pkt,
+		unsigned int lcore_id);
 
 /**
  * Read a message contained in pkt over the Virtio-Serial
  * from the host endpoint.
  *
  * @param pkt
- *  Pointer to channel_packet or
- *  channel_packet_freq_list struct.
+ *  Pointer to rte_power_channel_packet or
+ *  rte_power_channel_packet_freq_list struct.
  *
  * @param pkt_len
  *  Size of expected data packet.
@@ -91,30 +74,6 @@ int power_guest_channel_read_msg(void *pkt,
 		size_t pkt_len,
 		unsigned int lcore_id);
 
-/**
- * Receive a message contained in pkt over the Virtio-Serial
- * from the host endpoint.
- *
- * @param pkt
- *  Pointer to channel_packet or
- *  channel_packet_freq_list struct.
- *
- * @param pkt_len
- *  Size of expected data packet.
- *
- * @param lcore_id
- *  lcore_id.
- *
- * @return
- *  - 0 on success.
- *  - Negative on error.
- */
-__rte_experimental
-int
-rte_power_guest_channel_receive_msg(void *pkt,
-		size_t pkt_len,
-		unsigned int lcore_id);
-
 
 #ifdef __cplusplus
 }
diff --git a/dpdk/lib/librte_power/meson.build b/dpdk/lib/librte_power/meson.build
index cdf08f6df3..6281adfe17 100644
--- a/dpdk/lib/librte_power/meson.build
+++ b/dpdk/lib/librte_power/meson.build
@@ -9,5 +9,6 @@ sources = files('rte_power.c', 'power_acpi_cpufreq.c',
 		'power_kvm_vm.c', 'guest_channel.c',
 		'rte_power_empty_poll.c',
 		'power_pstate_cpufreq.c')
-headers = files('rte_power.h','rte_power_empty_poll.h')
+headers = files('rte_power.h','rte_power_empty_poll.h',
+	'rte_power_guest_channel.h')
 deps += ['timer']
diff --git a/dpdk/lib/librte_power/power_kvm_vm.c b/dpdk/lib/librte_power/power_kvm_vm.c
index 277ebbeaeb..b34773d9c6 100644
--- a/dpdk/lib/librte_power/power_kvm_vm.c
+++ b/dpdk/lib/librte_power/power_kvm_vm.c
@@ -6,14 +6,14 @@
 
 #include <rte_log.h>
 
+#include "rte_power_guest_channel.h"
 #include "guest_channel.h"
-#include "channel_commands.h"
 #include "power_kvm_vm.h"
 #include "power_common.h"
 
 #define FD_PATH "/dev/virtio-ports/virtio.serial.port.poweragent"
 
-static struct channel_packet pkt[RTE_MAX_LCORE];
+static struct rte_power_channel_packet pkt[RTE_MAX_LCORE];
 
 
 int
@@ -24,7 +24,7 @@ power_kvm_vm_init(unsigned int lcore_id)
 				lcore_id, RTE_MAX_LCORE-1);
 		return -1;
 	}
-	pkt[lcore_id].command = CPU_POWER;
+	pkt[lcore_id].command = RTE_POWER_CPU_POWER;
 	pkt[lcore_id].resource_id = lcore_id;
 	return guest_channel_host_connect(FD_PATH, lcore_id);
 }
@@ -85,25 +85,25 @@ send_msg(unsigned int lcore_id, uint32_t scale_direction)
 int
 power_kvm_vm_freq_up(unsigned int lcore_id)
 {
-	return send_msg(lcore_id, CPU_POWER_SCALE_UP);
+	return send_msg(lcore_id, RTE_POWER_SCALE_UP);
 }
 
 int
 power_kvm_vm_freq_down(unsigned int lcore_id)
 {
-	return send_msg(lcore_id, CPU_POWER_SCALE_DOWN);
+	return send_msg(lcore_id, RTE_POWER_SCALE_DOWN);
 }
 
 int
 power_kvm_vm_freq_max(unsigned int lcore_id)
 {
-	return send_msg(lcore_id, CPU_POWER_SCALE_MAX);
+	return send_msg(lcore_id, RTE_POWER_SCALE_MAX);
 }
 
 int
 power_kvm_vm_freq_min(unsigned int lcore_id)
 {
-	return send_msg(lcore_id, CPU_POWER_SCALE_MIN);
+	return send_msg(lcore_id, RTE_POWER_SCALE_MIN);
 }
 
 int
@@ -116,13 +116,13 @@ power_kvm_vm_turbo_status(__attribute__((unused)) unsigned int lcore_id)
 int
 power_kvm_vm_enable_turbo(unsigned int lcore_id)
 {
-	return send_msg(lcore_id, CPU_POWER_ENABLE_TURBO);
+	return send_msg(lcore_id, RTE_POWER_ENABLE_TURBO);
 }
 
 int
 power_kvm_vm_disable_turbo(unsigned int lcore_id)
 {
-	return send_msg(lcore_id, CPU_POWER_DISABLE_TURBO);
+	return send_msg(lcore_id, RTE_POWER_DISABLE_TURBO);
 }
 
 struct rte_power_core_capabilities;
diff --git a/dpdk/lib/librte_power/power_pstate_cpufreq.c b/dpdk/lib/librte_power/power_pstate_cpufreq.c
index 2d8a9499dc..fa16b44146 100644
--- a/dpdk/lib/librte_power/power_pstate_cpufreq.c
+++ b/dpdk/lib/librte_power/power_pstate_cpufreq.c
@@ -52,6 +52,9 @@
 		} \
 } while (0)
 
+/* macros used for rounding frequency to nearest 100000 */
+#define FREQ_ROUNDING_DELTA 50000
+#define ROUND_FREQ_TO_N_100000 100000
 
 #define POWER_CONVERT_TO_DECIMAL 10
 #define BUS_FREQ     100000
@@ -531,6 +534,57 @@ power_get_available_freqs(struct pstate_power_info *pi)
 	return ret;
 }
 
+static int
+power_get_cur_idx(struct pstate_power_info *pi)
+{
+	FILE *f_cur;
+	int ret = -1;
+	char *p_cur;
+	char buf_cur[BUFSIZ];
+	char fullpath_cur[PATH_MAX];
+	char *s_cur;
+	uint32_t sys_cur_freq = 0;
+	unsigned int i;
+
+	snprintf(fullpath_cur, sizeof(fullpath_cur),
+			POWER_SYSFILE_CUR_FREQ,
+			pi->lcore_id);
+	f_cur = fopen(fullpath_cur, "r");
+	FOPEN_OR_ERR_RET(f_cur, ret);
+
+	/* initialize the cur_idx to matching current frequency freq index */
+	s_cur = fgets(buf_cur, sizeof(buf_cur), f_cur);
+	FOPS_OR_NULL_GOTO(s_cur, fail);
+
+	p_cur = strchr(buf_cur, '\n');
+	if (p_cur != NULL)
+		*p_cur = 0;
+	sys_cur_freq = strtoul(buf_cur, &p_cur, POWER_CONVERT_TO_DECIMAL);
+
+	/* convert the frequency to nearest 100000 value
+	 * Ex: if sys_cur_freq=1396789 then freq_conv=1400000
+	 * Ex: if sys_cur_freq=800030 then freq_conv=800000
+	 * Ex: if sys_cur_freq=800030 then freq_conv=800000
+	 */
+	unsigned int freq_conv = 0;
+	freq_conv = (sys_cur_freq + FREQ_ROUNDING_DELTA)
+				/ ROUND_FREQ_TO_N_100000;
+	freq_conv = freq_conv * ROUND_FREQ_TO_N_100000;
+
+	for (i = 0; i < pi->nb_freqs; i++) {
+		if (freq_conv == pi->freqs[i]) {
+			pi->curr_idx = i;
+			break;
+		}
+	}
+
+	fclose(f_cur);
+	return 0;
+fail:
+	fclose(f_cur);
+	return ret;
+}
+
 int
 power_pstate_cpufreq_init(unsigned int lcore_id)
 {
@@ -571,6 +625,11 @@ power_pstate_cpufreq_init(unsigned int lcore_id)
 		goto fail;
 	}
 
+	if (power_get_cur_idx(pi) < 0) {
+		RTE_LOG(ERR, POWER, "Cannot get current frequency "
+				"index of lcore %u\n", lcore_id);
+		goto fail;
+	}
 
 	/* Set freq to max by default */
 	if (power_pstate_cpufreq_freq_max(lcore_id) < 0) {
diff --git a/dpdk/lib/librte_power/rte_power.h b/dpdk/lib/librte_power/rte_power.h
index 427058b811..04dc4cb1da 100644
--- a/dpdk/lib/librte_power/rte_power.h
+++ b/dpdk/lib/librte_power/rte_power.h
@@ -14,6 +14,7 @@
 #include <rte_byteorder.h>
 #include <rte_log.h>
 #include <rte_string_fns.h>
+#include <rte_power_guest_channel.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/dpdk/lib/librte_power/rte_power_guest_channel.h b/dpdk/lib/librte_power/rte_power_guest_channel.h
new file mode 100644
index 0000000000..ed4fbfdcd3
--- /dev/null
+++ b/dpdk/lib/librte_power/rte_power_guest_channel.h
@@ -0,0 +1,176 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2021 Intel Corporation
+ */
+#ifndef RTE_POWER_GUEST_CHANNEL_H
+#define RTE_POWER_GUEST_CHANNEL_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_POWER_MAX_VFS 10
+#define RTE_POWER_VM_MAX_NAME_SZ 32
+#define RTE_POWER_MAX_VCPU_PER_VM 8
+#define RTE_POWER_HOURS_PER_DAY 24
+
+/* Valid Commands */
+#define RTE_POWER_CPU_POWER               1
+#define RTE_POWER_CPU_POWER_CONNECT       2
+#define RTE_POWER_PKT_POLICY              3
+#define RTE_POWER_PKT_POLICY_REMOVE       4
+
+#define RTE_POWER_CORE_TYPE_VIRTUAL 0
+#define RTE_POWER_CORE_TYPE_PHYSICAL 1
+
+/* CPU Power Command Scaling */
+#define RTE_POWER_SCALE_UP      1
+#define RTE_POWER_SCALE_DOWN    2
+#define RTE_POWER_SCALE_MAX     3
+#define RTE_POWER_SCALE_MIN     4
+#define RTE_POWER_ENABLE_TURBO  5
+#define RTE_POWER_DISABLE_TURBO 6
+
+/* CPU Power Queries */
+#define RTE_POWER_QUERY_FREQ_LIST  7
+#define RTE_POWER_QUERY_FREQ       8
+#define RTE_POWER_QUERY_CAPS_LIST  9
+#define RTE_POWER_QUERY_CAPS       10
+
+/* Generic Power Command Response */
+#define RTE_POWER_CMD_ACK       1
+#define RTE_POWER_CMD_NACK      2
+
+/* CPU Power Query Responses */
+#define RTE_POWER_FREQ_LIST     3
+#define RTE_POWER_CAPS_LIST     4
+
+struct rte_power_traffic_policy {
+	uint32_t min_packet_thresh;
+	uint32_t avg_max_packet_thresh;
+	uint32_t max_max_packet_thresh;
+};
+
+struct rte_power_timer_profile {
+	int busy_hours[RTE_POWER_HOURS_PER_DAY];
+	int quiet_hours[RTE_POWER_HOURS_PER_DAY];
+	int hours_to_use_traffic_profile[RTE_POWER_HOURS_PER_DAY];
+};
+
+enum rte_power_workload_level {
+	RTE_POWER_WL_HIGH,
+	RTE_POWER_WL_MEDIUM,
+	RTE_POWER_WL_LOW
+};
+
+enum rte_power_policy {
+	RTE_POWER_POLICY_TRAFFIC,
+	RTE_POWER_POLICY_TIME,
+	RTE_POWER_POLICY_WORKLOAD,
+	RTE_POWER_POLICY_BRANCH_RATIO
+};
+
+struct rte_power_turbo_status {
+	bool tbEnabled;
+};
+
+struct rte_power_channel_packet {
+	uint64_t resource_id; /**< core_num, device */
+	uint32_t unit;        /**< scale down/up/min/max */
+	uint32_t command;     /**< Power, IO, etc */
+	char vm_name[RTE_POWER_VM_MAX_NAME_SZ];
+
+	uint64_t vfid[RTE_POWER_MAX_VFS];
+	int nb_mac_to_monitor;
+	struct rte_power_traffic_policy traffic_policy;
+	uint8_t vcpu_to_control[RTE_POWER_MAX_VCPU_PER_VM];
+	uint8_t num_vcpu;
+	struct rte_power_timer_profile timer_policy;
+	bool core_type;
+	enum rte_power_workload_level workload;
+	enum rte_power_policy policy_to_use;
+	struct rte_power_turbo_status t_boost_status;
+};
+
+struct rte_power_channel_packet_freq_list {
+	uint64_t resource_id; /**< core_num, device */
+	uint32_t unit;        /**< scale down/up/min/max */
+	uint32_t command;     /**< Power, IO, etc */
+	char vm_name[RTE_POWER_VM_MAX_NAME_SZ];
+
+	uint32_t freq_list[RTE_POWER_MAX_VCPU_PER_VM];
+	uint8_t num_vcpu;
+};
+
+struct rte_power_channel_packet_caps_list {
+	uint64_t resource_id; /**< core_num, device */
+	uint32_t unit;        /**< scale down/up/min/max */
+	uint32_t command;     /**< Power, IO, etc */
+	char vm_name[RTE_POWER_VM_MAX_NAME_SZ];
+
+	uint64_t turbo[RTE_POWER_MAX_VCPU_PER_VM];
+	uint64_t priority[RTE_POWER_MAX_VCPU_PER_VM];
+	uint8_t num_vcpu;
+};
+
+/**
+ * @internal
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Send a message contained in pkt over the Virtio-Serial to the host endpoint.
+ *
+ * @param pkt
+ *  Pointer to a populated struct channel_packet.
+ *
+ * @param lcore_id
+ *  Use channel specific to this lcore_id.
+ *
+ * @return
+ *  - 0 on success.
+ *  - Negative on error.
+ */
+__rte_experimental
+int rte_power_guest_channel_send_msg(struct rte_power_channel_packet *pkt,
+			unsigned int lcore_id);
+
+/**
+ * @internal
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Receive a message contained in pkt over the Virtio-Serial
+ * from the host endpoint.
+ *
+ * @param pkt
+ *  Pointer to channel_packet or
+ *  channel_packet_freq_list struct.
+ *
+ * @param pkt_len
+ *  Size of expected data packet.
+ *
+ * @param lcore_id
+ *  Use channel specific to this lcore_id.
+ *
+ * @return
+ *  - 0 on success.
+ *  - Negative on error.
+ */
+__rte_experimental
+int rte_power_guest_channel_receive_msg(void *pkt,
+		size_t pkt_len,
+		unsigned int lcore_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_POWER_GUEST_CHANNEL_H_ */
diff --git a/dpdk/lib/librte_power/rte_power_version.map b/dpdk/lib/librte_power/rte_power_version.map
index 55a168f56e..0fe85377ab 100644
--- a/dpdk/lib/librte_power/rte_power_version.map
+++ b/dpdk/lib/librte_power/rte_power_version.map
@@ -33,4 +33,8 @@ EXPERIMENTAL {
 	rte_power_guest_channel_receive_msg;
 	rte_power_poll_stat_fetch;
 	rte_power_poll_stat_update;
+
+	# added in 21.02
+	rte_power_guest_channel_receive_msg;
+	rte_power_guest_channel_send_msg;
 };
diff --git a/dpdk/lib/librte_rawdev/rte_rawdev.c b/dpdk/lib/librte_rawdev/rte_rawdev.c
index b6f1e1c779..fe289cefdf 100644
--- a/dpdk/lib/librte_rawdev/rte_rawdev.c
+++ b/dpdk/lib/librte_rawdev/rte_rawdev.c
@@ -89,15 +89,15 @@ rte_rawdev_info_get(uint16_t dev_id, struct rte_rawdev_info *dev_info)
 
 	rawdev = &rte_rawdevs[dev_id];
 
-	RTE_FUNC_PTR_OR_ERR_RET(*rawdev->dev_ops->dev_info_get, -ENOTSUP);
-	(*rawdev->dev_ops->dev_info_get)(rawdev, dev_info->dev_private);
-
-	if (dev_info) {
-
-		dev_info->driver_name = rawdev->driver_name;
-		dev_info->device = rawdev->device;
+	if (dev_info->dev_private != NULL) {
+		RTE_FUNC_PTR_OR_ERR_RET(*rawdev->dev_ops->dev_info_get, -ENOTSUP);
+		(*rawdev->dev_ops->dev_info_get)(rawdev, dev_info->dev_private);
 	}
 
+	dev_info->driver_name = rawdev->driver_name;
+	dev_info->device = rawdev->device;
+	dev_info->socket_id = rawdev->socket_id;
+
 	return 0;
 }
 
diff --git a/dpdk/lib/librte_rawdev/rte_rawdev.h b/dpdk/lib/librte_rawdev/rte_rawdev.h
index ed011ca228..32f6b8bb03 100644
--- a/dpdk/lib/librte_rawdev/rte_rawdev.h
+++ b/dpdk/lib/librte_rawdev/rte_rawdev.h
@@ -12,9 +12,6 @@
  *
  * This API allow applications to configure and use generic devices having
  * no specific type already available in DPDK.
- *
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
  */
 
 #ifdef __cplusplus
@@ -77,7 +74,13 @@ struct rte_rawdev_info;
  *
  * @param[out] dev_info
  *   A pointer to a structure of type *rte_rawdev_info* to be filled with the
- *   contextual information of the device.
+ *   contextual information of the device. The dev_info->dev_private field
+ *   should point to an appropriate buffer space for holding the device-
+ *   specific info for that hardware.
+ *   If the dev_private field is set to NULL, then the device-specific info
+ *   function will not be called and only basic information about the device
+ *   will be returned. This can be used to safely query the type of a rawdev
+ *   instance without needing to know the size of the private data to return.
  *
  * @return
  *   - 0: Success, driver updates the contextual information of the raw device
diff --git a/dpdk/lib/librte_rawdev/rte_rawdev_pmd.h b/dpdk/lib/librte_rawdev/rte_rawdev_pmd.h
index cb3555ab50..4395a2182d 100644
--- a/dpdk/lib/librte_rawdev/rte_rawdev_pmd.h
+++ b/dpdk/lib/librte_rawdev/rte_rawdev_pmd.h
@@ -11,9 +11,6 @@
  * @note
  * Driver facing APIs for a raw device. These are not to be called directly by
  * any application.
- *
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
  */
 
 #ifdef __cplusplus
diff --git a/dpdk/lib/librte_rawdev/rte_rawdev_version.map b/dpdk/lib/librte_rawdev/rte_rawdev_version.map
index d847c9e0d3..63b54f598b 100644
--- a/dpdk/lib/librte_rawdev/rte_rawdev_version.map
+++ b/dpdk/lib/librte_rawdev/rte_rawdev_version.map
@@ -5,6 +5,7 @@ DPDK_20.0 {
 	rte_rawdev_configure;
 	rte_rawdev_count;
 	rte_rawdev_dequeue_buffers;
+	rte_rawdev_dump;
 	rte_rawdev_enqueue_buffers;
 	rte_rawdev_firmware_load;
 	rte_rawdev_firmware_status_get;
diff --git a/dpdk/lib/librte_rcu/rte_rcu_qsbr.c b/dpdk/lib/librte_rcu/rte_rcu_qsbr.c
index 2f3fad776e..58d58c5be5 100644
--- a/dpdk/lib/librte_rcu/rte_rcu_qsbr.c
+++ b/dpdk/lib/librte_rcu/rte_rcu_qsbr.c
@@ -242,10 +242,10 @@ rte_rcu_qsbr_dump(FILE *f, struct rte_rcu_qsbr *v)
 
 	fprintf(f, "\n");
 
-	fprintf(f, "  Token = %"PRIu64"\n",
+	fprintf(f, "  Token = %" PRIu64 "\n",
 			__atomic_load_n(&v->token, __ATOMIC_ACQUIRE));
 
-	fprintf(f, "  Least Acknowledged Token = %"PRIu64"\n",
+	fprintf(f, "  Least Acknowledged Token = %" PRIu64 "\n",
 			__atomic_load_n(&v->acked_token, __ATOMIC_ACQUIRE));
 
 	fprintf(f, "Quiescent State Counts for readers:\n");
@@ -255,7 +255,7 @@ rte_rcu_qsbr_dump(FILE *f, struct rte_rcu_qsbr *v)
 		id = i << __RTE_QSBR_THRID_INDEX_SHIFT;
 		while (bmap) {
 			t = __builtin_ctzl(bmap);
-			fprintf(f, "thread ID = %u, count = %"PRIu64", lock count = %u\n",
+			fprintf(f, "thread ID = %u, count = %" PRIu64 ", lock count = %u\n",
 				id + t,
 				__atomic_load_n(
 					&v->qsbr_cnt[id + t].cnt,
diff --git a/dpdk/lib/librte_rcu/rte_rcu_qsbr.h b/dpdk/lib/librte_rcu/rte_rcu_qsbr.h
index 0b5585925f..430cdfb58a 100644
--- a/dpdk/lib/librte_rcu/rte_rcu_qsbr.h
+++ b/dpdk/lib/librte_rcu/rte_rcu_qsbr.h
@@ -7,7 +7,12 @@
 
 /**
  * @file
- * RTE Quiescent State Based Reclamation (QSBR)
+ *
+ * RTE Quiescent State Based Reclamation (QSBR).
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
  *
  * Quiescent State (QS) is any point in the thread execution
  * where the thread does not hold a reference to a data structure
@@ -465,7 +470,7 @@ rte_rcu_qsbr_quiescent(struct rte_rcu_qsbr *v, unsigned int thread_id)
 		__atomic_store_n(&v->qsbr_cnt[thread_id].cnt,
 					 t, __ATOMIC_RELEASE);
 
-	__RTE_RCU_DP_LOG(DEBUG, "%s: update: token = %"PRIu64", Thread ID = %d",
+	__RTE_RCU_DP_LOG(DEBUG, "%s: update: token = %" PRIu64 ", Thread ID = %d",
 		__func__, t, thread_id);
 }
 
@@ -493,13 +498,13 @@ __rte_rcu_qsbr_check_selective(struct rte_rcu_qsbr *v, uint64_t t, bool wait)
 		while (bmap) {
 			j = __builtin_ctzl(bmap);
 			__RTE_RCU_DP_LOG(DEBUG,
-				"%s: check: token = %"PRIu64", wait = %d, Bit Map = 0x%"PRIx64", Thread ID = %d",
+				"%s: check: token = %" PRIu64 ", wait = %d, Bit Map = 0x%" PRIx64 ", Thread ID = %d",
 				__func__, t, wait, bmap, id + j);
 			c = __atomic_load_n(
 					&v->qsbr_cnt[id + j].cnt,
 					__ATOMIC_ACQUIRE);
 			__RTE_RCU_DP_LOG(DEBUG,
-				"%s: status: token = %"PRIu64", wait = %d, Thread QS cnt = %"PRIu64", Thread ID = %d",
+				"%s: status: token = %" PRIu64 ", wait = %d, Thread QS cnt = %" PRIu64 ", Thread ID = %d",
 				__func__, t, wait, c, id+j);
 
 			/* Counter is not checked for wrap-around condition
@@ -556,12 +561,12 @@ __rte_rcu_qsbr_check_all(struct rte_rcu_qsbr *v, uint64_t t, bool wait)
 
 	for (i = 0, cnt = v->qsbr_cnt; i < v->max_threads; i++, cnt++) {
 		__RTE_RCU_DP_LOG(DEBUG,
-			"%s: check: token = %"PRIu64", wait = %d, Thread ID = %d",
+			"%s: check: token = %" PRIu64 ", wait = %d, Thread ID = %d",
 			__func__, t, wait, i);
 		while (1) {
 			c = __atomic_load_n(&cnt->cnt, __ATOMIC_ACQUIRE);
 			__RTE_RCU_DP_LOG(DEBUG,
-				"%s: status: token = %"PRIu64", wait = %d, Thread QS cnt = %"PRIu64", Thread ID = %d",
+				"%s: status: token = %" PRIu64 ", wait = %d, Thread QS cnt = %" PRIu64 ", Thread ID = %d",
 				__func__, t, wait, c, i);
 
 			/* Counter is not checked for wrap-around condition
diff --git a/dpdk/lib/librte_rib/rte_rib.c b/dpdk/lib/librte_rib/rte_rib.c
index 55d612dc2e..07b3c068ed 100644
--- a/dpdk/lib/librte_rib/rte_rib.c
+++ b/dpdk/lib/librte_rib/rte_rib.c
@@ -301,7 +301,7 @@ rte_rib_insert(struct rte_rib *rib, uint32_t ip, uint8_t depth)
 	/* closest node found, new_node should be inserted in the middle */
 	common_depth = RTE_MIN(depth, (*tmp)->depth);
 	common_prefix = ip ^ (*tmp)->ip;
-	d = __builtin_clz(common_prefix);
+	d = (common_prefix == 0) ? 32 : __builtin_clz(common_prefix);
 
 	common_depth = RTE_MIN(d, common_depth);
 	common_prefix = ip & rte_rib_depth_to_mask(common_depth);
diff --git a/dpdk/lib/librte_rib/rte_rib.h b/dpdk/lib/librte_rib/rte_rib.h
index 6b70de980a..93cd93b4ae 100644
--- a/dpdk/lib/librte_rib/rte_rib.h
+++ b/dpdk/lib/librte_rib/rte_rib.h
@@ -8,11 +8,25 @@
 
 /**
  * @file
+ *
+ * RTE RIB library.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
  * Level compressed tree implementation for IPv4 Longest Prefix Match
  */
 
+#include <stdlib.h>
+#include <stdint.h>
+
 #include <rte_compat.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * rte_rib_get_nxt() flags
  */
@@ -274,4 +288,8 @@ __rte_experimental
 void
 rte_rib_free(struct rte_rib *rib);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _RTE_RIB_H_ */
diff --git a/dpdk/lib/librte_rib/rte_rib6.h b/dpdk/lib/librte_rib/rte_rib6.h
index 871457138d..b80665bf44 100644
--- a/dpdk/lib/librte_rib/rte_rib6.h
+++ b/dpdk/lib/librte_rib/rte_rib6.h
@@ -8,11 +8,23 @@
 
 /**
  * @file
+ *
+ * RTE rib6 library.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
+ *
  * Level compressed tree implementation for IPv6 Longest Prefix Match
  */
 
 #include <rte_memcpy.h>
 #include <rte_compat.h>
+#include <rte_common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #define RTE_RIB6_IPV6_ADDR_SIZE	16
 
@@ -331,4 +343,8 @@ __rte_experimental
 void
 rte_rib6_free(struct rte_rib6 *rib);
 
-#endif /* _RTE_RIB_H_ */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_RIB6_H_ */
diff --git a/dpdk/lib/librte_sched/rte_sched.c b/dpdk/lib/librte_sched/rte_sched.c
index c0983ddda4..0fa0741664 100644
--- a/dpdk/lib/librte_sched/rte_sched.c
+++ b/dpdk/lib/librte_sched/rte_sched.c
@@ -222,6 +222,7 @@ struct rte_sched_port {
 	uint64_t time_cpu_bytes;      /* Current CPU time measured in bytes */
 	uint64_t time;                /* Current NIC TX time measured in bytes */
 	struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */
+	uint64_t cycles_per_byte;
 
 	/* Grinders */
 	struct rte_mbuf **pkts_out;
@@ -304,7 +305,7 @@ rte_sched_port_tc_queue(struct rte_sched_port *port, uint32_t qindex)
 
 static int
 pipe_profile_check(struct rte_sched_pipe_params *params,
-	uint32_t rate, uint16_t *qsize)
+	uint64_t rate, uint16_t *qsize)
 {
 	uint32_t i;
 
@@ -624,7 +625,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_subport *subport,
 
 static void
 rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport,
-	struct rte_sched_subport_params *params, uint32_t rate)
+	struct rte_sched_subport_params *params, uint64_t rate)
 {
 	uint32_t i;
 
@@ -852,6 +853,7 @@ rte_sched_port_config(struct rte_sched_port_params *params)
 	cycles_per_byte = (rte_get_tsc_hz() << RTE_SCHED_TIME_SHIFT)
 		/ params->rate;
 	port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte);
+	port->cycles_per_byte = cycles_per_byte;
 
 	/* Grinders */
 	port->pkts_out = NULL;
@@ -888,7 +890,7 @@ rte_sched_subport_free(struct rte_sched_port *port,
 		}
 	}
 
-	rte_bitmap_free(subport->bmp);
+	rte_free(subport);
 }
 
 void
@@ -2673,16 +2675,21 @@ static inline void
 rte_sched_port_time_resync(struct rte_sched_port *port)
 {
 	uint64_t cycles = rte_get_tsc_cycles();
-	uint64_t cycles_diff = cycles - port->time_cpu_cycles;
+	uint64_t cycles_diff;
 	uint64_t bytes_diff;
 	uint32_t i;
 
+	if (cycles < port->time_cpu_cycles)
+		port->time_cpu_cycles = 0;
+
+	cycles_diff = cycles - port->time_cpu_cycles;
 	/* Compute elapsed time in bytes */
 	bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT,
 					   port->inv_cycles_per_byte);
 
 	/* Advance port time */
-	port->time_cpu_cycles = cycles;
+	port->time_cpu_cycles +=
+		(bytes_diff * port->cycles_per_byte) >> RTE_SCHED_TIME_SHIFT;
 	port->time_cpu_bytes += bytes_diff;
 	if (port->time < port->time_cpu_bytes)
 		port->time = port->time_cpu_bytes;
diff --git a/dpdk/lib/librte_security/rte_security.c b/dpdk/lib/librte_security/rte_security.c
index bc81ce15d1..dc9a3e89cd 100644
--- a/dpdk/lib/librte_security/rte_security.c
+++ b/dpdk/lib/librte_security/rte_security.c
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2017 NXP.
  * Copyright(c) 2017 Intel Corporation.
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
  */
 
 #include <rte_malloc.h>
@@ -9,6 +10,19 @@
 #include "rte_security.h"
 #include "rte_security_driver.h"
 
+/* Macro to check for invalid pointers */
+#define RTE_PTR_OR_ERR_RET(ptr, retval) do {	\
+	if ((ptr) == NULL)			\
+		return retval;			\
+} while (0)
+
+/* Macro to check for invalid pointers chains */
+#define RTE_PTR_CHAIN3_OR_ERR_RET(p1, p2, p3, retval, last_retval) do {	\
+	RTE_PTR_OR_ERR_RET(p1, retval);					\
+	RTE_PTR_OR_ERR_RET(p1->p2, retval);				\
+	RTE_PTR_OR_ERR_RET(p1->p2->p3, last_retval);			\
+} while (0)
+
 struct rte_security_session *
 rte_security_session_create(struct rte_security_ctx *instance,
 			    struct rte_security_session_conf *conf,
@@ -16,10 +30,9 @@ rte_security_session_create(struct rte_security_ctx *instance,
 {
 	struct rte_security_session *sess = NULL;
 
-	if (conf == NULL)
-		return NULL;
-
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->session_create, NULL);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_create, NULL, NULL);
+	RTE_PTR_OR_ERR_RET(conf, NULL);
+	RTE_PTR_OR_ERR_RET(mp, NULL);
 
 	if (rte_mempool_get(mp, (void **)&sess))
 		return NULL;
@@ -38,14 +51,19 @@ rte_security_session_update(struct rte_security_ctx *instance,
 			    struct rte_security_session *sess,
 			    struct rte_security_session_conf *conf)
 {
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->session_update, -ENOTSUP);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_update, -EINVAL,
+			-ENOTSUP);
+	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
+	RTE_PTR_OR_ERR_RET(conf, -EINVAL);
+
 	return instance->ops->session_update(instance->device, sess, conf);
 }
 
 unsigned int
 rte_security_session_get_size(struct rte_security_ctx *instance)
 {
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->session_get_size, 0);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_get_size, 0, 0);
+
 	return instance->ops->session_get_size(instance->device);
 }
 
@@ -54,7 +72,11 @@ rte_security_session_stats_get(struct rte_security_ctx *instance,
 			       struct rte_security_session *sess,
 			       struct rte_security_stats *stats)
 {
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->session_stats_get, -ENOTSUP);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_stats_get, -EINVAL,
+			-ENOTSUP);
+	/* Parameter sess can be NULL in case of getting global statistics. */
+	RTE_PTR_OR_ERR_RET(stats, -EINVAL);
+
 	return instance->ops->session_stats_get(instance->device, sess, stats);
 }
 
@@ -64,16 +86,20 @@ rte_security_session_destroy(struct rte_security_ctx *instance,
 {
 	int ret;
 
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->session_destroy, -ENOTSUP);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, session_destroy, -EINVAL,
+			-ENOTSUP);
+	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
+
+	ret = instance->ops->session_destroy(instance->device, sess);
+	if (ret != 0)
+		return ret;
+
+	rte_mempool_put(rte_mempool_from_obj(sess), (void *)sess);
 
 	if (instance->sess_cnt)
 		instance->sess_cnt--;
 
-	ret = instance->ops->session_destroy(instance->device, sess);
-	if (!ret)
-		rte_mempool_put(rte_mempool_from_obj(sess), (void *)sess);
-
-	return ret;
+	return 0;
 }
 
 int
@@ -81,6 +107,11 @@ rte_security_set_pkt_metadata(struct rte_security_ctx *instance,
 			      struct rte_security_session *sess,
 			      struct rte_mbuf *m, void *params)
 {
+#ifdef RTE_DEBUG
+	RTE_PTR_OR_ERR_RET(sess, -EINVAL);
+	RTE_PTR_OR_ERR_RET(instance, -EINVAL);
+	RTE_PTR_OR_ERR_RET(instance->ops, -EINVAL);
+#endif
 	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->set_pkt_metadata, -ENOTSUP);
 	return instance->ops->set_pkt_metadata(instance->device,
 					       sess, m, params);
@@ -91,6 +122,10 @@ rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md)
 {
 	void *userdata = NULL;
 
+#ifdef RTE_DEBUG
+	RTE_PTR_OR_ERR_RET(instance, NULL);
+	RTE_PTR_OR_ERR_RET(instance->ops, NULL);
+#endif
 	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->get_userdata, NULL);
 	if (instance->ops->get_userdata(instance->device, md, &userdata))
 		return NULL;
@@ -101,7 +136,8 @@ rte_security_get_userdata(struct rte_security_ctx *instance, uint64_t md)
 const struct rte_security_capability *
 rte_security_capabilities_get(struct rte_security_ctx *instance)
 {
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->capabilities_get, NULL);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL);
+
 	return instance->ops->capabilities_get(instance->device);
 }
 
@@ -113,7 +149,9 @@ rte_security_capability_get(struct rte_security_ctx *instance,
 	const struct rte_security_capability *capability;
 	uint16_t i = 0;
 
-	RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->capabilities_get, NULL);
+	RTE_PTR_CHAIN3_OR_ERR_RET(instance, ops, capabilities_get, NULL, NULL);
+	RTE_PTR_OR_ERR_RET(idx, NULL);
+
 	capabilities = instance->ops->capabilities_get(instance->device);
 
 	if (capabilities == NULL)
@@ -121,7 +159,7 @@ rte_security_capability_get(struct rte_security_ctx *instance,
 
 	while ((capability = &capabilities[i++])->action
 			!= RTE_SECURITY_ACTION_TYPE_NONE) {
-		if (capability->action  == idx->action &&
+		if (capability->action == idx->action &&
 				capability->protocol == idx->protocol) {
 			if (idx->protocol == RTE_SECURITY_PROTOCOL_IPSEC) {
 				if (capability->ipsec.proto ==
diff --git a/dpdk/lib/librte_security/rte_security.h b/dpdk/lib/librte_security/rte_security.h
index 546779df2b..b4b4eb2d85 100644
--- a/dpdk/lib/librte_security/rte_security.h
+++ b/dpdk/lib/librte_security/rte_security.h
@@ -374,7 +374,7 @@ rte_security_session_create(struct rte_security_ctx *instance,
  * @param   conf	update configuration parameters
  * @return
  *  - On success returns 0
- *  - On failure return errno
+ *  - On failure returns a negative errno value.
  */
 __rte_experimental
 int
@@ -399,12 +399,14 @@ rte_security_session_get_size(struct rte_security_ctx *instance);
  * return it to its original mempool.
  *
  * @param   instance	security instance
- * @param   sess	security session to freed
+ * @param   sess	security session to be freed
  *
  * @return
  *  - 0 if successful.
- *  - -EINVAL if session is NULL.
+ *  - -EINVAL if session or context instance is NULL.
  *  - -EBUSY if not all device private data has been freed.
+ *  - -ENOTSUP if destroying private data is not supported.
+ *  - other negative values in case of freeing private data errors.
  */
 int
 rte_security_session_destroy(struct rte_security_ctx *instance,
diff --git a/dpdk/lib/librte_stack/rte_stack.h b/dpdk/lib/librte_stack/rte_stack.h
index 27ddb199e5..abf6420766 100644
--- a/dpdk/lib/librte_stack/rte_stack.h
+++ b/dpdk/lib/librte_stack/rte_stack.h
@@ -4,9 +4,12 @@
 
 /**
  * @file rte_stack.h
- * @b EXPERIMENTAL: this API may change without prior notice
  *
- * RTE Stack
+ * RTE Stack.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
  *
  * librte_stack provides an API for configuration and use of a bounded stack of
  * pointers. Push and pop operations are MT-safe, allowing concurrent access,
diff --git a/dpdk/lib/librte_stack/rte_stack_lf_c11.h b/dpdk/lib/librte_stack/rte_stack_lf_c11.h
index 999359f081..94129c3e8a 100644
--- a/dpdk/lib/librte_stack/rte_stack_lf_c11.h
+++ b/dpdk/lib/librte_stack/rte_stack_lf_c11.h
@@ -139,8 +139,10 @@ __rte_stack_lf_pop_elems(struct rte_stack_lf_list *list,
 		/* If NULL was encountered, the list was modified while
 		 * traversing it. Retry.
 		 */
-		if (i != num)
+		if (i != num) {
+			old_head = list->head;
 			continue;
+		}
 
 		new_head.top = tmp;
 		new_head.cnt = old_head.cnt + 1;
diff --git a/dpdk/lib/librte_stack/rte_stack_lf_generic.h b/dpdk/lib/librte_stack/rte_stack_lf_generic.h
index 3abbb53428..4850a05ee7 100644
--- a/dpdk/lib/librte_stack/rte_stack_lf_generic.h
+++ b/dpdk/lib/librte_stack/rte_stack_lf_generic.h
@@ -78,7 +78,7 @@ __rte_stack_lf_pop_elems(struct rte_stack_lf_list *list,
 			 struct rte_stack_lf_elem **last)
 {
 	struct rte_stack_lf_head old_head;
-	int success;
+	int success = 0;
 
 	/* Reserve num elements, if available */
 	while (1) {
diff --git a/dpdk/lib/librte_table/rte_table_hash_key16.c b/dpdk/lib/librte_table/rte_table_hash_key16.c
index 2cca1c924a..c4384b114d 100644
--- a/dpdk/lib/librte_table/rte_table_hash_key16.c
+++ b/dpdk/lib/librte_table/rte_table_hash_key16.c
@@ -33,6 +33,7 @@
 
 #endif
 
+#ifdef RTE_ARCH_64
 struct rte_bucket_4_16 {
 	/* Cache line 0 */
 	uint64_t signature[4 + 1];
@@ -46,6 +47,22 @@ struct rte_bucket_4_16 {
 	/* Cache line 2 */
 	uint8_t data[0];
 };
+#else
+struct rte_bucket_4_16 {
+	/* Cache line 0 */
+	uint64_t signature[4 + 1];
+	uint64_t lru_list;
+	struct rte_bucket_4_16 *next;
+	uint32_t pad;
+	uint64_t next_valid;
+
+	/* Cache line 1 */
+	uint64_t key[4][2];
+
+	/* Cache line 2 */
+	uint8_t data[0];
+};
+#endif
 
 struct rte_table_hash {
 	struct rte_table_stats stats;
diff --git a/dpdk/lib/librte_table/rte_table_hash_key32.c b/dpdk/lib/librte_table/rte_table_hash_key32.c
index a137c50284..3e0031fe1e 100644
--- a/dpdk/lib/librte_table/rte_table_hash_key32.c
+++ b/dpdk/lib/librte_table/rte_table_hash_key32.c
@@ -33,6 +33,7 @@
 
 #endif
 
+#ifdef RTE_ARCH_64
 struct rte_bucket_4_32 {
 	/* Cache line 0 */
 	uint64_t signature[4 + 1];
@@ -46,6 +47,22 @@ struct rte_bucket_4_32 {
 	/* Cache line 3 */
 	uint8_t data[0];
 };
+#else
+struct rte_bucket_4_32 {
+	/* Cache line 0 */
+	uint64_t signature[4 + 1];
+	uint64_t lru_list;
+	struct rte_bucket_4_32 *next;
+	uint32_t pad;
+	uint64_t next_valid;
+
+	/* Cache lines 1 and 2 */
+	uint64_t key[4][4];
+
+	/* Cache line 3 */
+	uint8_t data[0];
+};
+#endif
 
 struct rte_table_hash {
 	struct rte_table_stats stats;
diff --git a/dpdk/lib/librte_table/rte_table_hash_key8.c b/dpdk/lib/librte_table/rte_table_hash_key8.c
index 1811ad8d05..34e3ed1af9 100644
--- a/dpdk/lib/librte_table/rte_table_hash_key8.c
+++ b/dpdk/lib/librte_table/rte_table_hash_key8.c
@@ -31,6 +31,7 @@
 
 #endif
 
+#ifdef RTE_ARCH_64
 struct rte_bucket_4_8 {
 	/* Cache line 0 */
 	uint64_t signature;
@@ -43,6 +44,21 @@ struct rte_bucket_4_8 {
 	/* Cache line 1 */
 	uint8_t data[0];
 };
+#else
+struct rte_bucket_4_8 {
+	/* Cache line 0 */
+	uint64_t signature;
+	uint64_t lru_list;
+	struct rte_bucket_4_8 *next;
+	uint32_t pad;
+	uint64_t next_valid;
+
+	uint64_t key[4];
+
+	/* Cache line 1 */
+	uint8_t data[0];
+};
+#endif
 
 struct rte_table_hash {
 	struct rte_table_stats stats;
diff --git a/dpdk/lib/librte_telemetry/meson.build b/dpdk/lib/librte_telemetry/meson.build
index 26a331140b..f65f1f4acf 100644
--- a/dpdk/lib/librte_telemetry/meson.build
+++ b/dpdk/lib/librte_telemetry/meson.build
@@ -6,7 +6,7 @@ headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_pa
 deps += ['metrics', 'ethdev']
 cflags += '-DALLOW_EXPERIMENTAL_API'
 
-jansson = dependency('jansson', required: false)
+jansson = dependency('jansson', required: false, method: 'pkg-config')
 if jansson.found()
 	ext_deps += jansson
 	dpdk_app_link_libraries += ['telemetry']
diff --git a/dpdk/lib/librte_telemetry/rte_telemetry.h b/dpdk/lib/librte_telemetry/rte_telemetry.h
index aedb318598..f1376ea35f 100644
--- a/dpdk/lib/librte_telemetry/rte_telemetry.h
+++ b/dpdk/lib/librte_telemetry/rte_telemetry.h
@@ -9,7 +9,12 @@
 
 /**
  * @file
- * RTE Telemetry
+ *
+ * RTE Telemetry.
+ *
+ * @warning
+ * @b EXPERIMENTAL:
+ * All functions in this file may be changed or removed without prior notice.
  *
  * The telemetry library provides a method to retrieve statistics from
  * DPDK by sending a JSON encoded message over a socket. DPDK will send
diff --git a/dpdk/lib/librte_telemetry/rte_telemetry_parser.c b/dpdk/lib/librte_telemetry/rte_telemetry_parser.c
index 9601323970..e8c269e85e 100644
--- a/dpdk/lib/librte_telemetry/rte_telemetry_parser.c
+++ b/dpdk/lib/librte_telemetry/rte_telemetry_parser.c
@@ -456,9 +456,9 @@ rte_telemetry_command_ports_stats_values_by_name(struct telemetry_impl
 	size_t index;
 	json_t *value;
 
+	memset(&ep, 0, sizeof(ep));
 	ep.pp.num_port_ids = json_array_size(port_ids_json);
 	ep.pp.num_metric_ids = num_stat_names;
-	memset(&ep, 0, sizeof(ep));
 	if (telemetry == NULL) {
 		TELEMETRY_LOG_ERR("Invalid telemetry argument");
 		return -1;
diff --git a/dpdk/lib/librte_timer/meson.build b/dpdk/lib/librte_timer/meson.build
index b7edfe2e7d..d3b828ce9d 100644
--- a/dpdk/lib/librte_timer/meson.build
+++ b/dpdk/lib/librte_timer/meson.build
@@ -4,4 +4,3 @@
 sources = files('rte_timer.c')
 headers = files('rte_timer.h')
 allow_experimental_apis = true
-use_function_versioning = true
diff --git a/dpdk/lib/librte_timer/rte_timer.c b/dpdk/lib/librte_timer/rte_timer.c
index ca88454ff6..99862a3ba1 100644
--- a/dpdk/lib/librte_timer/rte_timer.c
+++ b/dpdk/lib/librte_timer/rte_timer.c
@@ -26,7 +26,6 @@
 #include <rte_memzone.h>
 #include <rte_malloc.h>
 #include <rte_errno.h>
-#include <rte_function_versioning.h>
 
 #include "rte_timer.h"
 
@@ -146,11 +145,13 @@ rte_timer_subsystem_init(void)
 	const size_t mem_size = data_arr_size + sizeof(*rte_timer_mz_refcnt);
 	bool do_full_init = true;
 
-	if (rte_timer_subsystem_initialized)
-		return -EALREADY;
-
 	rte_mcfg_timer_lock();
 
+	if (rte_timer_subsystem_initialized) {
+		rte_mcfg_timer_unlock();
+		return -EALREADY;
+	}
+
 	mz = rte_memzone_lookup(mz_name);
 	if (mz == NULL) {
 		mz = rte_memzone_reserve_aligned(mz_name, mem_size,
@@ -184,27 +185,29 @@ rte_timer_subsystem_init(void)
 	rte_timer_data_arr[default_data_id].internal_flags |= FL_ALLOCATED;
 	(*rte_timer_mz_refcnt)++;
 
-	rte_mcfg_timer_unlock();
-
 	rte_timer_subsystem_initialized = 1;
 
+	rte_mcfg_timer_unlock();
+
 	return 0;
 }
 
 void
 rte_timer_subsystem_finalize(void)
 {
-	if (!rte_timer_subsystem_initialized)
-		return;
-
 	rte_mcfg_timer_lock();
 
+	if (!rte_timer_subsystem_initialized) {
+		rte_mcfg_timer_unlock();
+		return;
+	}
+
 	if (--(*rte_timer_mz_refcnt) == 0)
 		rte_memzone_free(rte_timer_data_mz);
 
-	rte_mcfg_timer_unlock();
-
 	rte_timer_subsystem_initialized = 0;
+
+	rte_mcfg_timer_unlock();
 }
 
 /* Initialize the timer handle tim for use */
diff --git a/dpdk/lib/librte_timer/rte_timer.h b/dpdk/lib/librte_timer/rte_timer.h
index 9dc5fc3092..88cc267686 100644
--- a/dpdk/lib/librte_timer/rte_timer.h
+++ b/dpdk/lib/librte_timer/rte_timer.h
@@ -274,6 +274,12 @@ int rte_timer_reset(struct rte_timer *tim, uint64_t ticks,
  *   The callback function of the timer.
  * @param arg
  *   The user argument of the callback function.
+ *
+ * @note
+ *   This API should not be called inside a timer's callback function to
+ *   reset another timer; doing so could hang in certain scenarios. Instead,
+ *   the rte_timer_reset() API can be called directly and its return code
+ *   can be checked for success or failure.
  */
 void
 rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks,
@@ -313,6 +319,12 @@ int rte_timer_stop(struct rte_timer *tim);
  *
  * @param tim
  *   The timer handle.
+ *
+ * @note
+ *   This API should not be called inside a timer's callback function to
+ *   stop another timer; doing so could hang in certain scenarios. Instead, the
+ *   rte_timer_stop() API can be called directly and its return code can
+ *   be checked for success or failure.
  */
 void rte_timer_stop_sync(struct rte_timer *tim);
 
diff --git a/dpdk/lib/librte_vhost/iotlb.c b/dpdk/lib/librte_vhost/iotlb.c
index 4a1d8c1253..2e90a63bb1 100644
--- a/dpdk/lib/librte_vhost/iotlb.c
+++ b/dpdk/lib/librte_vhost/iotlb.c
@@ -308,8 +308,9 @@ vhost_user_iotlb_init(struct virtio_net *dev, int vq_index)
 	TAILQ_INIT(&vq->iotlb_list);
 	TAILQ_INIT(&vq->iotlb_pending_list);
 
-	snprintf(pool_name, sizeof(pool_name), "iotlb_cache_%d_%d",
-			dev->vid, vq_index);
+	snprintf(pool_name, sizeof(pool_name), "iotlb_%u_%d_%d",
+			getpid(), dev->vid, vq_index);
+	RTE_LOG(DEBUG, VHOST_CONFIG, "IOTLB cache name: %s\n", pool_name);
 
 	/* If already created, free it and recreate */
 	vq->iotlb_pool = rte_mempool_lookup(pool_name);
@@ -320,8 +321,7 @@ vhost_user_iotlb_init(struct virtio_net *dev, int vq_index)
 			IOTLB_CACHE_SIZE, sizeof(struct vhost_iotlb_entry), 0,
 			0, 0, NULL, NULL, NULL, socket,
 			MEMPOOL_F_NO_CACHE_ALIGN |
-			MEMPOOL_F_SP_PUT |
-			MEMPOOL_F_SC_GET);
+			MEMPOOL_F_SP_PUT);
 	if (!vq->iotlb_pool) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 				"Failed to create IOTLB cache pool (%s)\n",
diff --git a/dpdk/lib/librte_vhost/rte_vhost.h b/dpdk/lib/librte_vhost/rte_vhost.h
index 7b5dc87c2e..53a30a0623 100644
--- a/dpdk/lib/librte_vhost/rte_vhost.h
+++ b/dpdk/lib/librte_vhost/rte_vhost.h
@@ -35,6 +35,23 @@ extern "C" {
 /* support only linear buffers (no chained mbufs) */
 #define RTE_VHOST_USER_LINEARBUF_SUPPORT	(1ULL << 6)
 
+/* Features. */
+#ifndef VIRTIO_NET_F_GUEST_ANNOUNCE
+ #define VIRTIO_NET_F_GUEST_ANNOUNCE 21
+#endif
+
+#ifndef VIRTIO_NET_F_MQ
+ #define VIRTIO_NET_F_MQ		22
+#endif
+
+#ifndef VIRTIO_NET_F_MTU
+ #define VIRTIO_NET_F_MTU 3
+#endif
+
+#ifndef VIRTIO_F_ANY_LAYOUT
+ #define VIRTIO_F_ANY_LAYOUT		27
+#endif
+
 /** Protocol features. */
 #ifndef VHOST_USER_PROTOCOL_F_MQ
 #define VHOST_USER_PROTOCOL_F_MQ	0
@@ -68,6 +85,10 @@ extern "C" {
 #define VHOST_USER_PROTOCOL_F_PAGEFAULT 8
 #endif
 
+#ifndef VHOST_USER_PROTOCOL_F_CONFIG
+#define VHOST_USER_PROTOCOL_F_CONFIG 9
+#endif
+
 #ifndef VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD
 #define VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD 10
 #endif
@@ -85,6 +106,7 @@ extern "C" {
 #define VHOST_USER_F_PROTOCOL_FEATURES	30
 #endif
 
+
 /**
  * Information relating to memory regions including offsets to
  * addresses in QEMUs memory file.
@@ -253,7 +275,7 @@ struct vhost_device_ops {
 
 	/**
 	 * This callback gets called each time a guest gets notified
-	 * about waiting packets. This is the interrupt handling trough
+	 * about waiting packets. This is the interrupt handling through
 	 * the eventfd_write(callfd), which can be used for counting these
 	 * "slow" syscalls.
 	 */
diff --git a/dpdk/lib/librte_vhost/rte_vhost_crypto.h b/dpdk/lib/librte_vhost/rte_vhost_crypto.h
index d29871c7ea..b54d61db69 100644
--- a/dpdk/lib/librte_vhost/rte_vhost_crypto.h
+++ b/dpdk/lib/librte_vhost/rte_vhost_crypto.h
@@ -7,9 +7,12 @@
 
 #define VHOST_CRYPTO_MBUF_POOL_SIZE		(8192)
 #define VHOST_CRYPTO_MAX_BURST_SIZE		(64)
+#define VHOST_CRYPTO_MAX_DATA_SIZE		(4096)
 #define VHOST_CRYPTO_SESSION_MAP_ENTRIES	(1024) /**< Max nb sessions */
 /** max nb virtual queues in a burst for finalizing*/
 #define VIRTIO_CRYPTO_MAX_NUM_BURST_VQS		(64)
+#define VHOST_CRYPTO_MAX_IV_LEN			(32)
+#define VHOST_CRYPTO_MAX_N_DESC			(32)
 
 enum rte_vhost_crypto_zero_copy {
 	RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE = 0,
diff --git a/dpdk/lib/librte_vhost/socket.c b/dpdk/lib/librte_vhost/socket.c
index ebb2ff6c28..dc3ee1e99d 100644
--- a/dpdk/lib/librte_vhost/socket.c
+++ b/dpdk/lib/librte_vhost/socket.c
@@ -127,7 +127,8 @@ read_fd_message(int sockfd, char *buf, int buflen, int *fds, int max_fds,
 
 	ret = recvmsg(sockfd, &msgh, 0);
 	if (ret <= 0) {
-		RTE_LOG(ERR, VHOST_CONFIG, "recvmsg failed\n");
+		if (ret)
+			RTE_LOG(ERR, VHOST_CONFIG, "recvmsg failed\n");
 		return ret;
 	}
 
@@ -318,16 +319,16 @@ vhost_user_read_cb(int connfd, void *dat, int *remove)
 
 		vhost_destroy_device(conn->vid);
 
+		if (vsocket->reconnect) {
+			create_unix_socket(vsocket);
+			vhost_user_start_client(vsocket);
+		}
+
 		pthread_mutex_lock(&vsocket->conn_mutex);
 		TAILQ_REMOVE(&vsocket->conn_list, conn, next);
 		pthread_mutex_unlock(&vsocket->conn_mutex);
 
 		free(conn);
-
-		if (vsocket->reconnect) {
-			create_unix_socket(vsocket);
-			vhost_user_start_client(vsocket);
-		}
 	}
 }
 
@@ -877,6 +878,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 			"error: failed to init connection mutex\n");
 		goto out_free;
 	}
+	vsocket->vdpa_dev_id = -1;
 	vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
 	vsocket->extbuf = flags & RTE_VHOST_USER_EXTBUF_SUPPORT;
 	vsocket->linearbuf = flags & RTE_VHOST_USER_LINEARBUF_SUPPORT;
@@ -924,6 +926,10 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
 			ret = -1;
 			goto out_mutex;
 		}
+		if ((flags & RTE_VHOST_USER_CLIENT) != 0)
+			RTE_LOG(WARNING, VHOST_CONFIG,
+			"zero copy may be incompatible with vhost client mode\n");
+
 		vsocket->supported_features &= ~(1ULL << VIRTIO_F_IN_ORDER);
 		vsocket->features &= ~(1ULL << VIRTIO_F_IN_ORDER);
 
@@ -1051,9 +1057,10 @@ rte_vhost_driver_unregister(const char *path)
 				next = TAILQ_NEXT(conn, next);
 
 				/*
-				 * If r/wcb is executing, release the
-				 * conn_mutex lock, and try again since
-				 * the r/wcb may use the conn_mutex lock.
+				 * If r/wcb is executing, release vsocket's
+				 * conn_mutex and vhost_user's mutex locks, and
+				 * try again since the r/wcb may use the
+				 * conn_mutex and mutex locks.
 				 */
 				if (fdset_try_del(&vhost_user.fdset,
 						  conn->connfd) == -1) {
@@ -1074,8 +1081,17 @@ rte_vhost_driver_unregister(const char *path)
 			pthread_mutex_unlock(&vsocket->conn_mutex);
 
 			if (vsocket->is_server) {
-				fdset_del(&vhost_user.fdset,
-						vsocket->socket_fd);
+				/*
+				 * If r/wcb is executing, release vhost_user's
+				 * mutex lock, and try again since the r/wcb
+				 * may use the mutex lock.
+				 */
+				if (fdset_try_del(&vhost_user.fdset,
+						vsocket->socket_fd) == -1) {
+					pthread_mutex_unlock(&vhost_user.mutex);
+					goto again;
+				}
+
 				close(vsocket->socket_fd);
 				unlink(path);
 			} else if (vsocket->reconnect) {
diff --git a/dpdk/lib/librte_vhost/vhost.c b/dpdk/lib/librte_vhost/vhost.c
index 1cbe948f74..2d5bb2cfde 100644
--- a/dpdk/lib/librte_vhost/vhost.c
+++ b/dpdk/lib/librte_vhost/vhost.c
@@ -26,6 +26,7 @@
 #include "vhost_user.h"
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
+pthread_mutex_t vhost_dev_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /* Called with iotlb_lock read-locked */
 uint64_t
@@ -350,6 +351,57 @@ free_device(struct virtio_net *dev)
 	rte_free(dev);
 }
 
+static __rte_always_inline int
+log_translate(struct virtio_net *dev, struct vhost_virtqueue *vq)
+{
+	if (likely(!(vq->ring_addrs.flags & (1 << VHOST_VRING_F_LOG))))
+		return 0;
+
+	vq->log_guest_addr = translate_log_addr(dev, vq,
+						vq->ring_addrs.log_guest_addr);
+	if (vq->log_guest_addr == 0)
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Converts vring log address to GPA
+ * If IOMMU is enabled, the log address is IOVA
+ * If IOMMU not enabled, the log address is already GPA
+ *
+ * Caller should have iotlb_lock read-locked
+ */
+uint64_t
+translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq,
+		uint64_t log_addr)
+{
+	if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) {
+		const uint64_t exp_size = sizeof(uint64_t);
+		uint64_t hva, gpa;
+		uint64_t size = exp_size;
+
+		hva = vhost_iova_to_vva(dev, vq, log_addr,
+					&size, VHOST_ACCESS_RW);
+
+		if (size != exp_size)
+			return 0;
+
+		gpa = hva_to_gpa(dev, hva, exp_size);
+		if (!gpa) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"VQ: Failed to find GPA for log_addr: 0x%"
+				PRIx64 " hva: 0x%" PRIx64 "\n",
+				log_addr, hva);
+			return 0;
+		}
+		return gpa;
+
+	} else
+		return log_addr;
+}
+
+/* Caller should have iotlb_lock read-locked */
 static int
 vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq)
 {
@@ -388,6 +440,7 @@ vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq)
 	return 0;
 }
 
+/* Caller should have iotlb_lock read-locked */
 static int
 vring_translate_packed(struct virtio_net *dev, struct vhost_virtqueue *vq)
 {
@@ -434,6 +487,10 @@ vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq)
 		if (vring_translate_split(dev, vq) < 0)
 			return -1;
 	}
+
+	if (log_translate(dev, vq) < 0)
+		return -1;
+
 	vq->access_ok = 1;
 
 	return 0;
@@ -504,22 +561,29 @@ int
 alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
 {
 	struct vhost_virtqueue *vq;
+	uint32_t i;
 
-	vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
-	if (vq == NULL) {
-		RTE_LOG(ERR, VHOST_CONFIG,
-			"Failed to allocate memory for vring:%u.\n", vring_idx);
-		return -1;
-	}
+	/* Also allocate holes, if any, up to requested vring index. */
+	for (i = 0; i <= vring_idx; i++) {
+		if (dev->virtqueue[i])
+			continue;
 
-	dev->virtqueue[vring_idx] = vq;
-	init_vring_queue(dev, vring_idx);
-	rte_spinlock_init(&vq->access_lock);
-	vq->avail_wrap_counter = 1;
-	vq->used_wrap_counter = 1;
-	vq->signalled_used_valid = false;
+		vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
+		if (vq == NULL) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"Failed to allocate memory for vring:%u.\n", i);
+			return -1;
+		}
 
-	dev->nr_vring += 1;
+		dev->virtqueue[i] = vq;
+		init_vring_queue(dev, i);
+		rte_spinlock_init(&vq->access_lock);
+		vq->avail_wrap_counter = 1;
+		vq->used_wrap_counter = 1;
+		vq->signalled_used_valid = false;
+	}
+
+	dev->nr_vring = RTE_MAX(dev->nr_vring, vring_idx + 1);
 
 	return 0;
 }
@@ -552,6 +616,7 @@ vhost_new_device(void)
 	struct virtio_net *dev;
 	int i;
 
+	pthread_mutex_lock(&vhost_dev_lock);
 	for (i = 0; i < MAX_VHOST_DEVICE; i++) {
 		if (vhost_devices[i] == NULL)
 			break;
@@ -560,6 +625,7 @@ vhost_new_device(void)
 	if (i == MAX_VHOST_DEVICE) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"Failed to find a free slot for new device.\n");
+		pthread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
@@ -567,10 +633,13 @@ vhost_new_device(void)
 	if (dev == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"Failed to allocate memory for new dev.\n");
+		pthread_mutex_unlock(&vhost_dev_lock);
 		return -1;
 	}
 
 	vhost_devices[i] = dev;
+	pthread_mutex_unlock(&vhost_dev_lock);
+
 	dev->vid = i;
 	dev->flags = VIRTIO_DEV_BUILTIN_VIRTIO_NET;
 	dev->slave_req_fd = -1;
@@ -1195,7 +1264,12 @@ rte_vhost_avail_entries(int vid, uint16_t queue_id)
 	if (!dev)
 		return 0;
 
+	if (queue_id >= VHOST_MAX_VRING)
+		return 0;
+
 	vq = dev->virtqueue[queue_id];
+	if (!vq)
+		return 0;
 
 	rte_spinlock_lock(&vq->access_lock);
 
@@ -1265,7 +1339,12 @@ rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable)
 	if (!dev)
 		return -1;
 
+	if (queue_id >= VHOST_MAX_VRING)
+		return -1;
+
 	vq = dev->virtqueue[queue_id];
+	if (!vq)
+		return -1;
 
 	rte_spinlock_lock(&vq->access_lock);
 
@@ -1376,6 +1455,9 @@ int rte_vhost_get_vring_base(int vid, uint16_t queue_id,
 	if (dev == NULL || last_avail_idx == NULL || last_used_idx == NULL)
 		return -1;
 
+	if (queue_id >= VHOST_MAX_VRING)
+		return -1;
+
 	vq = dev->virtqueue[queue_id];
 	if (!vq)
 		return -1;
@@ -1402,6 +1484,9 @@ int rte_vhost_set_vring_base(int vid, uint16_t queue_id,
 	if (!dev)
 		return -1;
 
+	if (queue_id >= VHOST_MAX_VRING)
+		return -1;
+
 	vq = dev->virtqueue[queue_id];
 	if (!vq)
 		return -1;
@@ -1426,15 +1511,23 @@ rte_vhost_get_vring_base_from_inflight(int vid,
 				       uint16_t *last_used_idx)
 {
 	struct rte_vhost_inflight_info_packed *inflight_info;
+	struct vhost_virtqueue *vq;
 	struct virtio_net *dev = get_device(vid);
 
 	if (dev == NULL || last_avail_idx == NULL || last_used_idx == NULL)
 		return -1;
 
+	if (queue_id >= VHOST_MAX_VRING)
+		return -1;
+
+	vq = dev->virtqueue[queue_id];
+	if (!vq)
+		return -1;
+
 	if (!vq_is_packed(dev))
 		return -1;
 
-	inflight_info = dev->virtqueue[queue_id]->inflight_packed;
+	inflight_info = vq->inflight_packed;
 	if (!inflight_info)
 		return -1;
 
diff --git a/dpdk/lib/librte_vhost/vhost.h b/dpdk/lib/librte_vhost/vhost.h
index 9f11b28a31..deeca18f8f 100644
--- a/dpdk/lib/librte_vhost/vhost.h
+++ b/dpdk/lib/librte_vhost/vhost.h
@@ -202,26 +202,9 @@ struct vhost_virtqueue {
 	TAILQ_HEAD(, vhost_iotlb_entry) iotlb_pending_list;
 } __rte_cache_aligned;
 
-/* Old kernels have no such macros defined */
-#ifndef VIRTIO_NET_F_GUEST_ANNOUNCE
- #define VIRTIO_NET_F_GUEST_ANNOUNCE 21
-#endif
-
-#ifndef VIRTIO_NET_F_MQ
- #define VIRTIO_NET_F_MQ		22
-#endif
-
 #define VHOST_MAX_VRING			0x100
 #define VHOST_MAX_QUEUE_PAIRS		0x80
 
-#ifndef VIRTIO_NET_F_MTU
- #define VIRTIO_NET_F_MTU 3
-#endif
-
-#ifndef VIRTIO_F_ANY_LAYOUT
- #define VIRTIO_F_ANY_LAYOUT		27
-#endif
-
 /* Declare IOMMU related bits for older kernels */
 #ifndef VIRTIO_F_IOMMU_PLATFORM
 
@@ -462,14 +445,23 @@ static __rte_always_inline void
 vhost_log_cache_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
 			uint64_t offset, uint64_t len)
 {
-	vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, len);
+	if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) {
+		if (unlikely(vq->log_guest_addr == 0))
+			return;
+		__vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset,
+					len);
+	}
 }
 
 static __rte_always_inline void
 vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
 		     uint64_t offset, uint64_t len)
 {
-	vhost_log_write(dev, vq->log_guest_addr + offset, len);
+	if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) {
+		if (unlikely(vq->log_guest_addr == 0))
+			return;
+		__vhost_log_write(dev, vq->log_guest_addr + offset, len);
+	}
 }
 
 static __rte_always_inline void
@@ -528,7 +520,6 @@ vhost_log_write_iova(struct virtio_net *dev, struct vhost_virtqueue *vq,
 #define PRINT_PACKET(device, addr, size, header) do {} while (0)
 #endif
 
-extern uint64_t VHOST_FEATURES;
 #define MAX_VHOST_DEVICE	1024
 extern struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
@@ -620,6 +611,8 @@ void *vhost_alloc_copy_ind_table(struct virtio_net *dev,
 			struct vhost_virtqueue *vq,
 			uint64_t desc_addr, uint64_t desc_len);
 int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq);
+uint64_t translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq,
+		uint64_t log_addr);
 void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq);
 
 static __rte_always_inline uint64_t
diff --git a/dpdk/lib/librte_vhost/vhost_crypto.c b/dpdk/lib/librte_vhost/vhost_crypto.c
index 684fddc30b..e08f9c6d75 100644
--- a/dpdk/lib/librte_vhost/vhost_crypto.c
+++ b/dpdk/lib/librte_vhost/vhost_crypto.c
@@ -40,11 +40,20 @@
 		(1 << VIRTIO_RING_F_EVENT_IDX) |			\
 		(1 << VIRTIO_CRYPTO_SERVICE_CIPHER) |			\
 		(1 << VIRTIO_CRYPTO_SERVICE_MAC) |			\
-		(1 << VIRTIO_NET_F_CTRL_VQ))
+		(1 << VIRTIO_NET_F_CTRL_VQ) |				\
+		(1 << VHOST_USER_PROTOCOL_F_CONFIG))
 
 #define IOVA_TO_VVA(t, r, a, l, p)					\
 	((t)(uintptr_t)vhost_iova_to_vva(r->dev, r->vq, a, l, p))
 
+/*
+ * vhost_crypto_desc is used to copy original vring_desc to the local buffer
+ * before processing (except the next index). The copy result will be an
+ * array of vhost_crypto_desc elements that follows the sequence of original
+ * vring_desc.next is arranged.
+ */
+#define vhost_crypto_desc vring_desc
+
 static int
 cipher_algo_transform(uint32_t virtio_cipher_algo,
 		enum rte_crypto_cipher_algorithm *algo)
@@ -237,6 +246,11 @@ transform_cipher_param(struct rte_crypto_sym_xform *xform,
 	if (unlikely(ret < 0))
 		return ret;
 
+	if (param->cipher_key_len > VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH) {
+		VC_LOG_DBG("Invalid cipher key length\n");
+		return -VIRTIO_CRYPTO_BADMSG;
+	}
+
 	xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 	xform->cipher.key.length = param->cipher_key_len;
 	if (xform->cipher.key.length > 0)
@@ -287,6 +301,12 @@ transform_chain_param(struct rte_crypto_sym_xform *xforms,
 			&xform_cipher->cipher.algo);
 	if (unlikely(ret < 0))
 		return ret;
+
+	if (param->cipher_key_len > VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH) {
+		VC_LOG_DBG("Invalid cipher key length\n");
+		return -VIRTIO_CRYPTO_BADMSG;
+	}
+
 	xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
 	xform_cipher->cipher.key.length = param->cipher_key_len;
 	xform_cipher->cipher.key.data = param->cipher_key_buf;
@@ -301,6 +321,12 @@ transform_chain_param(struct rte_crypto_sym_xform *xforms,
 	ret = auth_algo_transform(param->hash_algo, &xform_auth->auth.algo);
 	if (unlikely(ret < 0))
 		return ret;
+
+	if (param->auth_key_len > VHOST_USER_CRYPTO_MAX_HMAC_KEY_LENGTH) {
+		VC_LOG_DBG("Invalid auth key length\n");
+		return -VIRTIO_CRYPTO_BADMSG;
+	}
+
 	xform_auth->auth.digest_length = param->digest_len;
 	xform_auth->auth.key.length = param->auth_key_len;
 	xform_auth->auth.key.data = param->auth_key_buf;
@@ -461,82 +487,71 @@ vhost_crypto_msg_post_handler(int vid, void *msg)
 	return ret;
 }
 
-static __rte_always_inline struct vring_desc *
-find_write_desc(struct vring_desc *head, struct vring_desc *desc,
-		uint32_t *nb_descs, uint32_t vq_size)
+static __rte_always_inline struct vhost_crypto_desc *
+find_write_desc(struct vhost_crypto_desc *head, struct vhost_crypto_desc *desc,
+		uint32_t max_n_descs)
 {
-	if (desc->flags & VRING_DESC_F_WRITE)
-		return desc;
-
-	while (desc->flags & VRING_DESC_F_NEXT) {
-		if (unlikely(*nb_descs == 0 || desc->next >= vq_size))
-			return NULL;
-		(*nb_descs)--;
+	if (desc < head)
+		return NULL;
 
-		desc = &head[desc->next];
+	while (desc - head < (int)max_n_descs) {
 		if (desc->flags & VRING_DESC_F_WRITE)
 			return desc;
+		desc++;
 	}
 
 	return NULL;
 }
 
-static struct virtio_crypto_inhdr *
-reach_inhdr(struct vhost_crypto_data_req *vc_req, struct vring_desc *desc,
-		uint32_t *nb_descs, uint32_t vq_size)
+static __rte_always_inline struct virtio_crypto_inhdr *
+reach_inhdr(struct vhost_crypto_data_req *vc_req,
+		struct vhost_crypto_desc *head,
+		uint32_t max_n_descs)
 {
-	uint64_t dlen;
 	struct virtio_crypto_inhdr *inhdr;
+	struct vhost_crypto_desc *last = head + (max_n_descs - 1);
+	uint64_t dlen = last->len;
 
-	while (desc->flags & VRING_DESC_F_NEXT) {
-		if (unlikely(*nb_descs == 0 || desc->next >= vq_size))
-			return NULL;
-		(*nb_descs)--;
-		desc = &vc_req->head[desc->next];
-	}
+	if (unlikely(dlen != sizeof(*inhdr)))
+		return NULL;
 
-	dlen = desc->len;
-	inhdr = IOVA_TO_VVA(struct virtio_crypto_inhdr *, vc_req, desc->addr,
+	inhdr = IOVA_TO_VVA(struct virtio_crypto_inhdr *, vc_req, last->addr,
 			&dlen, VHOST_ACCESS_WO);
-	if (unlikely(!inhdr || dlen != desc->len))
+	if (unlikely(!inhdr || dlen != last->len))
 		return NULL;
 
 	return inhdr;
 }
 
 static __rte_always_inline int
-move_desc(struct vring_desc *head, struct vring_desc **cur_desc,
-		uint32_t size, uint32_t *nb_descs, uint32_t vq_size)
+move_desc(struct vhost_crypto_desc *head,
+		struct vhost_crypto_desc **cur_desc,
+		uint32_t size, uint32_t max_n_descs)
 {
-	struct vring_desc *desc = *cur_desc;
+	struct vhost_crypto_desc *desc = *cur_desc;
 	int left = size - desc->len;
 
-	while ((desc->flags & VRING_DESC_F_NEXT) && left > 0) {
-		(*nb_descs)--;
-		if (unlikely(*nb_descs == 0 || desc->next >= vq_size))
-			return -1;
-
-		desc = &head[desc->next];
-		rte_prefetch0(&head[desc->next]);
+	while (desc->flags & VRING_DESC_F_NEXT && left > 0 &&
+			desc >= head &&
+			desc - head < (int)max_n_descs) {
+		desc++;
 		left -= desc->len;
 	}
 
 	if (unlikely(left > 0))
 		return -1;
 
-	if (unlikely(*nb_descs == 0))
+	if (unlikely(head - desc == (int)max_n_descs))
 		*cur_desc = NULL;
-	else {
-		if (unlikely(desc->next >= vq_size))
-			return -1;
-		*cur_desc = &head[desc->next];
-	}
+	else
+		*cur_desc = desc + 1;
 
 	return 0;
 }
 
 static __rte_always_inline void *
-get_data_ptr(struct vhost_crypto_data_req *vc_req, struct vring_desc *cur_desc,
+get_data_ptr(struct vhost_crypto_data_req *vc_req,
+		struct vhost_crypto_desc *cur_desc,
 		uint8_t perm)
 {
 	void *data;
@@ -551,12 +566,13 @@ get_data_ptr(struct vhost_crypto_data_req *vc_req, struct vring_desc *cur_desc,
 	return data;
 }
 
-static int
+static __rte_always_inline int
 copy_data(void *dst_data, struct vhost_crypto_data_req *vc_req,
-		struct vring_desc **cur_desc, uint32_t size,
-		uint32_t *nb_descs, uint32_t vq_size)
+		struct vhost_crypto_desc *head,
+		struct vhost_crypto_desc **cur_desc,
+		uint32_t size, uint32_t max_n_descs)
 {
-	struct vring_desc *desc = *cur_desc;
+	struct vhost_crypto_desc *desc = *cur_desc;
 	uint64_t remain, addr, dlen, len;
 	uint32_t to_copy;
 	uint8_t *data = dst_data;
@@ -595,17 +611,10 @@ copy_data(void *dst_data, struct vhost_crypto_data_req *vc_req,
 
 	left -= to_copy;
 
-	while ((desc->flags & VRING_DESC_F_NEXT) && left > 0) {
-		if (unlikely(*nb_descs == 0 || desc->next >= vq_size)) {
-			VC_LOG_ERR("Invalid descriptors");
-			return -1;
-		}
-		(*nb_descs)--;
-
-		desc = &vc_req->head[desc->next];
-		rte_prefetch0(&vc_req->head[desc->next]);
+	while (desc >= head && desc - head < (int)max_n_descs && left) {
+		desc++;
 		to_copy = RTE_MIN(desc->len, (uint32_t)left);
-		dlen = desc->len;
+		dlen = to_copy;
 		src = IOVA_TO_VVA(uint8_t *, vc_req, desc->addr, &dlen,
 				VHOST_ACCESS_RO);
 		if (unlikely(!src || !dlen)) {
@@ -644,13 +653,10 @@ copy_data(void *dst_data, struct vhost_crypto_data_req *vc_req,
 		return -1;
 	}
 
-	if (unlikely(*nb_descs == 0))
+	if (unlikely(desc - head == (int)max_n_descs))
 		*cur_desc = NULL;
-	else {
-		if (unlikely(desc->next >= vq_size))
-			return -1;
-		*cur_desc = &vc_req->head[desc->next];
-	}
+	else
+		*cur_desc = desc + 1;
 
 	return 0;
 }
@@ -662,6 +668,7 @@ write_back_data(struct vhost_crypto_data_req *vc_req)
 
 	while (wb_data) {
 		rte_memcpy(wb_data->dst, wb_data->src, wb_data->len);
+		memset(wb_data->src, 0, wb_data->len);
 		wb_last = wb_data;
 		wb_data = wb_data->next;
 		rte_mempool_put(vc_req->wb_pool, wb_last);
@@ -703,17 +710,18 @@ free_wb_data(struct vhost_crypto_writeback_data *wb_data,
  * @return
  *   The pointer to the start of the write back data linked list.
  */
-static struct vhost_crypto_writeback_data *
+static __rte_always_inline struct vhost_crypto_writeback_data *
 prepare_write_back_data(struct vhost_crypto_data_req *vc_req,
-		struct vring_desc **cur_desc,
+		struct vhost_crypto_desc *head_desc,
+		struct vhost_crypto_desc **cur_desc,
 		struct vhost_crypto_writeback_data **end_wb_data,
 		uint8_t *src,
 		uint32_t offset,
 		uint64_t write_back_len,
-		uint32_t *nb_descs, uint32_t vq_size)
+		uint32_t max_n_descs)
 {
 	struct vhost_crypto_writeback_data *wb_data, *head;
-	struct vring_desc *desc = *cur_desc;
+	struct vhost_crypto_desc *desc = *cur_desc;
 	uint64_t dlen;
 	uint8_t *dst;
 	int ret;
@@ -730,14 +738,14 @@ prepare_write_back_data(struct vhost_crypto_data_req *vc_req,
 		wb_data->src = src + offset;
 		dlen = desc->len;
 		dst = IOVA_TO_VVA(uint8_t *, vc_req, desc->addr,
-			&dlen, VHOST_ACCESS_RW) + offset;
+			&dlen, VHOST_ACCESS_RW);
 		if (unlikely(!dst || dlen != desc->len)) {
 			VC_LOG_ERR("Failed to map descriptor");
 			goto error_exit;
 		}
 
-		wb_data->dst = dst;
-		wb_data->len = desc->len - offset;
+		wb_data->dst = dst + offset;
+		wb_data->len = RTE_MIN(dlen - offset, write_back_len);
 		write_back_len -= wb_data->len;
 		src += offset + wb_data->len;
 		offset = 0;
@@ -756,14 +764,10 @@ prepare_write_back_data(struct vhost_crypto_data_req *vc_req,
 	} else
 		offset -= desc->len;
 
-	while (write_back_len) {
-		if (unlikely(*nb_descs == 0 || desc->next >= vq_size)) {
-			VC_LOG_ERR("Invalid descriptors");
-			goto error_exit;
-		}
-		(*nb_descs)--;
-
-		desc = &vc_req->head[desc->next];
+	while (write_back_len &&
+			desc >= head_desc &&
+			desc - head_desc < (int)max_n_descs) {
+		desc++;
 		if (unlikely(!(desc->flags & VRING_DESC_F_WRITE))) {
 			VC_LOG_ERR("incorrect descriptor");
 			goto error_exit;
@@ -782,7 +786,7 @@ prepare_write_back_data(struct vhost_crypto_data_req *vc_req,
 			goto error_exit;
 		}
 
-		wb_data->src = src;
+		wb_data->src = src + offset;
 		wb_data->dst = dst;
 		wb_data->len = RTE_MIN(desc->len - offset, write_back_len);
 		write_back_len -= wb_data->len;
@@ -802,13 +806,10 @@ prepare_write_back_data(struct vhost_crypto_data_req *vc_req,
 			wb_data->next = NULL;
 	}
 
-	if (unlikely(*nb_descs == 0))
+	if (unlikely(desc - head_desc == (int)max_n_descs))
 		*cur_desc = NULL;
-	else {
-		if (unlikely(desc->next >= vq_size))
-			goto error_exit;
-		*cur_desc = &vc_req->head[desc->next];
-	}
+	else
+		*cur_desc = desc + 1;
 
 	*end_wb_data = wb_data;
 
@@ -821,31 +822,44 @@ prepare_write_back_data(struct vhost_crypto_data_req *vc_req,
 	return NULL;
 }
 
-static uint8_t
+static __rte_always_inline uint8_t
+vhost_crypto_check_cipher_request(struct virtio_crypto_cipher_data_req *req)
+{
+	if (likely((req->para.iv_len <= VHOST_CRYPTO_MAX_IV_LEN) &&
+		(req->para.src_data_len <= RTE_MBUF_DEFAULT_BUF_SIZE) &&
+		(req->para.dst_data_len >= req->para.src_data_len) &&
+		(req->para.dst_data_len <= RTE_MBUF_DEFAULT_BUF_SIZE)))
+		return VIRTIO_CRYPTO_OK;
+	return VIRTIO_CRYPTO_BADMSG;
+}
+
+static __rte_always_inline uint8_t
 prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 		struct vhost_crypto_data_req *vc_req,
 		struct virtio_crypto_cipher_data_req *cipher,
-		struct vring_desc *cur_desc,
-		uint32_t *nb_descs, uint32_t vq_size)
+		struct vhost_crypto_desc *head,
+		uint32_t max_n_descs)
 {
-	struct vring_desc *desc = cur_desc;
+	struct vhost_crypto_desc *desc = head;
 	struct vhost_crypto_writeback_data *ewb = NULL;
 	struct rte_mbuf *m_src = op->sym->m_src, *m_dst = op->sym->m_dst;
 	uint8_t *iv_data = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET);
-	uint8_t ret = 0;
+	uint8_t ret = vhost_crypto_check_cipher_request(cipher);
+
+	if (unlikely(ret != VIRTIO_CRYPTO_OK))
+		goto error_exit;
 
 	/* prepare */
 	/* iv */
-	if (unlikely(copy_data(iv_data, vc_req, &desc, cipher->para.iv_len,
-			nb_descs, vq_size) < 0)) {
+	if (unlikely(copy_data(iv_data, vc_req, head, &desc,
+			cipher->para.iv_len, max_n_descs))) {
 		ret = VIRTIO_CRYPTO_BADMSG;
 		goto error_exit;
 	}
 
-	m_src->data_len = cipher->para.src_data_len;
-
 	switch (vcrypto->option) {
 	case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
+		m_src->data_len = cipher->para.src_data_len;
 		m_src->buf_iova = gpa_to_hpa(vcrypto->dev, desc->addr,
 				cipher->para.src_data_len);
 		m_src->buf_addr = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);
@@ -856,9 +870,8 @@ prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 			goto error_exit;
 		}
 
-		if (unlikely(move_desc(vc_req->head, &desc,
-				cipher->para.src_data_len, nb_descs,
-				vq_size) < 0)) {
+		if (unlikely(move_desc(head, &desc, cipher->para.src_data_len,
+				max_n_descs) < 0)) {
 			VC_LOG_ERR("Incorrect descriptor");
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
@@ -867,16 +880,10 @@ prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 		break;
 	case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
 		vc_req->wb_pool = vcrypto->wb_pool;
-
-		if (unlikely(cipher->para.src_data_len >
-				RTE_MBUF_DEFAULT_BUF_SIZE)) {
-			VC_LOG_ERR("Not enough space to do data copy");
-			ret = VIRTIO_CRYPTO_ERR;
-			goto error_exit;
-		}
+		m_src->data_len = cipher->para.src_data_len;
 		if (unlikely(copy_data(rte_pktmbuf_mtod(m_src, uint8_t *),
-				vc_req, &desc, cipher->para.src_data_len,
-				nb_descs, vq_size) < 0)) {
+				vc_req, head, &desc, cipher->para.src_data_len,
+				max_n_descs) < 0)) {
 			ret = VIRTIO_CRYPTO_BADMSG;
 			goto error_exit;
 		}
@@ -887,7 +894,7 @@ prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 	}
 
 	/* dst */
-	desc = find_write_desc(vc_req->head, desc, nb_descs, vq_size);
+	desc = find_write_desc(head, desc, max_n_descs);
 	if (unlikely(!desc)) {
 		VC_LOG_ERR("Cannot find write location");
 		ret = VIRTIO_CRYPTO_BADMSG;
@@ -905,9 +912,8 @@ prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 			goto error_exit;
 		}
 
-		if (unlikely(move_desc(vc_req->head, &desc,
-				cipher->para.dst_data_len,
-				nb_descs, vq_size) < 0)) {
+		if (unlikely(move_desc(head, &desc, cipher->para.dst_data_len,
+				max_n_descs) < 0)) {
 			VC_LOG_ERR("Incorrect descriptor");
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
@@ -916,9 +922,9 @@ prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 		m_dst->data_len = cipher->para.dst_data_len;
 		break;
 	case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
-		vc_req->wb = prepare_write_back_data(vc_req, &desc, &ewb,
+		vc_req->wb = prepare_write_back_data(vc_req, head, &desc, &ewb,
 				rte_pktmbuf_mtod(m_src, uint8_t *), 0,
-				cipher->para.dst_data_len, nb_descs, vq_size);
+				cipher->para.dst_data_len, max_n_descs);
 		if (unlikely(vc_req->wb == NULL)) {
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
@@ -956,33 +962,58 @@ prepare_sym_cipher_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 	return ret;
 }
 
-static uint8_t
+static __rte_always_inline uint8_t
+vhost_crypto_check_chain_request(struct virtio_crypto_alg_chain_data_req *req)
+{
+	if (likely((req->para.iv_len <= VHOST_CRYPTO_MAX_IV_LEN) &&
+		(req->para.src_data_len <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
+		(req->para.dst_data_len >= req->para.src_data_len) &&
+		(req->para.dst_data_len <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
+		(req->para.cipher_start_src_offset <
+			VHOST_CRYPTO_MAX_DATA_SIZE) &&
+		(req->para.len_to_cipher <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
+		(req->para.hash_start_src_offset <
+			VHOST_CRYPTO_MAX_DATA_SIZE) &&
+		(req->para.len_to_hash <= VHOST_CRYPTO_MAX_DATA_SIZE) &&
+		(req->para.cipher_start_src_offset + req->para.len_to_cipher <=
+			req->para.src_data_len) &&
+		(req->para.hash_start_src_offset + req->para.len_to_hash <=
+			req->para.src_data_len) &&
+		(req->para.dst_data_len + req->para.hash_result_len <=
+			VHOST_CRYPTO_MAX_DATA_SIZE)))
+		return VIRTIO_CRYPTO_OK;
+	return VIRTIO_CRYPTO_BADMSG;
+}
+
+static __rte_always_inline uint8_t
 prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 		struct vhost_crypto_data_req *vc_req,
 		struct virtio_crypto_alg_chain_data_req *chain,
-		struct vring_desc *cur_desc,
-		uint32_t *nb_descs, uint32_t vq_size)
+		struct vhost_crypto_desc *head,
+		uint32_t max_n_descs)
 {
-	struct vring_desc *desc = cur_desc, *digest_desc;
+	struct vhost_crypto_desc *desc = head, *digest_desc;
 	struct vhost_crypto_writeback_data *ewb = NULL, *ewb2 = NULL;
 	struct rte_mbuf *m_src = op->sym->m_src, *m_dst = op->sym->m_dst;
 	uint8_t *iv_data = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFFSET);
 	uint32_t digest_offset;
 	void *digest_addr;
-	uint8_t ret = 0;
+	uint8_t ret = vhost_crypto_check_chain_request(chain);
+
+	if (unlikely(ret != VIRTIO_CRYPTO_OK))
+		goto error_exit;
 
 	/* prepare */
 	/* iv */
-	if (unlikely(copy_data(iv_data, vc_req, &desc,
-			chain->para.iv_len, nb_descs, vq_size) < 0)) {
+	if (unlikely(copy_data(iv_data, vc_req, head, &desc,
+			chain->para.iv_len, max_n_descs) < 0)) {
 		ret = VIRTIO_CRYPTO_BADMSG;
 		goto error_exit;
 	}
 
-	m_src->data_len = chain->para.src_data_len;
-
 	switch (vcrypto->option) {
 	case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
+		m_src->data_len = chain->para.src_data_len;
 		m_dst->data_len = chain->para.dst_data_len;
 
 		m_src->buf_iova = gpa_to_hpa(vcrypto->dev, desc->addr,
@@ -994,9 +1025,8 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 			goto error_exit;
 		}
 
-		if (unlikely(move_desc(vc_req->head, &desc,
-				chain->para.src_data_len,
-				nb_descs, vq_size) < 0)) {
+		if (unlikely(move_desc(head, &desc, chain->para.src_data_len,
+				max_n_descs) < 0)) {
 			VC_LOG_ERR("Incorrect descriptor");
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
@@ -1004,16 +1034,10 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 		break;
 	case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
 		vc_req->wb_pool = vcrypto->wb_pool;
-
-		if (unlikely(chain->para.src_data_len >
-				RTE_MBUF_DEFAULT_BUF_SIZE)) {
-			VC_LOG_ERR("Not enough space to do data copy");
-			ret = VIRTIO_CRYPTO_ERR;
-			goto error_exit;
-		}
+		m_src->data_len = chain->para.src_data_len;
 		if (unlikely(copy_data(rte_pktmbuf_mtod(m_src, uint8_t *),
-				vc_req, &desc, chain->para.src_data_len,
-				nb_descs, vq_size) < 0)) {
+				vc_req, head, &desc, chain->para.src_data_len,
+				max_n_descs) < 0)) {
 			ret = VIRTIO_CRYPTO_BADMSG;
 			goto error_exit;
 		}
@@ -1025,7 +1049,7 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 	}
 
 	/* dst */
-	desc = find_write_desc(vc_req->head, desc, nb_descs, vq_size);
+	desc = find_write_desc(head, desc, max_n_descs);
 	if (unlikely(!desc)) {
 		VC_LOG_ERR("Cannot find write location");
 		ret = VIRTIO_CRYPTO_BADMSG;
@@ -1044,8 +1068,7 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 		}
 
 		if (unlikely(move_desc(vc_req->head, &desc,
-				chain->para.dst_data_len,
-				nb_descs, vq_size) < 0)) {
+				chain->para.dst_data_len, max_n_descs) < 0)) {
 			VC_LOG_ERR("Incorrect descriptor");
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
@@ -1061,9 +1084,9 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 			goto error_exit;
 		}
 
-		if (unlikely(move_desc(vc_req->head, &desc,
+		if (unlikely(move_desc(head, &desc,
 				chain->para.hash_result_len,
-				nb_descs, vq_size) < 0)) {
+				max_n_descs) < 0)) {
 			VC_LOG_ERR("Incorrect descriptor");
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
@@ -1071,34 +1094,34 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 
 		break;
 	case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
-		vc_req->wb = prepare_write_back_data(vc_req, &desc, &ewb,
+		vc_req->wb = prepare_write_back_data(vc_req, head, &desc, &ewb,
 				rte_pktmbuf_mtod(m_src, uint8_t *),
 				chain->para.cipher_start_src_offset,
 				chain->para.dst_data_len -
-				chain->para.cipher_start_src_offset,
-				nb_descs, vq_size);
+					chain->para.cipher_start_src_offset,
+				max_n_descs);
 		if (unlikely(vc_req->wb == NULL)) {
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
 		}
 
+		digest_desc = desc;
 		digest_offset = m_src->data_len;
 		digest_addr = rte_pktmbuf_mtod_offset(m_src, void *,
 				digest_offset);
-		digest_desc = desc;
 
 		/** create a wb_data for digest */
-		ewb->next = prepare_write_back_data(vc_req, &desc, &ewb2,
-				digest_addr, 0, chain->para.hash_result_len,
-				nb_descs, vq_size);
+		ewb->next = prepare_write_back_data(vc_req, head, &desc,
+				&ewb2, digest_addr, 0,
+				chain->para.hash_result_len, max_n_descs);
 		if (unlikely(ewb->next == NULL)) {
 			ret = VIRTIO_CRYPTO_ERR;
 			goto error_exit;
 		}
 
-		if (unlikely(copy_data(digest_addr, vc_req, &digest_desc,
+		if (unlikely(copy_data(digest_addr, vc_req, head, &digest_desc,
 				chain->para.hash_result_len,
-				nb_descs, vq_size) < 0)) {
+				max_n_descs) < 0)) {
 			ret = VIRTIO_CRYPTO_BADMSG;
 			goto error_exit;
 		}
@@ -1148,74 +1171,103 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,
 static __rte_always_inline int
 vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,
 		struct vhost_virtqueue *vq, struct rte_crypto_op *op,
-		struct vring_desc *head, uint16_t desc_idx)
+		struct vring_desc *head, struct vhost_crypto_desc *descs,
+		uint16_t desc_idx)
 {
 	struct vhost_crypto_data_req *vc_req = rte_mbuf_to_priv(op->sym->m_src);
 	struct rte_cryptodev_sym_session *session;
-	struct virtio_crypto_op_data_req *req, tmp_req;
+	struct virtio_crypto_op_data_req req;
 	struct virtio_crypto_inhdr *inhdr;
-	struct vring_desc *desc = NULL;
+	struct vhost_crypto_desc *desc = descs;
+	struct vring_desc *src_desc;
 	uint64_t session_id;
 	uint64_t dlen;
-	uint32_t nb_descs = vq->size;
-	int err = 0;
+	uint32_t nb_descs = 0, max_n_descs, i;
+	int err;
 
 	vc_req->desc_idx = desc_idx;
 	vc_req->dev = vcrypto->dev;
 	vc_req->vq = vq;
 
-	if (likely(head->flags & VRING_DESC_F_INDIRECT)) {
-		dlen = head->len;
-		nb_descs = dlen / sizeof(struct vring_desc);
-		/* drop invalid descriptors */
-		if (unlikely(nb_descs > vq->size))
-			return -1;
-		desc = IOVA_TO_VVA(struct vring_desc *, vc_req, head->addr,
-				&dlen, VHOST_ACCESS_RO);
-		if (unlikely(!desc || dlen != head->len))
-			return -1;
-		desc_idx = 0;
-		head = desc;
-	} else {
-		desc = head;
+	if (unlikely((head->flags & VRING_DESC_F_INDIRECT) == 0)) {
+		VC_LOG_ERR("Invalid descriptor");
+		return -1;
 	}
 
-	vc_req->head = head;
-	vc_req->zero_copy = vcrypto->option;
+	dlen = head->len;
+	src_desc = IOVA_TO_VVA(struct vring_desc *, vc_req, head->addr,
+			&dlen, VHOST_ACCESS_RO);
+	if (unlikely(!src_desc || dlen != head->len)) {
+		VC_LOG_ERR("Invalid descriptor");
+		return -1;
+	}
+	head = src_desc;
+
+	nb_descs = max_n_descs = dlen / sizeof(struct vring_desc);
+	if (unlikely(nb_descs > VHOST_CRYPTO_MAX_N_DESC || nb_descs == 0)) {
+		err = VIRTIO_CRYPTO_ERR;
+		VC_LOG_ERR("Cannot process num of descriptors %u", nb_descs);
+		if (nb_descs > 0) {
+			struct vring_desc *inhdr_desc = head;
+			while (inhdr_desc->flags & VRING_DESC_F_NEXT) {
+				if (inhdr_desc->next >= max_n_descs)
+					return -1;
+				inhdr_desc = &head[inhdr_desc->next];
+			}
+			if (inhdr_desc->len != sizeof(*inhdr))
+				return -1;
+			inhdr = IOVA_TO_VVA(struct virtio_crypto_inhdr *,
+					vc_req, inhdr_desc->addr, &dlen,
+					VHOST_ACCESS_WO);
+			if (unlikely(!inhdr || dlen != inhdr_desc->len))
+				return -1;
+			inhdr->status = VIRTIO_CRYPTO_ERR;
+			return -1;
+		}
+	}
 
-	req = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);
-	if (unlikely(req == NULL)) {
-		switch (vcrypto->option) {
-		case RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:
+	/* copy descriptors to local variable */
+	for (i = 0; i < max_n_descs; i++) {
+		desc->addr = src_desc->addr;
+		desc->len = src_desc->len;
+		desc->flags = src_desc->flags;
+		desc++;
+		if (unlikely((src_desc->flags & VRING_DESC_F_NEXT) == 0))
+			break;
+		if (unlikely(src_desc->next >= max_n_descs)) {
 			err = VIRTIO_CRYPTO_BADMSG;
 			VC_LOG_ERR("Invalid descriptor");
 			goto error_exit;
-		case RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:
-			req = &tmp_req;
-			if (unlikely(copy_data(req, vc_req, &desc, sizeof(*req),
-					&nb_descs, vq->size) < 0)) {
-				err = VIRTIO_CRYPTO_BADMSG;
-				VC_LOG_ERR("Invalid descriptor");
-				goto error_exit;
-			}
-			break;
-		default:
-			err = VIRTIO_CRYPTO_ERR;
-			VC_LOG_ERR("Invalid option");
-			goto error_exit;
-		}
-	} else {
-		if (unlikely(move_desc(vc_req->head, &desc,
-				sizeof(*req), &nb_descs, vq->size) < 0)) {
-			VC_LOG_ERR("Incorrect descriptor");
-			goto error_exit;
 		}
+		src_desc = &head[src_desc->next];
+	}
+
+	vc_req->head = head;
+	vc_req->zero_copy = vcrypto->option;
+
+	nb_descs = desc - descs;
+	desc = descs;
+
+	if (unlikely(desc->len < sizeof(req))) {
+		err = VIRTIO_CRYPTO_BADMSG;
+		VC_LOG_ERR("Invalid descriptor");
+		goto error_exit;
 	}
 
-	switch (req->header.opcode) {
+	if (unlikely(copy_data(&req, vc_req, descs, &desc, sizeof(req),
+			max_n_descs) < 0)) {
+		err = VIRTIO_CRYPTO_BADMSG;
+		VC_LOG_ERR("Invalid descriptor");
+		goto error_exit;
+	}
+
+	/* desc is advanced by 1 now */
+	max_n_descs -= 1;
+
+	switch (req.header.opcode) {
 	case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
 	case VIRTIO_CRYPTO_CIPHER_DECRYPT:
-		session_id = req->header.session_id;
+		session_id = req.header.session_id;
 
 		/* one branch to avoid unnecessary table lookup */
 		if (vcrypto->cache_session_id != session_id) {
@@ -1241,19 +1293,19 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,
 			goto error_exit;
 		}
 
-		switch (req->u.sym_req.op_type) {
+		switch (req.u.sym_req.op_type) {
 		case VIRTIO_CRYPTO_SYM_OP_NONE:
 			err = VIRTIO_CRYPTO_NOTSUPP;
 			break;
 		case VIRTIO_CRYPTO_SYM_OP_CIPHER:
 			err = prepare_sym_cipher_op(vcrypto, op, vc_req,
-					&req->u.sym_req.u.cipher, desc,
-					&nb_descs, vq->size);
+					&req.u.sym_req.u.cipher, desc,
+					max_n_descs);
 			break;
 		case VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:
 			err = prepare_sym_chain_op(vcrypto, op, vc_req,
-					&req->u.sym_req.u.chain, desc,
-					&nb_descs, vq->size);
+					&req.u.sym_req.u.chain, desc,
+					max_n_descs);
 			break;
 		}
 		if (unlikely(err != 0)) {
@@ -1262,8 +1314,9 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,
 		}
 		break;
 	default:
+		err = VIRTIO_CRYPTO_ERR;
 		VC_LOG_ERR("Unsupported symmetric crypto request type %u",
-				req->header.opcode);
+				req.header.opcode);
 		goto error_exit;
 	}
 
@@ -1271,7 +1324,7 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,
 
 error_exit:
 
-	inhdr = reach_inhdr(vc_req, desc, &nb_descs, vq->size);
+	inhdr = reach_inhdr(vc_req, descs, max_n_descs);
 	if (likely(inhdr != NULL))
 		inhdr->status = (uint8_t)err;
 
@@ -1285,17 +1338,16 @@ vhost_crypto_finalize_one_request(struct rte_crypto_op *op,
 	struct rte_mbuf *m_src = op->sym->m_src;
 	struct rte_mbuf *m_dst = op->sym->m_dst;
 	struct vhost_crypto_data_req *vc_req = rte_mbuf_to_priv(m_src);
-	uint16_t desc_idx;
+	struct vhost_virtqueue *vq = vc_req->vq;
+	uint16_t used_idx = vc_req->desc_idx, desc_idx;
 
 	if (unlikely(!vc_req)) {
 		VC_LOG_ERR("Failed to retrieve vc_req");
 		return NULL;
 	}
 
-	if (old_vq && (vc_req->vq != old_vq))
-		return vc_req->vq;
-
-	desc_idx = vc_req->desc_idx;
+	if (old_vq && (vq != old_vq))
+		return vq;
 
 	if (unlikely(op->status != RTE_CRYPTO_OP_STATUS_SUCCESS))
 		vc_req->inhdr->status = VIRTIO_CRYPTO_ERR;
@@ -1304,8 +1356,9 @@ vhost_crypto_finalize_one_request(struct rte_crypto_op *op,
 			write_back_data(vc_req);
 	}
 
-	vc_req->vq->used->ring[desc_idx].id = desc_idx;
-	vc_req->vq->used->ring[desc_idx].len = vc_req->len;
+	desc_idx = vq->avail->ring[used_idx];
+	vq->used->ring[desc_idx].id = vq->avail->ring[desc_idx];
+	vq->used->ring[desc_idx].len = vc_req->len;
 
 	rte_mempool_put(m_src->pool, (void *)m_src);
 
@@ -1403,7 +1456,7 @@ rte_vhost_crypto_create(int vid, uint8_t cryptodev_id,
 	vcrypto->mbuf_pool = rte_pktmbuf_pool_create(name,
 			VHOST_CRYPTO_MBUF_POOL_SIZE, 512,
 			sizeof(struct vhost_crypto_data_req),
-			RTE_MBUF_DEFAULT_DATAROOM * 2 + RTE_PKTMBUF_HEADROOM,
+			VHOST_CRYPTO_MAX_DATA_SIZE + RTE_PKTMBUF_HEADROOM,
 			rte_socket_id());
 	if (!vcrypto->mbuf_pool) {
 		VC_LOG_ERR("Failed to creath mbuf pool");
@@ -1529,6 +1582,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
 		struct rte_crypto_op **ops, uint16_t nb_ops)
 {
 	struct rte_mbuf *mbufs[VHOST_CRYPTO_MAX_BURST_SIZE * 2];
+	struct vhost_crypto_desc descs[VHOST_CRYPTO_MAX_N_DESC];
 	struct virtio_net *dev = get_device(vid);
 	struct vhost_crypto *vcrypto;
 	struct vhost_virtqueue *vq;
@@ -1539,18 +1593,18 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
 
 	if (unlikely(dev == NULL)) {
 		VC_LOG_ERR("Invalid vid %i", vid);
-		return -EINVAL;
+		return 0;
 	}
 
 	if (unlikely(qid >= VHOST_MAX_QUEUE_PAIRS)) {
 		VC_LOG_ERR("Invalid qid %u", qid);
-		return -EINVAL;
+		return 0;
 	}
 
 	vcrypto = (struct vhost_crypto *)dev->extern_data;
 	if (unlikely(vcrypto == NULL)) {
 		VC_LOG_ERR("Cannot find required data, is it initialized?");
-		return -ENOENT;
+		return 0;
 	}
 
 	vq = dev->virtqueue[qid];
@@ -1572,7 +1626,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
 		if (unlikely(rte_mempool_get_bulk(vcrypto->mbuf_pool,
 				(void **)mbufs, count * 2) < 0)) {
 			VC_LOG_ERR("Insufficient memory");
-			return -ENOMEM;
+			return 0;
 		}
 
 		for (i = 0; i < count; i++) {
@@ -1587,7 +1641,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
 			op->sym->m_dst->data_off = 0;
 
 			if (unlikely(vhost_crypto_process_one_req(vcrypto, vq,
-					op, head, desc_idx) < 0))
+					op, head, descs, used_idx) < 0))
 				break;
 		}
 
@@ -1602,7 +1656,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
 		if (unlikely(rte_mempool_get_bulk(vcrypto->mbuf_pool,
 				(void **)mbufs, count) < 0)) {
 			VC_LOG_ERR("Insufficient memory");
-			return -ENOMEM;
+			return 0;
 		}
 
 		for (i = 0; i < count; i++) {
@@ -1616,7 +1670,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,
 			op->sym->m_src->data_off = 0;
 
 			if (unlikely(vhost_crypto_process_one_req(vcrypto, vq,
-					op, head, desc_idx) < 0))
+					op, head, descs, desc_idx) < 0))
 				break;
 		}
 
diff --git a/dpdk/lib/librte_vhost/vhost_user.c b/dpdk/lib/librte_vhost/vhost_user.c
index 0cfb8b792b..dc1e312d84 100644
--- a/dpdk/lib/librte_vhost/vhost_user.c
+++ b/dpdk/lib/librte_vhost/vhost_user.c
@@ -97,8 +97,15 @@ close_msg_fds(struct VhostUserMsg *msg)
 {
 	int i;
 
-	for (i = 0; i < msg->fd_num; i++)
-		close(msg->fds[i]);
+	for (i = 0; i < msg->fd_num; i++) {
+		int fd = msg->fds[i];
+
+		if (fd == -1)
+			continue;
+
+		msg->fds[i] = -1;
+		close(fd);
+	}
 }
 
 /*
@@ -206,7 +213,7 @@ vhost_backend_cleanup(struct virtio_net *dev)
 			dev->inflight_info->addr = NULL;
 		}
 
-		if (dev->inflight_info->fd > 0) {
+		if (dev->inflight_info->fd >= 0) {
 			close(dev->inflight_info->fd);
 			dev->inflight_info->fd = -1;
 		}
@@ -350,7 +357,9 @@ vhost_user_set_features(struct virtio_net **pdev, struct VhostUserMsg *msg,
 
 	dev->features = features;
 	if (dev->features &
-		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
+		((1ULL << VIRTIO_NET_F_MRG_RXBUF) |
+		 (1ULL << VIRTIO_F_VERSION_1) |
+		 (1ULL << VIRTIO_F_RING_PACKED))) {
 		dev->vhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
 	} else {
 		dev->vhost_hlen = sizeof(struct virtio_net_hdr);
@@ -656,13 +665,11 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
 {
 	if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) {
 		uint64_t vva;
-		uint64_t req_size = *size;
 
-		vva = vhost_user_iotlb_cache_find(vq, ra,
+		vhost_user_iotlb_rd_lock(vq);
+		vva = vhost_iova_to_vva(dev, vq, ra,
 					size, VHOST_ACCESS_RW);
-		if (req_size != *size)
-			vhost_user_iotlb_miss(dev, (ra + *size),
-					      VHOST_ACCESS_RW);
+		vhost_user_iotlb_rd_unlock(vq);
 
 		return vva;
 	}
@@ -670,37 +677,16 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
 	return qva_to_vva(dev, ra, size);
 }
 
-/*
- * Converts vring log address to GPA
- * If IOMMU is enabled, the log address is IOVA
- * If IOMMU not enabled, the log address is already GPA
- */
 static uint64_t
-translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq,
-		uint64_t log_addr)
+log_addr_to_gpa(struct virtio_net *dev, struct vhost_virtqueue *vq)
 {
-	if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) {
-		const uint64_t exp_size = sizeof(struct vring_used) +
-			sizeof(struct vring_used_elem) * vq->size;
-		uint64_t hva, gpa;
-		uint64_t size = exp_size;
-
-		hva = vhost_iova_to_vva(dev, vq, log_addr,
-					&size, VHOST_ACCESS_RW);
-		if (size != exp_size)
-			return 0;
+	uint64_t log_gpa;
 
-		gpa = hva_to_gpa(dev, hva, exp_size);
-		if (!gpa) {
-			RTE_LOG(ERR, VHOST_CONFIG,
-				"VQ: Failed to find GPA for log_addr: 0x%" PRIx64 " hva: 0x%" PRIx64 "\n",
-				log_addr, hva);
-			return 0;
-		}
-		return gpa;
+	vhost_user_iotlb_rd_lock(vq);
+	log_gpa = translate_log_addr(dev, vq, vq->ring_addrs.log_guest_addr);
+	vhost_user_iotlb_rd_unlock(vq);
 
-	} else
-		return log_addr;
+	return log_gpa;
 }
 
 static struct virtio_net *
@@ -712,7 +698,7 @@ translate_ring_addresses(struct virtio_net *dev, int vq_index)
 
 	if (addr->flags & (1 << VHOST_VRING_F_LOG)) {
 		vq->log_guest_addr =
-			translate_log_addr(dev, vq, addr->log_guest_addr);
+			log_addr_to_gpa(dev, vq);
 		if (vq->log_guest_addr == 0) {
 			RTE_LOG(DEBUG, VHOST_CONFIG,
 				"(%d) failed to map log_guest_addr.\n",
@@ -1053,7 +1039,6 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 	uint64_t alignment;
 	uint32_t i;
 	int populate;
-	int fd;
 
 	if (validate_msg_fds(msg, memory->nregions) != 0)
 		return RTE_VHOST_MSG_RESULT_ERR;
@@ -1061,7 +1046,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 	if (memory->nregions > VHOST_MEMORY_MAX_NREGIONS) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"too many memory regions (%u)\n", memory->nregions);
-		return RTE_VHOST_MSG_RESULT_ERR;
+		goto close_msg_fds;
 	}
 
 	if (dev->mem && !vhost_memory_changed(memory, dev->mem)) {
@@ -1094,7 +1079,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 				"(%d) failed to allocate memory "
 				"for dev->guest_pages\n",
 				dev->vid);
-			return RTE_VHOST_MSG_RESULT_ERR;
+			goto close_msg_fds;
 		}
 	}
 
@@ -1104,18 +1089,23 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"(%d) failed to allocate memory for dev->mem\n",
 			dev->vid);
-		return RTE_VHOST_MSG_RESULT_ERR;
+		goto free_guest_pages;
 	}
 	dev->mem->nregions = memory->nregions;
 
 	for (i = 0; i < memory->nregions; i++) {
-		fd  = msg->fds[i];
 		reg = &dev->mem->regions[i];
 
 		reg->guest_phys_addr = memory->regions[i].guest_phys_addr;
 		reg->guest_user_addr = memory->regions[i].userspace_addr;
 		reg->size            = memory->regions[i].memory_size;
-		reg->fd              = fd;
+		reg->fd              = msg->fds[i];
+
+		/*
+		 * Assign invalid file descriptor value to avoid double
+		 * closing on error path.
+		 */
+		msg->fds[i] = -1;
 
 		mmap_offset = memory->regions[i].mmap_offset;
 
@@ -1125,7 +1115,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 				"mmap_offset (%#"PRIx64") and memory_size "
 				"(%#"PRIx64") overflow\n",
 				mmap_offset, reg->size);
-			goto err_mmap;
+			goto free_mem_table;
 		}
 
 		mmap_size = reg->size + mmap_offset;
@@ -1138,22 +1128,37 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 		 * to avoid failure, make sure in caller to keep length
 		 * aligned.
 		 */
-		alignment = get_blk_size(fd);
+		alignment = get_blk_size(reg->fd);
 		if (alignment == (uint64_t)-1) {
 			RTE_LOG(ERR, VHOST_CONFIG,
 				"couldn't get hugepage size through fstat\n");
-			goto err_mmap;
+			goto free_mem_table;
 		}
 		mmap_size = RTE_ALIGN_CEIL(mmap_size, alignment);
+		if (mmap_size == 0) {
+			/*
+			 * It could happen if initial mmap_size + alignment
+			 * overflows the sizeof uint64, which could happen if
+			 * either mmap_size or alignment value is wrong.
+			 *
+			 * mmap() kernel implementation would return an error,
+			 * but better catch it before and provide useful info
+			 * in the logs.
+			 */
+			RTE_LOG(ERR, VHOST_CONFIG, "mmap size (0x%" PRIx64 ") "
+					"or alignment (0x%" PRIx64 ") is invalid\n",
+					reg->size + mmap_offset, alignment);
+			goto free_mem_table;
+		}
 
 		populate = (dev->dequeue_zero_copy) ? MAP_POPULATE : 0;
 		mmap_addr = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
-				 MAP_SHARED | populate, fd, 0);
+				 MAP_SHARED | populate, reg->fd, 0);
 
 		if (mmap_addr == MAP_FAILED) {
 			RTE_LOG(ERR, VHOST_CONFIG,
 				"mmap region %u failed.\n", i);
-			goto err_mmap;
+			goto free_mem_table;
 		}
 
 		reg->mmap_addr = mmap_addr;
@@ -1166,7 +1171,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 				RTE_LOG(ERR, VHOST_CONFIG,
 					"adding guest pages to region %u failed.\n",
 					i);
-				goto err_mmap;
+				goto free_mem_table;
 			}
 
 		RTE_LOG(INFO, VHOST_CONFIG,
@@ -1209,17 +1214,17 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 		if (read_vhost_message(main_fd, &ack_msg) <= 0) {
 			RTE_LOG(ERR, VHOST_CONFIG,
 				"Failed to read qemu ack on postcopy set-mem-table\n");
-			goto err_mmap;
+			goto free_mem_table;
 		}
 
 		if (validate_msg_fds(&ack_msg, 0) != 0)
-			goto err_mmap;
+			goto free_mem_table;
 
 		if (ack_msg.request.master != VHOST_USER_SET_MEM_TABLE) {
 			RTE_LOG(ERR, VHOST_CONFIG,
 				"Bad qemu ack on postcopy set-mem-table (%d)\n",
 				ack_msg.request.master);
-			goto err_mmap;
+			goto free_mem_table;
 		}
 
 		/* Now userfault register and we can use the memory */
@@ -1243,7 +1248,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 					"Failed to register ufd for region %d: (ufd = %d) %s\n",
 					i, dev->postcopy_ufd,
 					strerror(errno));
-				goto err_mmap;
+				goto free_mem_table;
 			}
 			RTE_LOG(INFO, VHOST_CONFIG,
 				"\t userfaultfd registered for range : "
@@ -1252,7 +1257,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 				(uint64_t)reg_struct.range.start +
 				(uint64_t)reg_struct.range.len - 1);
 #else
-			goto err_mmap;
+			goto free_mem_table;
 #endif
 		}
 	}
@@ -1271,7 +1276,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 			dev = translate_ring_addresses(dev, i);
 			if (!dev) {
 				dev = *pdev;
-				goto err_mmap;
+				goto free_mem_table;
 			}
 
 			*pdev = dev;
@@ -1282,10 +1287,15 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg,
 
 	return RTE_VHOST_MSG_RESULT_OK;
 
-err_mmap:
+free_mem_table:
 	free_mem_region(dev);
 	rte_free(dev->mem);
 	dev->mem = NULL;
+free_guest_pages:
+	rte_free(dev->guest_pages);
+	dev->guest_pages = NULL;
+close_msg_fds:
+	close_msg_fds(msg);
 	return RTE_VHOST_MSG_RESULT_ERR;
 }
 
@@ -1298,7 +1308,8 @@ vq_is_ready(struct virtio_net *dev, struct vhost_virtqueue *vq)
 		return false;
 
 	if (vq_is_packed(dev))
-		rings_ok = !!vq->desc_packed;
+		rings_ok = vq->desc_packed && vq->driver_event &&
+			vq->device_event;
 	else
 		rings_ok = vq->desc && vq->avail && vq->used;
 
@@ -1415,6 +1426,7 @@ vhost_user_get_inflight_fd(struct virtio_net **pdev,
 				"failed to alloc dev inflight area\n");
 			return RTE_VHOST_MSG_RESULT_ERR;
 		}
+		dev->inflight_info->fd = -1;
 	}
 
 	num_queues = msg->payload.inflight.num_queues;
@@ -1440,6 +1452,16 @@ vhost_user_get_inflight_fd(struct virtio_net **pdev,
 	}
 	memset(addr, 0, mmap_size);
 
+	if (dev->inflight_info->addr) {
+		munmap(dev->inflight_info->addr, dev->inflight_info->size);
+		dev->inflight_info->addr = NULL;
+	}
+
+	if (dev->inflight_info->fd >= 0) {
+		close(dev->inflight_info->fd);
+		dev->inflight_info->fd = -1;
+	}
+
 	dev->inflight_info->addr = addr;
 	dev->inflight_info->size = msg->payload.inflight.mmap_size = mmap_size;
 	dev->inflight_info->fd = msg->fds[0] = fd;
@@ -1522,10 +1544,13 @@ vhost_user_set_inflight_fd(struct virtio_net **pdev, VhostUserMsg *msg,
 				"failed to alloc dev inflight area\n");
 			return RTE_VHOST_MSG_RESULT_ERR;
 		}
+		dev->inflight_info->fd = -1;
 	}
 
-	if (dev->inflight_info->addr)
+	if (dev->inflight_info->addr) {
 		munmap(dev->inflight_info->addr, dev->inflight_info->size);
+		dev->inflight_info->addr = NULL;
+	}
 
 	addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
 		    fd, mmap_offset);
@@ -1534,8 +1559,10 @@ vhost_user_set_inflight_fd(struct virtio_net **pdev, VhostUserMsg *msg,
 		return RTE_VHOST_MSG_RESULT_ERR;
 	}
 
-	if (dev->inflight_info->fd)
+	if (dev->inflight_info->fd >= 0) {
 		close(dev->inflight_info->fd);
+		dev->inflight_info->fd = -1;
+	}
 
 	dev->inflight_info->fd = fd;
 	dev->inflight_info->addr = addr;
@@ -1629,8 +1656,11 @@ vhost_check_queue_inflights_split(struct virtio_net *dev,
 	    (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
 		return RTE_VHOST_MSG_RESULT_OK;
 
+	/* The frontend may still not support the inflight feature
+	 * although we negotiate the protocol feature.
+	 */
 	if ((!vq->inflight_split))
-		return RTE_VHOST_MSG_RESULT_ERR;
+		return RTE_VHOST_MSG_RESULT_OK;
 
 	if (!vq->inflight_split->version) {
 		vq->inflight_split->version = INFLIGHT_VERSION;
@@ -1710,8 +1740,11 @@ vhost_check_queue_inflights_packed(struct virtio_net *dev,
 	    (1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD)))
 		return RTE_VHOST_MSG_RESULT_OK;
 
+	/* The frontend may still not support the inflight feature
+	 * although we negotiate the protocol feature.
+	 */
 	if ((!vq->inflight_packed))
-		return RTE_VHOST_MSG_RESULT_ERR;
+		return RTE_VHOST_MSG_RESULT_OK;
 
 	if (!vq->inflight_packed->version) {
 		vq->inflight_packed->version = INFLIGHT_VERSION;
@@ -1811,8 +1844,12 @@ vhost_user_set_vring_kick(struct virtio_net **pdev, struct VhostUserMsg *msg,
 
 	/* Interpret ring addresses only when ring is started. */
 	dev = translate_ring_addresses(dev, file.index);
-	if (!dev)
+	if (!dev) {
+		if (file.fd != VIRTIO_INVALID_EVENTFD)
+			close(file.fd);
+
 		return RTE_VHOST_MSG_RESULT_ERR;
+	}
 
 	*pdev = dev;
 
@@ -1857,6 +1894,7 @@ free_zmbufs(struct vhost_virtqueue *vq)
 	drain_zmbuf_list(vq);
 
 	rte_free(vq->zmbufs);
+	vq->zmbufs = NULL;
 }
 
 /*
@@ -2054,18 +2092,18 @@ vhost_user_set_log_base(struct virtio_net **pdev, struct VhostUserMsg *msg,
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"invalid log base msg size: %"PRId32" != %d\n",
 			msg->size, (int)sizeof(VhostUserLog));
-		return RTE_VHOST_MSG_RESULT_ERR;
+		goto close_msg_fds;
 	}
 
 	size = msg->payload.log.mmap_size;
 	off  = msg->payload.log.mmap_offset;
 
-	/* Don't allow mmap_offset to point outside the mmap region */
-	if (off > size) {
+	/* Check for mmap size and offset overflow. */
+	if (off >= -size) {
 		RTE_LOG(ERR, VHOST_CONFIG,
-			"log offset %#"PRIx64" exceeds log size %#"PRIx64"\n",
+			"log offset %#"PRIx64" and log size %#"PRIx64" overflow\n",
 			off, size);
-		return RTE_VHOST_MSG_RESULT_ERR;
+		goto close_msg_fds;
 	}
 
 	RTE_LOG(INFO, VHOST_CONFIG,
@@ -2102,6 +2140,10 @@ vhost_user_set_log_base(struct virtio_net **pdev, struct VhostUserMsg *msg,
 	msg->fd_num = 0;
 
 	return RTE_VHOST_MSG_RESULT_REPLY;
+
+close_msg_fds:
+	close_msg_fds(msg);
+	return RTE_VHOST_MSG_RESULT_ERR;
 }
 
 static int vhost_user_set_log_fd(struct virtio_net **pdev __rte_unused,
@@ -2229,6 +2271,13 @@ is_vring_iotlb_split(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg)
 	if (ra->used_user_addr < end && (ra->used_user_addr + len) > start)
 		return 1;
 
+	if (ra->flags & (1 << VHOST_VRING_F_LOG)) {
+		len = sizeof(uint64_t);
+		if (ra->log_guest_addr < end &&
+		    (ra->log_guest_addr + len) > start)
+			return 1;
+	}
+
 	return 0;
 }
 
@@ -2254,6 +2303,13 @@ is_vring_iotlb_packed(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg)
 	if (ra->used_user_addr < end && (ra->used_user_addr + len) > start)
 		return 1;
 
+	if (ra->flags & (1 << VHOST_VRING_F_LOG)) {
+		len = sizeof(uint64_t);
+		if (ra->log_guest_addr < end &&
+		    (ra->log_guest_addr + len) > start)
+			return 1;
+	}
+
 	return 0;
 }
 
@@ -2440,8 +2496,13 @@ read_vhost_message(int sockfd, struct VhostUserMsg *msg)
 
 	ret = read_fd_message(sockfd, (char *)msg, VHOST_USER_HDR_SIZE,
 		msg->fds, VHOST_MEMORY_MAX_NREGIONS, &msg->fd_num);
-	if (ret <= 0)
+	if (ret <= 0) {
 		return ret;
+	} else if (ret != VHOST_USER_HDR_SIZE) {
+		RTE_LOG(ERR, VHOST_CONFIG, "Unexpected header size read\n");
+		close_msg_fds(msg);
+		return -1;
+	}
 
 	if (msg->size) {
 		if (msg->size > sizeof(msg->payload)) {
@@ -2508,7 +2569,7 @@ static int
 vhost_user_check_and_alloc_queue_pair(struct virtio_net *dev,
 			struct VhostUserMsg *msg)
 {
-	uint16_t vring_idx;
+	uint32_t vring_idx;
 
 	switch (msg->request.master) {
 	case VHOST_USER_SET_VRING_KICK:
@@ -2758,7 +2819,7 @@ vhost_user_msg_handler(int vid, int fd)
 		return -1;
 	}
 
-	if (!(dev->flags & VIRTIO_DEV_RUNNING) && virtio_is_ready(dev)) {
+	if (!(dev->flags & VIRTIO_DEV_READY) && virtio_is_ready(dev)) {
 		dev->flags |= VIRTIO_DEV_READY;
 
 		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
@@ -2794,11 +2855,19 @@ static int process_slave_message_reply(struct virtio_net *dev,
 	if ((msg->flags & VHOST_USER_NEED_REPLY) == 0)
 		return 0;
 
-	if (read_vhost_message(dev->slave_req_fd, &msg_reply) < 0) {
+	ret = read_vhost_message(dev->slave_req_fd, &msg_reply);
+	if (ret <= 0) {
+		if (ret < 0)
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"vhost read slave message reply failed\n");
+		else
+			RTE_LOG(INFO, VHOST_CONFIG,
+				"vhost peer closed\n");
 		ret = -1;
 		goto out;
 	}
 
+	ret = 0;
 	if (msg_reply.request.slave != msg->request.slave) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"Received unexpected msg type (%u), expected %u\n",
diff --git a/dpdk/lib/librte_vhost/virtio_net.c b/dpdk/lib/librte_vhost/virtio_net.c
index 21c311732a..f397e9a13a 100644
--- a/dpdk/lib/librte_vhost/virtio_net.c
+++ b/dpdk/lib/librte_vhost/virtio_net.c
@@ -43,6 +43,36 @@ is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
 	return (is_tx ^ (idx & 1)) == 0 && idx < nr_vring;
 }
 
+static inline void
+do_data_copy_enqueue(struct virtio_net *dev, struct vhost_virtqueue *vq)
+{
+	struct batch_copy_elem *elem = vq->batch_copy_elems;
+	uint16_t count = vq->batch_copy_nb_elems;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		rte_memcpy(elem[i].dst, elem[i].src, elem[i].len);
+		vhost_log_cache_write_iova(dev, vq, elem[i].log_addr,
+					   elem[i].len);
+		PRINT_PACKET(dev, (uintptr_t)elem[i].dst, elem[i].len, 0);
+	}
+
+	vq->batch_copy_nb_elems = 0;
+}
+
+static inline void
+do_data_copy_dequeue(struct vhost_virtqueue *vq)
+{
+	struct batch_copy_elem *elem = vq->batch_copy_elems;
+	uint16_t count = vq->batch_copy_nb_elems;
+	int i;
+
+	for (i = 0; i < count; i++)
+		rte_memcpy(elem[i].dst, elem[i].src, elem[i].len);
+
+	vq->batch_copy_nb_elems = 0;
+}
+
 static __rte_always_inline void
 do_flush_shadow_used_ring_split(struct virtio_net *dev,
 			struct vhost_virtqueue *vq,
@@ -186,6 +216,11 @@ vhost_flush_enqueue_batch_packed(struct virtio_net *dev,
 	uint16_t i;
 	uint16_t flags;
 
+	if (vq->shadow_used_idx) {
+		do_data_copy_enqueue(dev, vq);
+		vhost_flush_enqueue_shadow_packed(dev, vq);
+	}
+
 	flags = PACKED_DESC_ENQUEUE_USED_FLAG(vq->used_wrap_counter);
 
 	vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
@@ -325,36 +360,6 @@ vhost_shadow_dequeue_single_packed_inorder(struct vhost_virtqueue *vq,
 	vq_inc_last_used_packed(vq, count);
 }
 
-static inline void
-do_data_copy_enqueue(struct virtio_net *dev, struct vhost_virtqueue *vq)
-{
-	struct batch_copy_elem *elem = vq->batch_copy_elems;
-	uint16_t count = vq->batch_copy_nb_elems;
-	int i;
-
-	for (i = 0; i < count; i++) {
-		rte_memcpy(elem[i].dst, elem[i].src, elem[i].len);
-		vhost_log_cache_write_iova(dev, vq, elem[i].log_addr,
-					   elem[i].len);
-		PRINT_PACKET(dev, (uintptr_t)elem[i].dst, elem[i].len, 0);
-	}
-
-	vq->batch_copy_nb_elems = 0;
-}
-
-static inline void
-do_data_copy_dequeue(struct vhost_virtqueue *vq)
-{
-	struct batch_copy_elem *elem = vq->batch_copy_elems;
-	uint16_t count = vq->batch_copy_nb_elems;
-	int i;
-
-	for (i = 0; i < count; i++)
-		rte_memcpy(elem[i].dst, elem[i].src, elem[i].len);
-
-	vq->batch_copy_nb_elems = 0;
-}
-
 static __rte_always_inline void
 vhost_shadow_enqueue_single_packed(struct virtio_net *dev,
 				   struct vhost_virtqueue *vq,
@@ -382,25 +387,6 @@ vhost_shadow_enqueue_single_packed(struct virtio_net *dev,
 	}
 }
 
-static __rte_always_inline void
-vhost_flush_dequeue_packed(struct virtio_net *dev,
-			   struct vhost_virtqueue *vq)
-{
-	int shadow_count;
-	if (!vq->shadow_used_idx)
-		return;
-
-	shadow_count = vq->last_used_idx - vq->shadow_last_used_idx;
-	if (shadow_count <= 0)
-		shadow_count += vq->size;
-
-	if ((uint32_t)shadow_count >= (vq->size - MAX_PKT_BURST)) {
-		do_data_copy_dequeue(vq);
-		vhost_flush_dequeue_shadow_packed(dev, vq);
-		vhost_vring_call_packed(dev, vq);
-	}
-}
-
 /* avoid write operation when necessary, to lessen cache issues */
 #define ASSIGN_UNLESS_EQUAL(var, val) do {	\
 	if ((var) != (val))			\
@@ -1086,6 +1072,8 @@ virtio_dev_rx_batch_packed(struct virtio_net *dev,
 						  VHOST_ACCESS_RW);
 
 	vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
+		if (unlikely(!desc_addrs[i]))
+			return -1;
 		if (unlikely(lens[i] != descs[avail_idx + i].len))
 			return -1;
 	}
@@ -1607,16 +1595,8 @@ virtio_dev_extbuf_alloc(struct rte_mbuf *pkt, uint32_t size)
 	rte_iova_t iova;
 	void *buf;
 
-	/* Try to use pkt buffer to store shinfo to reduce the amount of memory
-	 * required, otherwise store shinfo in the new buffer.
-	 */
-	if (rte_pktmbuf_tailroom(pkt) >= sizeof(*shinfo))
-		shinfo = rte_pktmbuf_mtod(pkt,
-					  struct rte_mbuf_ext_shared_info *);
-	else {
-		total_len += sizeof(*shinfo) + sizeof(uintptr_t);
-		total_len = RTE_ALIGN_CEIL(total_len, sizeof(uintptr_t));
-	}
+	total_len += sizeof(*shinfo) + sizeof(uintptr_t);
+	total_len = RTE_ALIGN_CEIL(total_len, sizeof(uintptr_t));
 
 	if (unlikely(total_len > UINT16_MAX))
 		return -ENOSPC;
@@ -1627,18 +1607,12 @@ virtio_dev_extbuf_alloc(struct rte_mbuf *pkt, uint32_t size)
 		return -ENOMEM;
 
 	/* Initialize shinfo */
-	if (shinfo) {
-		shinfo->free_cb = virtio_dev_extbuf_free;
-		shinfo->fcb_opaque = buf;
-		rte_mbuf_ext_refcnt_set(shinfo, 1);
-	} else {
-		shinfo = rte_pktmbuf_ext_shinfo_init_helper(buf, &buf_len,
-					      virtio_dev_extbuf_free, buf);
-		if (unlikely(shinfo == NULL)) {
-			rte_free(buf);
-			RTE_LOG(ERR, VHOST_DATA, "Failed to init shinfo\n");
-			return -1;
-		}
+	shinfo = rte_pktmbuf_ext_shinfo_init_helper(buf, &buf_len,
+						virtio_dev_extbuf_free, buf);
+	if (unlikely(shinfo == NULL)) {
+		rte_free(buf);
+		RTE_LOG(ERR, VHOST_DATA, "Failed to init shinfo\n");
+		return -1;
 	}
 
 	iova = rte_malloc_virt2iova(buf);
@@ -1688,6 +1662,8 @@ virtio_dev_tx_split(struct virtio_net *dev, struct vhost_virtqueue *vq,
 {
 	uint16_t i;
 	uint16_t free_entries;
+	uint16_t dropped = 0;
+	static bool allocerr_warned;
 
 	if (unlikely(dev->dequeue_zero_copy)) {
 		struct zcopy_mbuf *zmbuf, *next;
@@ -1751,13 +1727,35 @@ virtio_dev_tx_split(struct virtio_net *dev, struct vhost_virtqueue *vq,
 			update_shadow_used_ring_split(vq, head_idx, 0);
 
 		pkts[i] = virtio_dev_pktmbuf_alloc(dev, mbuf_pool, buf_len);
-		if (unlikely(pkts[i] == NULL))
+		if (unlikely(pkts[i] == NULL)) {
+			/*
+			 * mbuf allocation fails for jumbo packets when external
+			 * buffer allocation is not allowed and linear buffer
+			 * is required. Drop this packet.
+			 */
+			if (!allocerr_warned) {
+				RTE_LOG(ERR, VHOST_DATA,
+					"Failed mbuf alloc of size %d from %s on %s.\n",
+					buf_len, mbuf_pool->name, dev->ifname);
+				allocerr_warned = true;
+			}
+			dropped += 1;
+			i++;
 			break;
+		}
 
 		err = copy_desc_to_mbuf(dev, vq, buf_vec, nr_vec, pkts[i],
 				mbuf_pool);
 		if (unlikely(err)) {
 			rte_pktmbuf_free(pkts[i]);
+			if (!allocerr_warned) {
+				RTE_LOG(ERR, VHOST_DATA,
+					"Failed to copy desc to mbuf on %s.\n",
+					dev->ifname);
+				allocerr_warned = true;
+			}
+			dropped += 1;
+			i++;
 			break;
 		}
 
@@ -1767,6 +1765,8 @@ virtio_dev_tx_split(struct virtio_net *dev, struct vhost_virtqueue *vq,
 			zmbuf = get_zmbuf(vq);
 			if (!zmbuf) {
 				rte_pktmbuf_free(pkts[i]);
+				dropped += 1;
+				i++;
 				break;
 			}
 			zmbuf->mbuf = pkts[i];
@@ -1796,7 +1796,7 @@ virtio_dev_tx_split(struct virtio_net *dev, struct vhost_virtqueue *vq,
 		}
 	}
 
-	return i;
+	return (i - dropped);
 }
 
 static __rte_always_inline int
@@ -1810,7 +1810,6 @@ vhost_reserve_avail_batch_packed(struct virtio_net *dev,
 {
 	bool wrap = vq->avail_wrap_counter;
 	struct vring_packed_desc *descs = vq->desc_packed;
-	struct virtio_net_hdr *hdr;
 	uint64_t lens[PACKED_BATCH_SIZE];
 	uint64_t buf_lens[PACKED_BATCH_SIZE];
 	uint32_t buf_offset = dev->vhost_hlen;
@@ -1841,6 +1840,8 @@ vhost_reserve_avail_batch_packed(struct virtio_net *dev,
 	}
 
 	vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
+		if (unlikely(!desc_addrs[i]))
+			return -1;
 		if (unlikely((lens[i] != descs[avail_idx + i].len)))
 			return -1;
 	}
@@ -1865,13 +1866,6 @@ vhost_reserve_avail_batch_packed(struct virtio_net *dev,
 		ids[i] = descs[avail_idx + i].id;
 	}
 
-	if (virtio_net_with_host_offload(dev)) {
-		vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
-			hdr = (struct virtio_net_hdr *)(desc_addrs[i]);
-			vhost_dequeue_offload(hdr, pkts[i]);
-		}
-	}
-
 	return 0;
 
 free_buf:
@@ -1889,6 +1883,7 @@ virtio_dev_tx_batch_packed(struct virtio_net *dev,
 {
 	uint16_t avail_idx = vq->last_avail_idx;
 	uint32_t buf_offset = dev->vhost_hlen;
+	struct virtio_net_hdr *hdr;
 	uintptr_t desc_addrs[PACKED_BATCH_SIZE];
 	uint16_t ids[PACKED_BATCH_SIZE];
 	uint16_t i;
@@ -1905,6 +1900,13 @@ virtio_dev_tx_batch_packed(struct virtio_net *dev,
 			   (void *)(uintptr_t)(desc_addrs[i] + buf_offset),
 			   pkts[i]->pkt_len);
 
+	if (virtio_net_with_host_offload(dev)) {
+		vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
+			hdr = (struct virtio_net_hdr *)(desc_addrs[i]);
+			vhost_dequeue_offload(hdr, pkts[i]);
+		}
+	}
+
 	if (virtio_net_is_inorder(dev))
 		vhost_shadow_dequeue_batch_packed_inorder(vq,
 			ids[PACKED_BATCH_SIZE - 1]);
@@ -1928,6 +1930,7 @@ vhost_dequeue_single_packed(struct virtio_net *dev,
 	uint32_t buf_len;
 	uint16_t nr_vec = 0;
 	int err;
+	static bool allocerr_warned;
 
 	if (unlikely(fill_vec_buf_packed(dev, vq,
 					 vq->last_avail_idx, desc_count,
@@ -1938,14 +1941,24 @@ vhost_dequeue_single_packed(struct virtio_net *dev,
 
 	*pkts = virtio_dev_pktmbuf_alloc(dev, mbuf_pool, buf_len);
 	if (unlikely(*pkts == NULL)) {
-		RTE_LOG(ERR, VHOST_DATA,
-			"Failed to allocate memory for mbuf.\n");
+		if (!allocerr_warned) {
+			RTE_LOG(ERR, VHOST_DATA,
+				"Failed mbuf alloc of size %d from %s on %s.\n",
+				buf_len, mbuf_pool->name, dev->ifname);
+			allocerr_warned = true;
+		}
 		return -1;
 	}
 
 	err = copy_desc_to_mbuf(dev, vq, buf_vec, nr_vec, *pkts,
 				mbuf_pool);
 	if (unlikely(err)) {
+		if (!allocerr_warned) {
+			RTE_LOG(ERR, VHOST_DATA,
+				"Failed to copy desc to mbuf on %s.\n",
+				dev->ifname);
+			allocerr_warned = true;
+		}
 		rte_pktmbuf_free(*pkts);
 		return -1;
 	}
@@ -1960,21 +1973,24 @@ virtio_dev_tx_single_packed(struct virtio_net *dev,
 			    struct rte_mbuf **pkts)
 {
 
-	uint16_t buf_id, desc_count;
+	uint16_t buf_id, desc_count = 0;
+	int ret;
 
-	if (vhost_dequeue_single_packed(dev, vq, mbuf_pool, pkts, &buf_id,
-					&desc_count))
-		return -1;
+	ret = vhost_dequeue_single_packed(dev, vq, mbuf_pool, pkts, &buf_id,
+					&desc_count);
 
-	if (virtio_net_is_inorder(dev))
-		vhost_shadow_dequeue_single_packed_inorder(vq, buf_id,
-							   desc_count);
-	else
-		vhost_shadow_dequeue_single_packed(vq, buf_id, desc_count);
+	if (likely(desc_count > 0)) {
+		if (virtio_net_is_inorder(dev))
+			vhost_shadow_dequeue_single_packed_inorder(vq, buf_id,
+								   desc_count);
+		else
+			vhost_shadow_dequeue_single_packed(vq, buf_id,
+					desc_count);
 
-	vq_inc_last_avail_packed(vq, desc_count);
+		vq_inc_last_avail_packed(vq, desc_count);
+	}
 
-	return 0;
+	return ret;
 }
 
 static __rte_always_inline int
@@ -2004,7 +2020,7 @@ virtio_dev_tx_batch_packed_zmbuf(struct virtio_net *dev,
 
 	vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
 		zmbufs[i]->mbuf = pkts[i];
-		zmbufs[i]->desc_idx = avail_idx + i;
+		zmbufs[i]->desc_idx = ids[i];
 		zmbufs[i]->desc_count = 1;
 	}
 
@@ -2045,7 +2061,7 @@ virtio_dev_tx_single_packed_zmbuf(struct virtio_net *dev,
 		return -1;
 	}
 	zmbuf->mbuf = *pkts;
-	zmbuf->desc_idx = vq->last_avail_idx;
+	zmbuf->desc_idx = buf_id;
 	zmbuf->desc_count = desc_count;
 
 	rte_mbuf_refcnt_update(*pkts, 1);
@@ -2149,7 +2165,6 @@ virtio_dev_tx_packed(struct virtio_net *dev,
 		if (remained >= PACKED_BATCH_SIZE) {
 			if (!virtio_dev_tx_batch_packed(dev, vq, mbuf_pool,
 							&pkts[pkt_idx])) {
-				vhost_flush_dequeue_packed(dev, vq);
 				pkt_idx += PACKED_BATCH_SIZE;
 				remained -= PACKED_BATCH_SIZE;
 				continue;
@@ -2159,15 +2174,18 @@ virtio_dev_tx_packed(struct virtio_net *dev,
 		if (virtio_dev_tx_single_packed(dev, vq, mbuf_pool,
 						&pkts[pkt_idx]))
 			break;
-		vhost_flush_dequeue_packed(dev, vq);
 		pkt_idx++;
 		remained--;
 
 	} while (remained);
 
-	if (vq->shadow_used_idx)
+	if (vq->shadow_used_idx) {
 		do_data_copy_dequeue(vq);
 
+		vhost_flush_dequeue_shadow_packed(dev, vq);
+		vhost_vring_call_packed(dev, vq);
+	}
+
 	return pkt_idx;
 }
 
diff --git a/dpdk/lib/meson.build b/dpdk/lib/meson.build
index 6ceb5e756e..b60396428c 100644
--- a/dpdk/lib/meson.build
+++ b/dpdk/lib/meson.build
@@ -127,7 +127,7 @@ foreach l:libraries
 					dependencies: static_deps,
 					include_directories: includes,
 					install: true)
-			static_dep = declare_dependency(link_with: static_lib,
+			static_dep = declare_dependency(
 					include_directories: includes,
 					dependencies: static_deps)
 
@@ -148,12 +148,18 @@ foreach l:libraries
 				command: [map_to_def_cmd, '@INPUT@', '@OUTPUT@'],
 				input: version_map,
 				output: 'rte_@0@_exports.def'.format(name))
-			lk_deps = [version_map, def_file]
-			if is_windows
-				lk_args = ['-Wl,/def:' + def_file.full_path(),
-					'-Wl,/implib:lib\\' + implib]
+
+			if is_ms_linker
+				lk_args = ['-Wl,/def:' + def_file.full_path()]
+				if meson.version().version_compare('<0.54.0')
+					lk_args += ['-Wl,/implib:lib\\' + implib]
+				endif
 			else
 				lk_args = ['-Wl,--version-script=' + version_map]
+			endif
+
+			lk_deps = [version_map, def_file]
+			if not is_windows
 				# on unix systems check the output of the
 				# experimental syms script, using it as a
 				# dependency of the .so build
diff --git a/dpdk/license/bsd-2-clause.txt b/dpdk/license/bsd-2-clause.txt
new file mode 100644
index 0000000000..dfb3f1adea
--- /dev/null
+++ b/dpdk/license/bsd-2-clause.txt
@@ -0,0 +1,20 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+
+    2. Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/dpdk/license/isc.txt b/dpdk/license/isc.txt
new file mode 100644
index 0000000000..34a6a760d5
--- /dev/null
+++ b/dpdk/license/isc.txt
@@ -0,0 +1,11 @@
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
+TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+OF THIS SOFTWARE.
diff --git a/dpdk/license/mit.txt b/dpdk/license/mit.txt
new file mode 100644
index 0000000000..c4037a4605
--- /dev/null
+++ b/dpdk/license/mit.txt
@@ -0,0 +1,18 @@
+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 (including the next
+paragraph) 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.
diff --git a/dpdk/meson.build b/dpdk/meson.build
index b7ae9c8d9a..00949de995 100644
--- a/dpdk/meson.build
+++ b/dpdk/meson.build
@@ -48,6 +48,9 @@ subdir('doc')
 # build any examples explicitly requested - useful for developers - and
 # install any example code into the appropriate install path
 subdir('examples')
+install_subdir('examples',
+	install_dir: get_option('datadir') + '/dpdk',
+	exclude_files: 'meson.build')
 
 # build kernel modules if enabled
 if get_option('enable_kmods')
@@ -61,29 +64,8 @@ configure_file(output: build_cfg,
 		install_dir: join_paths(get_option('includedir'),
 				get_option('include_subdir_arch')))
 
-# for static builds, include the drivers as libs and we need to "whole-archive"
-# them.
-dpdk_drivers = ['-Wl,--whole-archive'] + dpdk_drivers + ['-Wl,--no-whole-archive']
-
-pkg = import('pkgconfig')
-pkg_extra_cflags = ['-include', 'rte_config.h'] + machine_args
-if is_freebsd
-	pkg_extra_cflags += ['-D__BSD_VISIBLE']
-endif
-pkg.generate(name: meson.project_name(),
-	filebase: 'lib' + meson.project_name().to_lower(),
-	version: meson.project_version(),
-	libraries: dpdk_libraries,
-	libraries_private: dpdk_drivers + dpdk_static_libraries +
-			['-Wl,-Bdynamic'] + dpdk_extra_ldflags,
-	requires: libbsd, # apps using rte_string_fns.h may need this if enabled
-	                  # if libbsd is not enabled, then this is blank
-	description: '''The Data Plane Development Kit (DPDK).
-Note that CFLAGS might contain an -march flag higher than typical baseline.
-This is required for a number of static inline functions in the public headers.''',
-	subdirs: [get_option('include_subdir_arch'), '.'],
-	extra_cflags: pkg_extra_cflags
-)
+# build pkg-config files for dpdk
+subdir('buildtools/pkg-config')
 
 # final output, list all the libs and drivers to be built
 # this does not affect any part of the build, for information only.
diff --git a/dpdk/meson_options.txt b/dpdk/meson_options.txt
index bc369d06c9..0de16b4fdb 100644
--- a/dpdk/meson_options.txt
+++ b/dpdk/meson_options.txt
@@ -12,8 +12,8 @@ option('examples', type: 'string', value: '',
 	description: 'Comma-separated list of examples to build by default')
 option('flexran_sdk', type: 'string', value: '',
 	description: 'Path to FlexRAN SDK optional Libraries for BBDEV device')
-option('ibverbs_link', type: 'combo', choices : ['shared', 'dlopen'], value: 'shared',
-	description: 'Linkage method (shared/dlopen) for Mellanox PMDs with ibverbs dependencies.')
+option('ibverbs_link', type: 'combo', choices : ['static', 'shared', 'dlopen'], value: 'shared',
+	description: 'Linkage method (static/shared/dlopen) for Mellanox PMDs with ibverbs dependencies.')
 option('include_subdir_arch', type: 'string', value: '',
 	description: 'subdirectory where to install arch-dependent headers')
 option('kernel_dir', type: 'string', value: '',
diff --git a/dpdk/mk/internal/rte.compile-pre.mk b/dpdk/mk/internal/rte.compile-pre.mk
index 0cf3791b4d..82fe098f7c 100644
--- a/dpdk/mk/internal/rte.compile-pre.mk
+++ b/dpdk/mk/internal/rte.compile-pre.mk
@@ -61,7 +61,7 @@ CHECK_EXPERIMENTAL = $(EXPERIMENTAL_CHECK) $(SRCDIR)/$(EXPORT_MAP) $@
 
 PMDINFO_GEN = $(RTE_SDK_BIN)/app/dpdk-pmdinfogen $@ $@.pmd.c
 PMDINFO_CC = $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@.pmd.o $@.pmd.c
-PMDINFO_LD = $(CROSS)ld $(LDFLAGS) -r -o $@.o $@.pmd.o $@
+PMDINFO_LD = $(CROSS)ld -r $(filter-out -export-dynamic,$(LDFLAGS)) -o $@.o $@.pmd.o $@
 PMDINFO_TO_O = if grep -q 'RTE_PMD_REGISTER_.*(.*)' $<; then \
 	echo "$(if $V,$(PMDINFO_GEN),  PMDINFO $@.pmd.c)" && \
 	$(PMDINFO_GEN) && \
diff --git a/dpdk/mk/machine/graviton2/rte.vars.mk b/dpdk/mk/machine/graviton2/rte.vars.mk
new file mode 100644
index 0000000000..1796c9cf8f
--- /dev/null
+++ b/dpdk/mk/machine/graviton2/rte.vars.mk
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) Amazon.com, Inc or its affiliates
+#
+
+#
+# machine:
+#
+#   - can define ARCH variable (overridden by cmdline value)
+#   - can define CROSS variable (overridden by cmdline value)
+#   - define MACHINE_CFLAGS variable (overridden by cmdline value)
+#   - define MACHINE_LDFLAGS variable (overridden by cmdline value)
+#   - define MACHINE_ASFLAGS variable (overridden by cmdline value)
+#   - can define CPU_CFLAGS variable (overridden by cmdline value) that
+#     overrides the one defined in arch.
+#   - can define CPU_LDFLAGS variable (overridden by cmdline value) that
+#     overrides the one defined in arch.
+#   - can define CPU_ASFLAGS variable (overridden by cmdline value) that
+#     overrides the one defined in arch.
+#   - may override any previously defined variable
+#
+
+# ARCH =
+# CROSS =
+# MACHINE_CFLAGS =
+# MACHINE_LDFLAGS =
+# MACHINE_ASFLAGS =
+# CPU_CFLAGS =
+# CPU_LDFLAGS =
+# CPU_ASFLAGS =
+
+include $(RTE_SDK)/mk/rte.helper.mk
+
+MACHINE_CFLAGS += $(call rte_cc_has_argument, -march=armv8.2-a+crypto)
+MACHINE_CFLAGS += $(call rte_cc_has_argument, -mcpu=neoverse-n1)
diff --git a/dpdk/mk/rte.app.mk b/dpdk/mk/rte.app.mk
index 05ea034b99..44dd684cb1 100644
--- a/dpdk/mk/rte.app.mk
+++ b/dpdk/mk/rte.app.mk
@@ -196,8 +196,12 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -ldl
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -ldl
 else ifeq ($(CONFIG_RTE_IBVERBS_LINK_STATIC),y)
 LIBS_IBVERBS_STATIC = $(shell $(RTE_SDK)/buildtools/options-ibverbs-static.sh)
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += --no-whole-archive
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += $(LIBS_IBVERBS_STATIC)
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += --whole-archive
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += --no-whole-archive
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += $(LIBS_IBVERBS_STATIC)
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += --whole-archive
 else
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX4_PMD)       += -libverbs -lmlx4
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MLX5_PMD)       += -libverbs -lmlx5
diff --git a/dpdk/mk/toolchain/gcc/rte.vars.mk b/dpdk/mk/toolchain/gcc/rte.vars.mk
index 9fc704193b..b3473c06fd 100644
--- a/dpdk/mk/toolchain/gcc/rte.vars.mk
+++ b/dpdk/mk/toolchain/gcc/rte.vars.mk
@@ -83,6 +83,11 @@ ifeq ($(shell test $(GCC_VERSION) -lt 47 && echo 1), 1)
 WERROR_FLAGS += -Wno-uninitialized
 endif
 
+ifeq ($(shell test $(GCC_VERSION) -ge 100 && echo 1), 1)
+# FIXME: Bugzilla 396
+WERROR_FLAGS += -Wno-zero-length-bounds
+endif
+
 HOST_WERROR_FLAGS := $(WERROR_FLAGS)
 
 ifeq ($(shell test $(HOST_GCC_VERSION) -gt 70 && echo 1), 1)
diff --git a/dpdk/usertools/cpu_layout.py b/dpdk/usertools/cpu_layout.py
index 6f129b1db8..39b268752a 100755
--- a/dpdk/usertools/cpu_layout.py
+++ b/dpdk/usertools/cpu_layout.py
@@ -22,8 +22,6 @@
         fd = open("{}/cpu{}/topology/core_id".format(base_path, cpu))
     except IOError:
         continue
-    except:
-        break
     core = int(fd.read())
     fd.close()
     fd = open("{}/cpu{}/topology/physical_package_id".format(base_path, cpu))
@@ -66,7 +64,7 @@
 for c in cores:
     output = "Core %s" % str(c).ljust(max_core_id_len)
     for s in sockets:
-        if (s,c) in core_map:
+        if (s, c) in core_map:
             output += " " + str(core_map[(s, c)]).ljust(max_core_map_len)
         else:
             output += " " * (max_core_map_len + 1)
diff --git a/dpdk/usertools/dpdk-devbind.py b/dpdk/usertools/dpdk-devbind.py
index b1d1498768..44ea3dd30b 100755
--- a/dpdk/usertools/dpdk-devbind.py
+++ b/dpdk/usertools/dpdk-devbind.py
@@ -7,6 +7,7 @@
 import sys
 import os
 import getopt
+import platform
 import subprocess
 from os.path import exists, abspath, dirname, basename
 
@@ -172,7 +173,17 @@ def module_is_loaded(module):
 
     loaded_modules = sysfs_mods
 
-    return module in sysfs_mods
+    # add built-in modules as loaded
+    release = platform.release()
+    filename = os.path.join("/lib/modules/", release, "modules.builtin")
+    if os.path.exists(filename):
+        try:
+            with open(filename) as f:
+                loaded_modules += [os.path.splitext(os.path.basename(mod))[0] for mod in f]
+        except IOError:
+            print("Warning: cannot read list of built-in kernel modules")
+
+    return module in loaded_modules
 
 
 def check_modules():
diff --git a/dpdk/usertools/dpdk-pmdinfo.py b/dpdk/usertools/dpdk-pmdinfo.py
index 069a3bf124..27e1cad328 100755
--- a/dpdk/usertools/dpdk-pmdinfo.py
+++ b/dpdk/usertools/dpdk-pmdinfo.py
@@ -352,7 +352,7 @@ def display_pmd_info_strings(self, section_spec):
             mystring = force_unicode(data[dataptr:endptr])
             rc = mystring.find("PMD_INFO_STRING")
             if (rc != -1):
-                self.parse_pmd_info_string(mystring)
+                self.parse_pmd_info_string(mystring[rc:])
 
             dataptr = endptr
 
@@ -539,7 +539,7 @@ def scan_for_autoload_pmds(dpdk_path):
         return
 
     (autoload_path, scannedfile) = readelf.search_for_autoload_path()
-    if (autoload_path is None or autoload_path is ""):
+    if not autoload_path:
         if (raw_output is False):
             print("No autoload path configured in %s" % dpdk_path)
         return
@@ -561,7 +561,10 @@ def main(stream=None):
 
     pcifile_default = "./pci.ids"  # For unknown OS's assume local file
     if platform.system() == 'Linux':
-        pcifile_default = "/usr/share/hwdata/pci.ids"
+        # hwdata is the legacy location, misc is supported going forward
+        pcifile_default = "/usr/share/misc/pci.ids"
+        if not os.path.exists(pcifile_default):
+            pcifile_default = "/usr/share/hwdata/pci.ids"
     elif platform.system() == 'FreeBSD':
         pcifile_default = "/usr/local/share/pciids/pci.ids"
         if not os.path.exists(pcifile_default):
diff --git a/dpdk/usertools/dpdk-telemetry-client.py b/dpdk/usertools/dpdk-telemetry-client.py
index 290345dcc4..35edb7cd26 100755
--- a/dpdk/usertools/dpdk-telemetry-client.py
+++ b/dpdk/usertools/dpdk-telemetry-client.py
@@ -3,6 +3,7 @@
 # Copyright(c) 2018 Intel Corporation
 
 from __future__ import print_function
+from __future__ import unicode_literals
 
 import socket
 import os
@@ -65,18 +66,19 @@ def register(self): # Connects a client to DPDK-instance
         self.socket.recv_fd.settimeout(2)
         self.socket.send_fd.connect("/var/run/dpdk/rte/telemetry")
         JSON = (API_REG + self.file_path + "\"}}")
-        self.socket.send_fd.sendall(JSON)
+        self.socket.send_fd.sendall(JSON.encode())
+
         self.socket.recv_fd.listen(1)
         self.socket.client_fd = self.socket.recv_fd.accept()[0]
 
     def unregister(self): # Unregister a given client
-        self.socket.client_fd.send(API_UNREG + self.file_path + "\"}}")
+        self.socket.client_fd.send((API_UNREG + self.file_path + "\"}}").encode())
         self.socket.client_fd.close()
 
     def requestMetrics(self): # Requests metrics for given client
-        self.socket.client_fd.send(METRICS_REQ)
-        data = self.socket.client_fd.recv(BUFFER_SIZE)
-        print("\nResponse: \n", str(data))
+        self.socket.client_fd.send(METRICS_REQ.encode())
+        data = self.socket.client_fd.recv(BUFFER_SIZE).decode()
+        print("\nResponse: \n", data)
 
     def repeatedlyRequestMetrics(self, sleep_time): # Recursively requests metrics for given client
         print("\nPlease enter the number of times you'd like to continuously request Metrics:")
@@ -88,9 +90,9 @@ def repeatedlyRequestMetrics(self, sleep_time): # Recursively requests metrics f
             time.sleep(sleep_time)
 
     def requestGlobalMetrics(self): #Requests global metrics for given client
-        self.socket.client_fd.send(GLOBAL_METRICS_REQ)
-        data = self.socket.client_fd.recv(BUFFER_SIZE)
-        print("\nResponse: \n", str(data))
+        self.socket.client_fd.send(GLOBAL_METRICS_REQ.encode())
+        data = self.socket.client_fd.recv(BUFFER_SIZE).decode()
+        print("\nResponse: \n", data)
 
     def interactiveMenu(self, sleep_time): # Creates Interactive menu within the script
         while self.choice != 4:
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index b0a5ce8bec..bc51a5767f 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -1,7 +1,7 @@
 #ifndef __LINUX_PKT_CLS_WRAPPER_H
 #define __LINUX_PKT_CLS_WRAPPER_H 1
 
-#if defined(__KERNEL__) || defined(HAVE_TCA_ACT_FLAGS)
+#if defined(__KERNEL__) || defined(HAVE_TCA_FLOWER_KEY_CT_FLAGS_REPLY)
 #include_next <linux/pkt_cls.h>
 #else
 
@@ -255,6 +255,9 @@ enum {
 	TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */
 	TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */
 	TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */
+	TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */
+	TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */
+	__TCA_FLOWER_KEY_CT_FLAGS_MAX,
 };
 
 enum {
diff --git a/include/openvswitch/compiler.h b/include/openvswitch/compiler.h
index 5289a70f6e..cf009f8264 100644
--- a/include/openvswitch/compiler.h
+++ b/include/openvswitch/compiler.h
@@ -113,6 +113,8 @@
  *    OVS_REQUIRES         OVS_REQ_RDLOCK       OVS_REQ_WRLOCK
  *    OVS_EXCLUDED         OVS_EXCLUDED         OVS_EXCLUDED
  */
+
+/* Please keep OVS_CTAGS_IDENTIFIERS up-to-date in acinclude.m4. */
 #define OVS_LOCKABLE __attribute__((lockable))
 #define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__)))
 #define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__)))
diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
index 1f81d830e7..4b9893388b 100644
--- a/include/openvswitch/meta-flow.h
+++ b/include/openvswitch/meta-flow.h
@@ -2277,6 +2277,7 @@ void mf_set_flow_value_masked(const struct mf_field *,
                               const union mf_value *mask,
                               struct flow *);
 bool mf_is_tun_metadata(const struct mf_field *);
+bool mf_is_frozen_metadata(const struct mf_field *);
 bool mf_is_pipeline_field(const struct mf_field *);
 bool mf_is_set(const struct mf_field *, const struct flow *);
 void mf_mask_field(const struct mf_field *, struct flow_wildcards *);
diff --git a/ipsec/ovs-monitor-ipsec.in b/ipsec/ovs-monitor-ipsec.in
index 37e3703245..668507fd37 100755
--- a/ipsec/ovs-monitor-ipsec.in
+++ b/ipsec/ovs-monitor-ipsec.in
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 import argparse
+import ipaddress
 import re
 import subprocess
 import sys
@@ -101,7 +102,7 @@ class XFRM(object):
         proc = subprocess.Popen([self.IP, 'xfrm', 'policy'],
                                 stdout=subprocess.PIPE)
         while True:
-            line = proc.stdout.readline().strip()
+            line = proc.stdout.readline().strip().decode()
             if line == '':
                 break
             a = line.split(" ")
@@ -124,7 +125,7 @@ class XFRM(object):
         proc = subprocess.Popen([self.IP, 'xfrm', 'state'],
                                 stdout=subprocess.PIPE)
         while True:
-            line = proc.stdout.readline().strip()
+            line = proc.stdout.readline().strip().decode()
             if line == '':
                 break
             a = line.split(" ")
@@ -145,10 +146,18 @@ class StrongSwanHelper(object):
     """This class does StrongSwan specific configurations."""
 
     STRONGSWAN_CONF = """%s
-charon.plugins.kernel-netlink.set_proto_port_transport_sa = yes
-charon.plugins.kernel-netlink.xfrm_ack_expires = 10
-charon.load_modular = yes
-charon.plugins.gcm.load = yes
+charon {
+  plugins {
+    kernel-netlink {
+      set_proto_port_transport_sa = yes
+      xfrm_ack_expires = 10
+    }
+    gcm {
+      load = yes
+    }
+  }
+  load_modular = yes
+}
 """ % (FILE_HEADER)
 
     CONF_HEADER = """%s
@@ -246,7 +255,7 @@ conn prevent_unencrypted_vxlan
         proc = subprocess.Popen([self.IPSEC, 'status'], stdout=subprocess.PIPE)
 
         while True:
-            line = proc.stdout.readline().strip()
+            line = proc.stdout.readline().strip().decode()
             if line == '':
                 break
             tunnel_name = line.split(":")
@@ -340,7 +349,7 @@ conn prevent_unencrypted_vxlan
         # about possibility of ovs-monitor-ipsec to block for each tunnel
         # while strongSwan sends IKE messages over Internet.
         conns_dict = self.get_active_conns()
-        for ifname, conns in conns_dict.iteritems():
+        for ifname, conns in conns_dict.items():
             tunnel = monitor.tunnels.get(ifname)
             for conn in conns:
                 # IPsec "connection" names that we choose in strongswan
@@ -405,22 +414,27 @@ conn prevent_unencrypted_vxlan
     leftprotoport=udp/4789
     mark={0}
 
+"""
+
+    IPV6_CONN = """\
+    hostaddrfamily=ipv6
+    clientaddrfamily=ipv6
 """
 
     auth_tmpl = {"psk": Template("""\
-    left=%defaultroute
+    left=$local_ip
     right=$remote_ip
     authby=secret"""),
                  "pki_remote": Template("""\
-    left=%defaultroute
+    left=$local_ip
     right=$remote_ip
     leftid=@$local_name
     rightid=@$remote_name
-    leftcert="$local_name"
-    rightcert="$remote_name"
+    leftcert="ovs_certkey_$local_name"
+    rightcert="ovs_cert_$remote_name"
     leftrsasigkey=%cert"""),
                  "pki_ca": Template("""\
-    left=%defaultroute
+    left=$local_ip
     right=$remote_ip
     leftid=@$local_name
     rightid=@$remote_name
@@ -512,6 +526,9 @@ conn prevent_unencrypted_vxlan
         else:
             auth_section = self.auth_tmpl["pki_ca"].substitute(tunnel.conf)
 
+        if tunnel.conf["address_family"] == "IPv6":
+            auth_section = self.IPV6_CONN + auth_section
+
         vals = tunnel.conf.copy()
         vals["auth_section"] = auth_section
         vals["version"] = tunnel.version
@@ -536,7 +553,7 @@ conn prevent_unencrypted_vxlan
 
         # Delete old connections
         conns_dict = self.get_active_conns()
-        for ifname, conns in conns_dict.iteritems():
+        for ifname, conns in conns_dict.items():
             tunnel = monitor.tunnels.get(ifname)
 
             for conn in conns:
@@ -608,7 +625,7 @@ conn prevent_unencrypted_vxlan
         proc = subprocess.Popen([self.IPSEC, 'status'], stdout=subprocess.PIPE)
 
         while True:
-            line = proc.stdout.readline().strip()
+            line = proc.stdout.readline().strip().decode()
             if line == '':
                 break
 
@@ -617,7 +634,10 @@ conn prevent_unencrypted_vxlan
                 continue
 
             conn = m.group(1)
-            m = re.match(r"(.*)(-in-\d+|-out-\d+|-\d+)", conn)
+            m = re.match(r"(.*)(-in-\d+|-out-\d+)", conn)
+            if not m:
+                # GRE connections have format <iface>-<ver>
+                m = re.match(r"(.*)(-\d+)", conn)
             if not m:
                 continue
 
@@ -649,7 +669,8 @@ conn prevent_unencrypted_vxlan
             proc = subprocess.Popen(['certutil', '-L', '-d',
                                     'sql:/etc/ipsec.d/'],
                                     stdout=subprocess.PIPE,
-                                    stderr=subprocess.PIPE)
+                                    stderr=subprocess.PIPE,
+                                    universal_newlines=True)
             lines = proc.stdout.readlines()
 
             for line in lines:
@@ -678,7 +699,7 @@ conn prevent_unencrypted_vxlan
             if proc.returncode:
                 raise Exception(proc.stderr.read())
         except Exception as e:
-            vlog.err("Failed to import ceretificate into NSS.\n" + str(e))
+            vlog.err("Failed to import certificate into NSS.\n" + str(e))
 
     def _nss_delete_cert(self, name):
         try:
@@ -690,7 +711,7 @@ conn prevent_unencrypted_vxlan
             if proc.returncode:
                 raise Exception(proc.stderr.read())
         except Exception as e:
-            vlog.err("Failed to delete ceretificate from NSS.\n" + str(e))
+            vlog.err("Failed to delete certificate from NSS.\n" + str(e))
 
     def _nss_import_cert_and_key(self, cert, key, name):
         try:
@@ -742,7 +763,9 @@ class IPsecTunnel(object):
 
     unixctl_config_tmpl = Template("""\
   Tunnel Type:    $tunnel_type
+  Local IP:       $local_ip
   Remote IP:      $remote_ip
+  Address Family: $address_family
   SKB mark:       $skb_mark
   Local cert:     $certificate
   Local name:     $local_name
@@ -782,7 +805,11 @@ class IPsecTunnel(object):
         new_conf = {
             "ifname": self.name,
             "tunnel_type": row.type,
+            "local_ip": options.get("local_ip", "%defaultroute"),
             "remote_ip": options.get("remote_ip"),
+            "address_family": self._get_conn_address_family(
+                                                   options.get("remote_ip"),
+                                                   options.get("local_ip")),
             "skb_mark": monitor.conf["skb_mark"],
             "certificate": monitor.conf["pki"]["certificate"],
             "private_key": monitor.conf["pki"]["private_key"],
@@ -851,6 +878,17 @@ class IPsecTunnel(object):
 
         return header + conf + status + spds + sas + cons + "\n"
 
+    def _get_conn_address_family(self, remote_ip, local_ip):
+        remote = address_family(remote_ip)
+        local = address_family(local_ip)
+
+        if local is None:
+            return remote
+        elif local != remote:
+            return None
+        else:
+            return remote
+
     def _is_valid_tunnel_conf(self):
         """This function verifies if IPsec tunnel has valid configuration
         set in 'conf'.  If it is valid, then it returns True.  Otherwise,
@@ -911,7 +949,7 @@ class IPsecTunnel(object):
 class IPsecMonitor(object):
     """This class monitors and configures IPsec tunnels"""
 
-    def __init__(self, root_prefix, ike_daemon):
+    def __init__(self, root_prefix, ike_daemon, restart):
         self.IPSEC = root_prefix + "/usr/sbin/ipsec"
         self.tunnels = {}
 
@@ -941,7 +979,9 @@ class IPsecMonitor(object):
                 not os.access(self.IPSEC, os.X_OK):
             vlog.err("IKE daemon is not installed in the system.")
 
-        self.ike_helper.restart_ike_daemon()
+        if restart:
+            vlog.info("Restarting IKE daemon")
+            self.ike_helper.restart_ike_daemon()
 
     def is_tunneling_type_supported(self, tunnel_type):
         """Returns True if we know how to configure IPsec for these
@@ -989,7 +1029,7 @@ class IPsecMonitor(object):
         skb_mark = None
         is_valid = False
 
-        for row in data["Open_vSwitch"].rows.itervalues():
+        for row in data["Open_vSwitch"].rows.values():
             pki[0] = row.other_config.get("certificate")
             pki[1] = row.other_config.get("private_key")
             pki[2] = row.other_config.get("ca_cert")
@@ -1016,7 +1056,7 @@ class IPsecMonitor(object):
         table."""
         ifaces = set()
 
-        for row in data["Interface"].rows.itervalues():
+        for row in data["Interface"].rows.values():
             if not self.is_tunneling_type_supported(row.type):
                 continue
             if not self.is_ipsec_required(row.options):
@@ -1047,7 +1087,7 @@ class IPsecMonitor(object):
             return
         s = ""
         conns = self.ike_helper.get_active_conns()
-        for name, tunnel in self.tunnels.iteritems():
+        for name, tunnel in self.tunnels.items():
             s += tunnel.show(policies, securities, conns)
         unix_conn.reply(s)
 
@@ -1064,7 +1104,7 @@ class IPsecMonitor(object):
         if self.ike_helper.config_global(self):
             needs_refresh = True
 
-        for name, tunnel in self.tunnels.iteritems():
+        for name, tunnel in self.tunnels.items():
             if tunnel.last_refreshed_version != tunnel.version:
                 tunnel.last_refreshed_version = tunnel.version
                 needs_refresh = True
@@ -1094,7 +1134,7 @@ class IPsecMonitor(object):
             proc.wait()
             if proc.returncode:
                 raise Exception(proc.stderr.read())
-            m = re.search(r"CN=(.+?),", proc.stdout.readline())
+            m = re.search(r"CN=(.+?),", proc.stdout.readline().decode())
             if not m:
                 raise Exception("No CN in the certificate subject.")
         except Exception as e:
@@ -1104,6 +1144,19 @@ class IPsecMonitor(object):
         return m.group(1)
 
 
+def address_family(address):
+    try:
+        ip = ipaddress.ip_address(address)
+        ipstr = str(type(ip))
+    # ipaddress has inconsistencies with what exceptions are raised:
+    # https://mail.openvswitch.org/pipermail/ovs-dev/2021-April/381696.html
+    except (ValueError, ipaddress.AddressValueError):
+        return None
+    if ipstr.find('v6') != -1:
+        return "IPv6"
+    return "IPv4"
+
+
 def unixctl_xfrm_policies(conn, unused_argv, unused_aux):
     global xfrm
     policies = xfrm.get_policies()
@@ -1136,19 +1189,30 @@ def unixctl_refresh(conn, unused_argv, unused_aux):
     conn.reply(None)
 
 
-def unixctl_exit(conn, unused_argv, unused_aux):
+def unixctl_exit(conn, argv, unused_aux):
     global monitor
     global exiting
+    ret = None
     exiting = True
+    cleanup = True
 
-    # Make sure persistent global states are cleared
-    monitor.update_conf([None, None, None, None], None)
-    # Make sure persistent tunnel states are cleared
-    for tunnel in monitor.tunnels.keys():
-        monitor.del_tunnel(tunnel)
-    monitor.run()
+    for arg in argv:
+        if arg == "--no-cleanup":
+            cleanup = False
+        else:
+            cleanup = False
+            exiting = False
+            ret = str("unrecognized parameter: %s" % arg)
+
+    if cleanup:
+        # Make sure persistent global states are cleared
+        monitor.update_conf([None, None, None, None], None)
+        # Make sure persistent tunnel states are cleared
+        for tunnel in monitor.tunnels.keys():
+            monitor.del_tunnel(tunnel)
+        monitor.run()
 
-    conn.reply(None)
+    conn.reply(ret)
 
 
 def main():
@@ -1161,6 +1225,8 @@ def main():
     parser.add_argument("--ike-daemon", metavar="IKE-DAEMON",
                         help="The IKE daemon used for IPsec tunnels"
                         " (either libreswan or strongswan).")
+    parser.add_argument("--no-restart-ike-daemon", action='store_true',
+                        help="Don't restart the IKE daemon on startup.")
 
     ovs.vlog.add_args(parser)
     ovs.daemon.add_args(parser)
@@ -1173,7 +1239,8 @@ def main():
 
     root_prefix = args.root_prefix if args.root_prefix else ""
     xfrm = XFRM(root_prefix)
-    monitor = IPsecMonitor(root_prefix, args.ike_daemon)
+    monitor = IPsecMonitor(root_prefix, args.ike_daemon,
+                           not args.no_restart_ike_daemon)
 
     remote = args.database
     schema_helper = ovs.db.idl.SchemaHelper()
@@ -1194,7 +1261,8 @@ def main():
     ovs.unixctl.command_register("tunnels/show", "", 0, 0,
                                  unixctl_show, None)
     ovs.unixctl.command_register("refresh", "", 0, 0, unixctl_refresh, None)
-    ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, None)
+    ovs.unixctl.command_register("exit", "[--no-cleanup]", 0, 1,
+                                 unixctl_exit, None)
 
     error, unixctl_server = ovs.unixctl.server.UnixctlServer.create(None)
     if error:
diff --git a/lib/classifier.c b/lib/classifier.c
index 0fad953213..2a1d155dad 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -393,7 +393,9 @@ classifier_set_prefix_fields(struct classifier *cls,
         bitmap_set1(fields.bm, trie_fields[i]);
 
         new_fields[n_tries] = NULL;
-        if (n_tries >= cls->n_tries || field != cls->tries[n_tries].field) {
+        const struct mf_field *cls_field
+            = ovsrcu_get(struct mf_field *, &cls->tries[n_tries].field);
+        if (n_tries >= cls->n_tries || field != cls_field) {
             new_fields[n_tries] = field;
             changed = true;
         }
@@ -454,7 +456,7 @@ trie_init(struct classifier *cls, int trie_idx, const struct mf_field *field)
     } else {
         ovsrcu_set_hidden(&trie->root, NULL);
     }
-    trie->field = field;
+    ovsrcu_set_hidden(&trie->field, CONST_CAST(struct mf_field *, field));
 
     /* Add existing rules to the new trie. */
     CMAP_FOR_EACH (subtable, cmap_node, &cls->subtables_map) {
@@ -839,7 +841,6 @@ classifier_remove_assert(struct classifier *cls,
 struct trie_ctx {
     const struct cls_trie *trie;
     bool lookup_done;        /* Status of the lookup. */
-    uint8_t be32ofs;         /* U32 offset of the field in question. */
     unsigned int maskbits;   /* Prefix length needed to avoid false matches. */
     union trie_prefix match_plens;  /* Bitmask of prefix lengths with possible
                                      * matches. */
@@ -849,7 +850,6 @@ static void
 trie_ctx_init(struct trie_ctx *ctx, const struct cls_trie *trie)
 {
     ctx->trie = trie;
-    ctx->be32ofs = trie->field->flow_be32ofs;
     ctx->lookup_done = false;
 }
 
@@ -1370,6 +1370,7 @@ cls_cursor_start(const struct classifier *cls, const struct cls_rule *target,
     struct cls_cursor cursor;
     struct cls_subtable *subtable;
 
+    memset(&cursor, 0x0, sizeof cursor);
     cursor.cls = cls;
     cursor.target = target && !cls_rule_is_catchall(target) ? target : NULL;
     cursor.version = version;
@@ -1531,8 +1532,10 @@ insert_subtable(struct classifier *cls, const struct minimask *mask)
     *CONST_CAST(uint8_t *, &subtable->n_indices) = index;
 
     for (i = 0; i < cls->n_tries; i++) {
-        subtable->trie_plen[i] = minimask_get_prefix_len(mask,
-                                                         cls->tries[i].field);
+        const struct mf_field *field
+            = ovsrcu_get(struct mf_field *, &cls->tries[i].field);
+        subtable->trie_plen[i]
+            = field ? minimask_get_prefix_len(mask, field) : 0;
     }
 
     /* Ports trie. */
@@ -1575,11 +1578,17 @@ check_tries(struct trie_ctx trie_ctx[CLS_MAX_TRIES], unsigned int n_tries,
      * fields using the prefix tries.  The trie checks are done only as
      * needed to avoid folding in additional bits to the wildcards mask. */
     for (j = 0; j < n_tries; j++) {
-        /* Is the trie field relevant for this subtable, and
-           is the trie field within the current range of fields? */
-        if (field_plen[j] &&
-            flowmap_is_set(&range_map, trie_ctx[j].be32ofs / 2)) {
+        /* Is the trie field relevant for this subtable? */
+        if (field_plen[j]) {
             struct trie_ctx *ctx = &trie_ctx[j];
+            const struct mf_field *ctx_field
+                = ovsrcu_get(struct mf_field *, &ctx->trie->field);
+
+            /* Is the trie field within the current range of fields? */
+            if (!ctx_field
+                || !flowmap_is_set(&range_map, ctx_field->flow_be32ofs / 2)) {
+                continue;
+            }
 
             /* On-demand trie lookup. */
             if (!ctx->lookup_done) {
@@ -1601,14 +1610,16 @@ check_tries(struct trie_ctx trie_ctx[CLS_MAX_TRIES], unsigned int n_tries,
                  * than this subtable would otherwise. */
                 if (ctx->maskbits <= field_plen[j]) {
                     /* Unwildcard the bits and skip the rest. */
-                    mask_set_prefix_bits(wc, ctx->be32ofs, ctx->maskbits);
+                    mask_set_prefix_bits(wc, ctx_field->flow_be32ofs,
+                                         ctx->maskbits);
                     /* Note: Prerequisite already unwildcarded, as the only
                      * prerequisite of the supported trie lookup fields is
                      * the ethertype, which is always unwildcarded. */
                     return true;
                 }
                 /* Can skip if the field is already unwildcarded. */
-                if (mask_prefix_bits_set(wc, ctx->be32ofs, ctx->maskbits)) {
+                if (mask_prefix_bits_set(wc, ctx_field->flow_be32ofs,
+                                         ctx->maskbits)) {
                     return true;
                 }
             }
@@ -2001,12 +2012,12 @@ static unsigned int
 trie_lookup(const struct cls_trie *trie, const struct flow *flow,
             union trie_prefix *plens)
 {
-    const struct mf_field *mf = trie->field;
+    const struct mf_field *mf = ovsrcu_get(struct mf_field *, &trie->field);
 
     /* Check that current flow matches the prerequisites for the trie
      * field.  Some match fields are used for multiple purposes, so we
      * must check that the trie is relevant for this flow. */
-    if (mf_are_prereqs_ok(mf, flow, NULL)) {
+    if (mf && mf_are_prereqs_ok(mf, flow, NULL)) {
         return trie_lookup_value(&trie->root,
                                  &((ovs_be32 *)flow)[mf->flow_be32ofs],
                                  &plens->be32, mf->n_bits);
@@ -2053,8 +2064,9 @@ minimask_get_prefix_len(const struct minimask *minimask,
  * happened to be zeros.
  */
 static const ovs_be32 *
-minimatch_get_prefix(const struct minimatch *match, const struct mf_field *mf)
+minimatch_get_prefix(const struct minimatch *match, rcu_field_ptr *field)
 {
+    struct mf_field *mf = ovsrcu_get_protected(struct mf_field *, field);
     size_t u64_ofs = mf->flow_be32ofs / 2;
 
     return (OVS_FORCE const ovs_be32 *)miniflow_get__(match->flow, u64_ofs)
@@ -2068,7 +2080,7 @@ static void
 trie_insert(struct cls_trie *trie, const struct cls_rule *rule, int mlen)
 {
     trie_insert_prefix(&trie->root,
-                       minimatch_get_prefix(&rule->match, trie->field), mlen);
+                       minimatch_get_prefix(&rule->match, &trie->field), mlen);
 }
 
 static void
@@ -2123,7 +2135,7 @@ static void
 trie_remove(struct cls_trie *trie, const struct cls_rule *rule, int mlen)
 {
     trie_remove_prefix(&trie->root,
-                       minimatch_get_prefix(&rule->match, trie->field), mlen);
+                       minimatch_get_prefix(&rule->match, &trie->field), mlen);
 }
 
 /* 'mlen' must be the (non-zero) CIDR prefix length of the 'trie->field' mask
diff --git a/lib/classifier.h b/lib/classifier.h
index d1bd4aa12a..f646a8f742 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -314,13 +314,15 @@ extern "C" {
 struct cls_subtable;
 struct cls_match;
 
+struct mf_field;
+typedef OVSRCU_TYPE(struct mf_field *) rcu_field_ptr;
 struct trie_node;
 typedef OVSRCU_TYPE(struct trie_node *) rcu_trie_ptr;
 
 /* Prefix trie for a 'field' */
 struct cls_trie {
-    const struct mf_field *field; /* Trie field, or NULL. */
-    rcu_trie_ptr root;            /* NULL if none. */
+    rcu_field_ptr field;   /* Trie field, or NULL. */
+    rcu_trie_ptr root;     /* NULL if none. */
 };
 
 enum {
diff --git a/lib/conntrack-icmp.c b/lib/conntrack-icmp.c
index 63246f0124..63ddd8038b 100644
--- a/lib/conntrack-icmp.c
+++ b/lib/conntrack-icmp.c
@@ -50,10 +50,16 @@ icmp_conn_update(struct conntrack *ct, struct conn *conn_,
                  struct dp_packet *pkt OVS_UNUSED, bool reply, long long now)
 {
     struct conn_icmp *conn = conn_icmp_cast(conn_);
-    conn->state = reply ? ICMPS_REPLY : ICMPS_FIRST;
-    conn_update_expiration(ct, &conn->up, icmp_timeouts[conn->state], now);
+    enum ct_update_res ret = CT_UPDATE_VALID;
+
+    if (reply && conn->state == ICMPS_FIRST) {
+       conn->state = ICMPS_REPLY;
+    } else if (conn->state == ICMPS_FIRST) {
+        ret = CT_UPDATE_VALID_NEW;
+    }
 
-    return CT_UPDATE_VALID;
+    conn_update_expiration(ct, &conn->up, icmp_timeouts[conn->state], now);
+    return ret;
 }
 
 static bool
diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
index 9a8ca39101..cd6c4bfee9 100644
--- a/lib/conntrack-private.h
+++ b/lib/conntrack-private.h
@@ -59,6 +59,9 @@ struct conn_key {
     uint8_t nw_proto;
 };
 
+/* Verify that nw_proto stays uint8_t as it's used to index into l4_protos[] */
+BUILD_ASSERT_DECL(MEMBER_SIZEOF(struct conn_key, nw_proto) == sizeof(uint8_t));
+
 /* This is used for alg expectations; an expectation is a
  * context created in preparation for establishing a data
  * connection. The expectation is created by the control
diff --git a/lib/conntrack-tcp.c b/lib/conntrack-tcp.c
index 416cb769d2..47261c7551 100644
--- a/lib/conntrack-tcp.c
+++ b/lib/conntrack-tcp.c
@@ -189,7 +189,7 @@ tcp_conn_update(struct conntrack *ct, struct conn *conn_,
         } else if (src->state <= CT_DPIF_TCPS_SYN_SENT) {
             src->state = CT_DPIF_TCPS_SYN_SENT;
             conn_update_expiration(ct, &conn->up, CT_TM_TCP_FIRST_PACKET, now);
-            return CT_UPDATE_NEW;
+            return CT_UPDATE_VALID_NEW;
         }
     }
 
diff --git a/lib/conntrack.c b/lib/conntrack.c
index ff5a89457c..4a26f370c3 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -44,6 +44,7 @@ VLOG_DEFINE_THIS_MODULE(conntrack);
 
 COVERAGE_DEFINE(conntrack_full);
 COVERAGE_DEFINE(conntrack_long_cleanup);
+COVERAGE_DEFINE(conntrack_lookup_natted_miss);
 
 struct conn_lookup_ctx {
     struct conn_key key;
@@ -143,12 +144,7 @@ detect_ftp_ctl_type(const struct conn_lookup_ctx *ctx,
 static void
 expectation_clean(struct conntrack *ct, const struct conn_key *master_key);
 
-static struct ct_l4_proto *l4_protos[] = {
-    [IPPROTO_TCP] = &ct_proto_tcp,
-    [IPPROTO_UDP] = &ct_proto_other,
-    [IPPROTO_ICMP] = &ct_proto_icmp4,
-    [IPPROTO_ICMPV6] = &ct_proto_icmp6,
-};
+static struct ct_l4_proto *l4_protos[UINT8_MAX + 1];
 
 static void
 handle_ftp_ctl(struct conntrack *ct, const struct conn_lookup_ctx *ctx,
@@ -296,6 +292,7 @@ ct_print_conn_info(const struct conn *c, const char *log_msg,
 struct conntrack *
 conntrack_init(void)
 {
+    static struct ovsthread_once setup_l4_once = OVSTHREAD_ONCE_INITIALIZER;
     struct conntrack *ct = xzalloc(sizeof *ct);
 
     ovs_rwlock_init(&ct->resources_lock);
@@ -322,6 +319,18 @@ conntrack_init(void)
     ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct);
     ct->ipf = ipf_init();
 
+    /* Initialize the l4 protocols. */
+    if (ovsthread_once_start(&setup_l4_once)) {
+        for (int i = 0; i < ARRAY_SIZE(l4_protos); i++) {
+            l4_protos[i] = &ct_proto_other;
+        }
+        /* IPPROTO_UDP uses ct_proto_other, so no need to initialize it. */
+        l4_protos[IPPROTO_TCP] = &ct_proto_tcp;
+        l4_protos[IPPROTO_ICMP] = &ct_proto_icmp4;
+        l4_protos[IPPROTO_ICMPV6] = &ct_proto_icmp6;
+
+        ovsthread_once_done(&setup_l4_once);
+    }
     return ct;
 }
 
@@ -813,7 +822,7 @@ static void
 reverse_nat_packet(struct dp_packet *pkt, const struct conn *conn)
 {
     char *tail = dp_packet_tail(pkt);
-    uint8_t pad = dp_packet_l2_pad_size(pkt);
+    uint16_t pad = dp_packet_l2_pad_size(pkt);
     struct conn_key inner_key;
     const char *inner_l4 = NULL;
     uint16_t orig_l3_ofs = pkt->l3_ofs;
@@ -1269,6 +1278,34 @@ process_one_fast(uint16_t zone, const uint32_t *setmark,
     }
 }
 
+static void
+initial_conn_lookup(struct conntrack *ct, struct conn_lookup_ctx *ctx,
+                    long long now, bool natted)
+{
+    if (natted) {
+        /* If the packet has been already natted (e.g. a previous
+         * action took place), retrieve it performing a lookup of its
+         * reverse key. */
+        conn_key_reverse(&ctx->key);
+    }
+
+    conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply);
+
+    if (natted) {
+        if (OVS_LIKELY(ctx->conn)) {
+            ctx->reply = !ctx->reply;
+            ctx->key = ctx->reply ? ctx->conn->rev_key : ctx->conn->key;
+            ctx->hash = conn_key_hash(&ctx->key, ct->hash_basis);
+        } else {
+            /* A lookup failure does not necessarily imply that an
+             * error occurred, it may simply indicate that a conn got
+             * removed during the recirculation. */
+            COVERAGE_INC(conntrack_lookup_natted_miss);
+            conn_key_reverse(&ctx->key);
+        }
+    }
+}
+
 static void
 process_one(struct conntrack *ct, struct dp_packet *pkt,
             struct conn_lookup_ctx *ctx, uint16_t zone,
@@ -1277,8 +1314,14 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
             const struct nat_action_info_t *nat_action_info,
             ovs_be16 tp_src, ovs_be16 tp_dst, const char *helper)
 {
+    /* Reset ct_state whenever entering a new zone. */
+    if (pkt->md.ct_state && pkt->md.ct_zone != zone) {
+        pkt->md.ct_state = 0;
+    }
+
     bool create_new_conn = false;
-    conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply);
+    initial_conn_lookup(ct, ctx, now, !!(pkt->md.ct_state &
+                                         (CS_SRC_NAT | CS_DST_NAT)));
     struct conn *conn = ctx->conn;
 
     /* Delete found entry if in wrong direction. 'force' implies commit. */
@@ -1300,9 +1343,10 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
             conn_key_lookup(ct, &ctx->key, hash, now, &conn, &ctx->reply);
 
             if (!conn) {
-                pkt->md.ct_state |= CS_TRACKED | CS_INVALID;
+                pkt->md.ct_state |= CS_INVALID;
+                write_ct_md(pkt, zone, NULL, NULL, NULL);
                 char *log_msg = xasprintf("Missing master conn %p", rev_conn);
-                ct_print_conn_info(conn, log_msg, VLL_INFO, true, true);
+                ct_print_conn_info(rev_conn, log_msg, VLL_INFO, true, true);
                 free(log_msg);
                 return;
             }
@@ -1964,9 +2008,10 @@ extract_l4(struct conn_key *key, const void *data, size_t size, bool *related,
         return (!related || check_l4_icmp6(key, data, size, l3,
                 validate_checksum))
                && extract_l4_icmp6(key, data, size, related);
-    } else {
-        return false;
     }
+
+    /* For all other protocols we do not have L4 keys, so keep them zero. */
+    return true;
 }
 
 static bool
@@ -2249,8 +2294,8 @@ nat_select_range_tuple(struct conntrack *ct, const struct conn *conn,
               conn->nat_info->nat_action & NAT_ACTION_SRC_PORT
           ? true : false;
     union ct_addr first_addr = ct_addr;
-    bool pat_enabled = conn->key.nw_proto != IPPROTO_ICMP &&
-                       conn->key.nw_proto != IPPROTO_ICMPV6;
+    bool pat_enabled = conn->key.nw_proto == IPPROTO_TCP ||
+                       conn->key.nw_proto == IPPROTO_UDP;
 
     while (true) {
         if (conn->nat_info->nat_action & NAT_ACTION_SRC) {
diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c
index 8c2480e7ac..880352376e 100644
--- a/lib/ct-dpif.c
+++ b/lib/ct-dpif.c
@@ -889,3 +889,11 @@ ct_dpif_get_timeout_policy_name(struct dpif *dpif, uint32_t tp_id,
                 dpif, tp_id, dl_type, nw_proto, tp_name, is_generic)
             : EOPNOTSUPP);
 }
+
+int
+ct_dpif_get_features(struct dpif *dpif, enum ct_features *features)
+{
+    return (dpif->dpif_class->ct_get_features
+            ? dpif->dpif_class->ct_get_features(dpif, features)
+            : EOPNOTSUPP);
+}
diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
index 3e227d9e3b..ebd9ac9be5 100644
--- a/lib/ct-dpif.h
+++ b/lib/ct-dpif.h
@@ -269,6 +269,11 @@ struct ct_dpif_timeout_policy {
                                                  * timeout attribute values */
 };
 
+/* Conntrack Features. */
+enum ct_features {
+    CONNTRACK_F_ZERO_SNAT = 1 << 0,  /* All-zero SNAT support. */
+};
+
 int ct_dpif_dump_start(struct dpif *, struct ct_dpif_dump_state **,
                        const uint16_t *zone, int *);
 int ct_dpif_dump_next(struct ct_dpif_dump_state *, struct ct_dpif_entry *);
@@ -323,5 +328,6 @@ int ct_dpif_timeout_policy_dump_done(struct dpif *dpif, void *state);
 int ct_dpif_get_timeout_policy_name(struct dpif *dpif, uint32_t tp_id,
                                     uint16_t dl_type, uint8_t nw_proto,
                                     char **tp_name, bool *is_generic);
+int ct_dpif_get_features(struct dpif *dpif, enum ct_features *features);
 
 #endif /* CT_DPIF_H */
diff --git a/lib/daemon-unix.c b/lib/daemon-unix.c
index 7e48630f0e..4e2874c22e 100644
--- a/lib/daemon-unix.c
+++ b/lib/daemon-unix.c
@@ -285,6 +285,7 @@ fork_and_wait_for_startup(int *fdp, pid_t *child_pid)
                     VLOG_ERR("fork child died before signaling startup (%s)",
                              status_msg);
                     ret = -1;
+                    free(status_msg);
                 }
             } else if (retval < 0) {
                 VLOG_FATAL("waitpid failed (%s)", ovs_strerror(errno));
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
index 9f8991faad..4c14951d6a 100644
--- a/lib/dp-packet.h
+++ b/lib/dp-packet.h
@@ -81,7 +81,7 @@ struct dp_packet {
 
     /* All the following elements of this struct are copied in a single call
      * of memcpy in dp_packet_clone_with_headroom. */
-    uint8_t l2_pad_size;           /* Detected l2 padding size.
+    uint16_t l2_pad_size;          /* Detected l2 padding size.
                                     * Padding is non-pullable. */
     uint16_t l2_5_ofs;             /* MPLS label stack offset, or UINT16_MAX */
     uint16_t l3_ofs;               /* Network-level header offset,
@@ -118,8 +118,8 @@ void *dp_packet_resize_l2(struct dp_packet *, int increment);
 void *dp_packet_resize_l2_5(struct dp_packet *, int increment);
 static inline void *dp_packet_eth(const struct dp_packet *);
 static inline void dp_packet_reset_offsets(struct dp_packet *);
-static inline uint8_t dp_packet_l2_pad_size(const struct dp_packet *);
-static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint8_t);
+static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *);
+static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t);
 static inline void *dp_packet_l2_5(const struct dp_packet *);
 static inline void dp_packet_set_l2_5(struct dp_packet *, void *);
 static inline void *dp_packet_l3(const struct dp_packet *);
@@ -155,6 +155,7 @@ struct dp_packet *dp_packet_clone_data_with_headroom(const void *, size_t,
 void dp_packet_resize(struct dp_packet *b, size_t new_headroom,
                       size_t new_tailroom);
 static inline void dp_packet_delete(struct dp_packet *);
+static inline void dp_packet_swap(struct dp_packet *, struct dp_packet *);
 
 static inline void *dp_packet_at(const struct dp_packet *, size_t offset,
                                  size_t size);
@@ -212,6 +213,18 @@ dp_packet_delete(struct dp_packet *b)
     }
 }
 
+/* Swaps content of two packets. */
+static inline void
+dp_packet_swap(struct dp_packet *a, struct dp_packet *b)
+{
+    ovs_assert(a->source == DPBUF_MALLOC || a->source == DPBUF_STUB);
+    ovs_assert(b->source == DPBUF_MALLOC || b->source == DPBUF_STUB);
+    struct dp_packet c = *a;
+
+    *a = *b;
+    *b = c;
+}
+
 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
  * byte 'offset'.  Otherwise, returns a null pointer. */
 static inline void *
@@ -327,14 +340,14 @@ dp_packet_reset_offsets(struct dp_packet *b)
     b->l4_ofs = UINT16_MAX;
 }
 
-static inline uint8_t
+static inline uint16_t
 dp_packet_l2_pad_size(const struct dp_packet *b)
 {
     return b->l2_pad_size;
 }
 
 static inline void
-dp_packet_set_l2_pad_size(struct dp_packet *b, uint8_t pad_size)
+dp_packet_set_l2_pad_size(struct dp_packet *b, uint16_t pad_size)
 {
     ovs_assert(pad_size <= dp_packet_size(b));
     b->l2_pad_size = pad_size;
@@ -950,7 +963,6 @@ enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */
 struct dp_packet_batch {
     size_t count;
     bool trunc; /* true if the batch needs truncate. */
-    bool do_not_steal; /* Indicate that the packets should not be stolen. */
     struct dp_packet *packets[NETDEV_MAX_BURST];
 };
 
@@ -959,7 +971,6 @@ dp_packet_batch_init(struct dp_packet_batch *batch)
 {
     batch->count = 0;
     batch->trunc = false;
-    batch->do_not_steal = false;
 }
 
 static inline void
diff --git a/lib/dpctl.c b/lib/dpctl.c
index db2b1f8961..36038a13d8 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1031,7 +1031,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
     memset(&dump_types, 0, sizeof dump_types);
     error = populate_dump_types(types_list, &dump_types, dpctl_p);
     if (error) {
-        goto out_free;
+        goto out_dpifclose;
     }
     determine_dpif_flow_dump_types(&dump_types, &dpif_dump_types);
 
@@ -2502,15 +2502,16 @@ static const struct dpctl_command all_commands[] = {
     { "del-if", "dp iface...", 2, INT_MAX, dpctl_del_if, DP_RW },
     { "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW },
     { "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO },
-    { "show", "[dp...]", 0, INT_MAX, dpctl_show, DP_RO },
-    { "dump-flows", "[dp] [filter=..] [type=..]",
-      0, 3, dpctl_dump_flows, DP_RO },
+    { "show", "[-s] [dp...]", 0, INT_MAX, dpctl_show, DP_RO },
+    { "dump-flows", "[-m] [--names] [dp] [filter=..] [type=..]",
+      0, 5, dpctl_dump_flows, DP_RO },
     { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW },
     { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW },
     { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO },
     { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow, DP_RW },
     { "del-flows", "[dp]", 0, 1, dpctl_del_flows, DP_RW },
-    { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack, DP_RO },
+    { "dump-conntrack", "[-m] [-s] [dp] [zone=N]",
+      0, 4, dpctl_dump_conntrack, DP_RO },
     { "flush-conntrack", "[dp] [zone=N] [ct-tuple]", 0, 3,
       dpctl_flush_conntrack, DP_RW },
     { "ct-stats-show", "[dp] [zone=N]",
diff --git a/lib/dpif-netdev-private.h b/lib/dpif-netdev-private.h
index 68c33a0f96..9b251f81fa 100644
--- a/lib/dpif-netdev-private.h
+++ b/lib/dpif-netdev-private.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
- * Copyright (c) 2019 Intel Corperation.
+ * Copyright (c) 2019 Intel Corporation.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index d393aab5e3..a73102ea98 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -83,9 +83,9 @@
 VLOG_DEFINE_THIS_MODULE(dpif_netdev);
 
 /* Auto Load Balancing Defaults */
-#define ALB_ACCEPTABLE_IMPROVEMENT       25
-#define ALB_PMD_LOAD_THRESHOLD           95
-#define ALB_PMD_REBALANCE_POLL_INTERVAL  1 /* 1 Min */
+#define ALB_IMPROVEMENT_THRESHOLD    25
+#define ALB_LOAD_THRESHOLD           95
+#define ALB_REBALANCE_INTERVAL       1 /* 1 Min */
 #define MIN_TO_MSEC                  60000
 
 #define FLOW_DUMP_MAX_BATCH 50
@@ -273,8 +273,9 @@ static bool dpcls_lookup(struct dpcls *cls,
     ( 1 << OFPMBT13_DROP )
 
 struct dp_meter_band {
-    struct ofputil_meter_band up; /* type, prec_level, pad, rate, burst_size */
-    uint32_t bucket; /* In 1/1000 packets (for PKTPS), or in bits (for KBPS) */
+    uint32_t rate;
+    uint32_t burst_size;
+    uint64_t bucket; /* In 1/1000 packets (for PKTPS), or in bits (for KBPS) */
     uint64_t packet_count;
     uint64_t byte_count;
 };
@@ -294,6 +295,8 @@ struct pmd_auto_lb {
     bool is_enabled;            /* Current status of Auto load balancing. */
     uint64_t rebalance_intvl;
     uint64_t rebalance_poll_timer;
+    uint8_t rebalance_improve_thresh;
+    atomic_uint8_t rebalance_load_thresh;
 };
 
 /* Datapath based on the network device interface from netdev.h.
@@ -481,6 +484,12 @@ struct dp_netdev_flow_stats {
     atomic_uint16_t tcp_flags;     /* Bitwise-OR of seen tcp_flags values. */
 };
 
+/* Contained by struct dp_netdev_flow's 'last_attrs' member.  */
+struct dp_netdev_flow_attrs {
+    atomic_bool offloaded;         /* True if flow is offloaded to HW. */
+    ATOMIC(const char *) dp_layer; /* DP layer the flow is handled in. */
+};
+
 /* A flow in 'dp_netdev_pmd_thread's 'flow_table'.
  *
  *
@@ -541,6 +550,11 @@ struct dp_netdev_flow {
     /* Statistics. */
     struct dp_netdev_flow_stats stats;
 
+    /* Statistics and attributes received from the netdev offload provider. */
+    atomic_int netdev_flow_get_result;
+    struct dp_netdev_flow_stats last_stats;
+    struct dp_netdev_flow_attrs last_attrs;
+
     /* Actions. */
     OVSRCU_TYPE(struct dp_netdev_actions *) actions;
 
@@ -2149,7 +2163,11 @@ dp_netdev_pmd_find_dpcls(struct dp_netdev_pmd_thread *pmd,
 }
 
 #define MAX_FLOW_MARK       (UINT32_MAX - 1)
-#define INVALID_FLOW_MARK   (UINT32_MAX)
+#define INVALID_FLOW_MARK   0
+/* Zero flow mark is used to indicate the HW to remove the mark. A packet
+ * marked with zero mark is received in SW without a mark at all, so it
+ * cannot be used as a valid mark.
+ */
 
 struct megaflow_to_mark_data {
     const struct cmap_node node;
@@ -2175,7 +2193,7 @@ flow_mark_alloc(void)
 
     if (!flow_mark.pool) {
         /* Haven't initiated yet, do it here */
-        flow_mark.pool = id_pool_create(0, MAX_FLOW_MARK);
+        flow_mark.pool = id_pool_create(1, MAX_FLOW_MARK);
     }
 
     if (id_pool_alloc_id(flow_mark.pool, &mark)) {
@@ -2280,6 +2298,12 @@ mark_to_flow_disassociate(struct dp_netdev_pmd_thread *pmd,
     struct cmap_node *mark_node = CONST_CAST(struct cmap_node *,
                                              &flow->mark_node);
 
+    /* INVALID_FLOW_MARK may mean that the flow has been disassociated or
+     * never associated. */
+    if (OVS_UNLIKELY(mark == INVALID_FLOW_MARK)) {
+        return EINVAL;
+    }
+
     cmap_remove(&flow_mark.mark_to_flow, mark_node, hash_int(mark, 0));
     flow->mark = INVALID_FLOW_MARK;
 
@@ -2401,7 +2425,8 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload)
     const struct dpif_class *dpif_class = pmd->dp->class;
     struct dp_netdev_flow *flow = offload->flow;
     odp_port_t in_port = flow->flow.in_port.odp_port;
-    bool modification = offload->op == DP_NETDEV_FLOW_OFFLOAD_OP_MOD;
+    bool modification = offload->op == DP_NETDEV_FLOW_OFFLOAD_OP_MOD
+                        && flow->mark != INVALID_FLOW_MARK;
     struct offload_info info;
     struct netdev *port;
     uint32_t mark;
@@ -2413,7 +2438,6 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload)
 
     if (modification) {
         mark = flow->mark;
-        ovs_assert(mark != INVALID_FLOW_MARK);
     } else {
         /*
          * If a mega flow has already been offloaded (from other PMD
@@ -2433,6 +2457,7 @@ dp_netdev_flow_offload_put(struct dp_flow_offload_item *offload)
         mark = flow_mark_alloc();
         if (mark == INVALID_FLOW_MARK) {
             VLOG_ERR("Failed to allocate flow mark!\n");
+            return -1;
         }
     }
     info.flow_mark = mark;
@@ -2512,6 +2537,7 @@ dp_netdev_flow_offload_main(void *data OVS_UNUSED)
         VLOG_DBG("%s to %s netdev flow\n",
                  ret == 0 ? "succeed" : "failed", op);
         dp_netdev_free_flow_offload(offload);
+        ovsrcu_quiesce();
     }
 
     return NULL;
@@ -2538,10 +2564,9 @@ queue_netdev_flow_del(struct dp_netdev_pmd_thread *pmd,
 static void
 queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
                       struct dp_netdev_flow *flow, struct match *match,
-                      const struct nlattr *actions, size_t actions_len)
+                      const struct nlattr *actions, size_t actions_len, int op)
 {
     struct dp_flow_offload_item *offload;
-    int op;
 
     if (!netdev_is_flow_api_enabled()) {
         return;
@@ -2554,11 +2579,6 @@ queue_netdev_flow_put(struct dp_netdev_pmd_thread *pmd,
         ovsthread_once_done(&offload_thread_once);
     }
 
-    if (flow->mark != INVALID_FLOW_MARK) {
-        op = DP_NETDEV_FLOW_OFFLOAD_OP_MOD;
-    } else {
-        op = DP_NETDEV_FLOW_OFFLOAD_OP_ADD;
-    }
     offload = dp_netdev_alloc_flow_offload(pmd, flow, op);
     offload->match = *match;
     offload->actions = xmalloc(actions_len);
@@ -3032,9 +3052,56 @@ dp_netdev_pmd_find_flow(const struct dp_netdev_pmd_thread *pmd,
     return NULL;
 }
 
+static void
+dp_netdev_flow_set_last_stats_attrs(struct dp_netdev_flow *netdev_flow,
+                                    const struct dpif_flow_stats *stats,
+                                    const struct dpif_flow_attrs *attrs,
+                                    int result)
+{
+    struct dp_netdev_flow_stats *last_stats = &netdev_flow->last_stats;
+    struct dp_netdev_flow_attrs *last_attrs = &netdev_flow->last_attrs;
+
+    atomic_store_relaxed(&netdev_flow->netdev_flow_get_result, result);
+    if (result) {
+        return;
+    }
+
+    atomic_store_relaxed(&last_stats->used,         stats->used);
+    atomic_store_relaxed(&last_stats->packet_count, stats->n_packets);
+    atomic_store_relaxed(&last_stats->byte_count,   stats->n_bytes);
+    atomic_store_relaxed(&last_stats->tcp_flags,    stats->tcp_flags);
+
+    atomic_store_relaxed(&last_attrs->offloaded,    attrs->offloaded);
+    atomic_store_relaxed(&last_attrs->dp_layer,     attrs->dp_layer);
+
+}
+
+static void
+dp_netdev_flow_get_last_stats_attrs(struct dp_netdev_flow *netdev_flow,
+                                    struct dpif_flow_stats *stats,
+                                    struct dpif_flow_attrs *attrs,
+                                    int *result)
+{
+    struct dp_netdev_flow_stats *last_stats = &netdev_flow->last_stats;
+    struct dp_netdev_flow_attrs *last_attrs = &netdev_flow->last_attrs;
+
+    atomic_read_relaxed(&netdev_flow->netdev_flow_get_result, result);
+    if (*result) {
+        return;
+    }
+
+    atomic_read_relaxed(&last_stats->used,         &stats->used);
+    atomic_read_relaxed(&last_stats->packet_count, &stats->n_packets);
+    atomic_read_relaxed(&last_stats->byte_count,   &stats->n_bytes);
+    atomic_read_relaxed(&last_stats->tcp_flags,    &stats->tcp_flags);
+
+    atomic_read_relaxed(&last_attrs->offloaded,    &attrs->offloaded);
+    atomic_read_relaxed(&last_attrs->dp_layer,     &attrs->dp_layer);
+}
+
 static bool
 dpif_netdev_get_flow_offload_status(const struct dp_netdev *dp,
-                                    const struct dp_netdev_flow *netdev_flow,
+                                    struct dp_netdev_flow *netdev_flow,
                                     struct dpif_flow_stats *stats,
                                     struct dpif_flow_attrs *attrs)
 {
@@ -3056,11 +3123,31 @@ dpif_netdev_get_flow_offload_status(const struct dp_netdev *dp,
     }
     ofpbuf_use_stack(&buf, &act_buf, sizeof act_buf);
     /* Taking a global 'port_mutex' to fulfill thread safety
-     * restrictions for the netdev-offload-dpdk module. */
-    ovs_mutex_lock(&dp->port_mutex);
-    ret = netdev_flow_get(netdev, &match, &actions, &netdev_flow->mega_ufid,
-                          stats, attrs, &buf);
-    ovs_mutex_unlock(&dp->port_mutex);
+     * restrictions for the netdev-offload-dpdk module.
+     *
+     * XXX: Main thread will try to pause/stop all revalidators during datapath
+     *      reconfiguration via datapath purge callback (dp_purge_cb) while
+     *      holding 'dp->port_mutex'.  So we're not waiting for mutex here.
+     *      Otherwise, deadlock is possible, bcause revalidators might sleep
+     *      waiting for the main thread to release the lock and main thread
+     *      will wait for them to stop processing.
+     *      This workaround might make statistics less accurate. Especially
+     *      for flow deletion case, since there will be no other attempt.  */
+    if (!ovs_mutex_trylock(&dp->port_mutex)) {
+        ret = netdev_flow_get(netdev, &match, &actions,
+                              &netdev_flow->mega_ufid, stats, attrs, &buf);
+        /* Storing statistics and attributes from the last request for
+         * later use on mutex contention. */
+        dp_netdev_flow_set_last_stats_attrs(netdev_flow, stats, attrs, ret);
+        ovs_mutex_unlock(&dp->port_mutex);
+    } else {
+        dp_netdev_flow_get_last_stats_attrs(netdev_flow, stats, attrs, &ret);
+        if (!ret && !attrs->dp_layer) {
+            /* Flow was never reported as 'offloaded' so it's harmless
+             * to continue to think so. */
+            ret = EAGAIN;
+        }
+    }
     netdev_close(netdev);
     if (ret) {
         return false;
@@ -3329,6 +3416,9 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
     /* Do not allocate extra space. */
     flow = xmalloc(sizeof *flow - sizeof flow->cr.flow.mf + mask.len);
     memset(&flow->stats, 0, sizeof flow->stats);
+    atomic_init(&flow->netdev_flow_get_result, 0);
+    memset(&flow->last_stats, 0, sizeof flow->last_stats);
+    memset(&flow->last_attrs, 0, sizeof flow->last_attrs);
     flow->dead = false;
     flow->batch = NULL;
     flow->mark = INVALID_FLOW_MARK;
@@ -3360,7 +3450,8 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd,
     cmap_insert(&pmd->flow_table, CONST_CAST(struct cmap_node *, &flow->node),
                 dp_netdev_flow_hash(&flow->ufid));
 
-    queue_netdev_flow_put(pmd, flow, match, actions, actions_len);
+    queue_netdev_flow_put(pmd, flow, match, actions, actions_len,
+                          DP_NETDEV_FLOW_OFFLOAD_OP_ADD);
 
     if (OVS_UNLIKELY(!VLOG_DROP_DBG((&upcall_rl)))) {
         struct ds ds = DS_EMPTY_INITIALIZER;
@@ -3450,7 +3541,8 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd,
             ovsrcu_set(&netdev_flow->actions, new_actions);
 
             queue_netdev_flow_put(pmd, netdev_flow, match,
-                                  put->actions, put->actions_len);
+                                  put->actions, put->actions_len,
+                                  DP_NETDEV_FLOW_OFFLOAD_OP_MOD);
 
             if (stats) {
                 get_dpif_flow_status(pmd->dp, netdev_flow, stats, NULL);
@@ -3506,6 +3598,15 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
         return error;
     }
 
+    if (match.wc.masks.in_port.odp_port != ODPP_NONE) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+
+        VLOG_ERR_RL(&rl, "failed to put%s flow: in_port is not an exact match",
+                    (put->flags & DPIF_FP_CREATE) ? "[create]"
+                    : (put->flags & DPIF_FP_MODIFY) ? "[modify]" : "[zero]");
+        return EINVAL;
+    }
+
     if (put->ufid) {
         ufid = *put->ufid;
     } else {
@@ -3830,8 +3931,10 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
                                flow_hash_5tuple(execute->flow, 0));
     }
 
-    dp_packet_batch_init_packet(&pp, execute->packet);
-    pp.do_not_steal = true;
+    /* Making a copy because the packet might be stolen during the execution
+     * and caller might still need it.  */
+    struct dp_packet *packet_clone = dp_packet_clone(execute->packet);
+    dp_packet_batch_init_packet(&pp, packet_clone);
     dp_netdev_execute_actions(pmd, &pp, false, execute->flow,
                               execute->actions, execute->actions_len);
     dp_netdev_pmd_flush_output_packets(pmd, true);
@@ -3841,6 +3944,24 @@ dpif_netdev_execute(struct dpif *dpif, struct dpif_execute *execute)
         dp_netdev_pmd_unref(pmd);
     }
 
+    if (dp_packet_batch_size(&pp) == 1) {
+        /* Packet wasn't dropped during the execution.  Swapping content with
+         * the original packet, because the caller might expect actions to
+         * modify it.  Uisng the packet from a batch instead of 'packet_clone'
+         * because it maybe stolen and replaced by other packet, e.g. by
+         * the fragmentation engine. */
+        dp_packet_swap(execute->packet, pp.packets[0]);
+        dp_packet_delete_batch(&pp, true);
+    } else if (dp_packet_batch_size(&pp)) {
+        /* FIXME: We have more packets than expected.  Likely, we got IP
+         * fragments of the reassembled packet.  Dropping them here as we have
+         * no way to get them to the caller.  It might be that all the required
+         * actions with them are already executed, but it also might not be a
+         * case, e.g. if dpif_netdev_execute() called to execute a single
+         * tunnel push. */
+        dp_packet_delete_batch(&pp, true);
+    }
+
     return 0;
 }
 
@@ -3875,11 +3996,12 @@ dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops,
 
 /* Enable or Disable PMD auto load balancing. */
 static void
-set_pmd_auto_lb(struct dp_netdev *dp)
+set_pmd_auto_lb(struct dp_netdev *dp, bool always_log)
 {
     unsigned int cnt = 0;
     struct dp_netdev_pmd_thread *pmd;
     struct pmd_auto_lb *pmd_alb = &dp->pmd_alb;
+    uint8_t rebalance_load_thresh;
 
     bool enable_alb = false;
     bool multi_rxq = false;
@@ -3906,18 +4028,24 @@ set_pmd_auto_lb(struct dp_netdev *dp)
     enable_alb = enable_alb && pmd_rxq_assign_cyc &&
                     pmd_alb->auto_lb_requested;
 
-    if (pmd_alb->is_enabled != enable_alb) {
+    if (pmd_alb->is_enabled != enable_alb || always_log) {
         pmd_alb->is_enabled = enable_alb;
         if (pmd_alb->is_enabled) {
+            atomic_read_relaxed(&pmd_alb->rebalance_load_thresh,
+                                &rebalance_load_thresh);
             VLOG_INFO("PMD auto load balance is enabled "
-                      "(with rebalance interval:%"PRIu64" msec)",
-                       pmd_alb->rebalance_intvl);
+                      "interval %"PRIu64" mins, "
+                      "pmd load threshold %"PRIu8"%%, "
+                      "improvement threshold %"PRIu8"%%",
+                       pmd_alb->rebalance_intvl / MIN_TO_MSEC,
+                       rebalance_load_thresh,
+                       pmd_alb->rebalance_improve_thresh);
+
         } else {
             pmd_alb->rebalance_poll_timer = 0;
             VLOG_INFO("PMD auto load balance is disabled");
         }
     }
-
 }
 
 /* Applies datapath configuration from the database. Some of the changes are
@@ -3935,6 +4063,9 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
     uint32_t insert_min, cur_min;
     uint32_t tx_flush_interval, cur_tx_flush_interval;
     uint64_t rebalance_intvl;
+    uint8_t rebalance_load, cur_rebalance_load;
+    uint8_t rebalance_improve;
+    bool log_autolb = false;
 
     tx_flush_interval = smap_get_int(other_config, "tx-flush-interval",
                                      DEFAULT_TX_FLUSH_INTERVAL);
@@ -4012,7 +4143,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
                               false);
 
     rebalance_intvl = smap_get_int(other_config, "pmd-auto-lb-rebal-interval",
-                              ALB_PMD_REBALANCE_POLL_INTERVAL);
+                                   ALB_REBALANCE_INTERVAL);
 
     /* Input is in min, convert it to msec. */
     rebalance_intvl =
@@ -4020,9 +4151,38 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
 
     if (pmd_alb->rebalance_intvl != rebalance_intvl) {
         pmd_alb->rebalance_intvl = rebalance_intvl;
-    }
-
-    set_pmd_auto_lb(dp);
+        VLOG_INFO("PMD auto load balance interval set to "
+                  "%"PRIu64" mins\n", rebalance_intvl / MIN_TO_MSEC);
+        log_autolb = true;
+    }
+
+    rebalance_improve = smap_get_int(other_config,
+                                     "pmd-auto-lb-improvement-threshold",
+                                     ALB_IMPROVEMENT_THRESHOLD);
+    if (rebalance_improve > 100) {
+        rebalance_improve = ALB_IMPROVEMENT_THRESHOLD;
+    }
+    if (rebalance_improve != pmd_alb->rebalance_improve_thresh) {
+        pmd_alb->rebalance_improve_thresh = rebalance_improve;
+        VLOG_INFO("PMD auto load balance improvement threshold set to "
+                  "%"PRIu8"%%", rebalance_improve);
+        log_autolb = true;
+    }
+
+    rebalance_load = smap_get_int(other_config, "pmd-auto-lb-load-threshold",
+                                  ALB_LOAD_THRESHOLD);
+    if (rebalance_load > 100) {
+        rebalance_load = ALB_LOAD_THRESHOLD;
+    }
+    atomic_read_relaxed(&pmd_alb->rebalance_load_thresh, &cur_rebalance_load);
+    if (rebalance_load != cur_rebalance_load) {
+        atomic_store_relaxed(&pmd_alb->rebalance_load_thresh,
+                             rebalance_load);
+        VLOG_INFO("PMD auto load balance load threshold set to %"PRIu8"%%",
+                  rebalance_load);
+        log_autolb = true;
+    }
+    set_pmd_auto_lb(dp, log_autolb);
     return 0;
 }
 
@@ -4493,6 +4653,12 @@ struct rr_numa {
     bool idx_inc;
 };
 
+static size_t
+rr_numa_list_count(struct rr_numa_list *rr)
+{
+    return hmap_count(&rr->numas);
+}
+
 static struct rr_numa *
 rr_numa_list_lookup(struct rr_numa_list *rr, int numa_id)
 {
@@ -4940,9 +5106,17 @@ reconfigure_datapath(struct dp_netdev *dp)
 
     /* Check for all the ports that need reconfiguration.  We cache this in
      * 'port->need_reconfigure', because netdev_is_reconf_required() can
-     * change at any time. */
+     * change at any time.
+     * Also mark for reconfiguration all ports which will likely change their
+     * 'dynamic_txqs' parameter.  It's required to stop using them before
+     * changing this setting and it's simpler to mark ports here and allow
+     * 'pmd_remove_stale_ports' to remove them from threads.  There will be
+     * no actual reconfiguration in 'port_reconfigure' because it's
+     * unnecessary.  */
     HMAP_FOR_EACH (port, node, &dp->ports) {
-        if (netdev_is_reconf_required(port->netdev)) {
+        if (netdev_is_reconf_required(port->netdev)
+            || (port->dynamic_txqs
+                != (netdev_n_txq(port->netdev) < wanted_txqs))) {
             port->need_reconfigure = true;
         }
     }
@@ -5076,7 +5250,7 @@ reconfigure_datapath(struct dp_netdev *dp)
     reload_affected_pmds(dp);
 
     /* Check if PMD Auto LB is to be enabled */
-    set_pmd_auto_lb(dp);
+    set_pmd_auto_lb(dp, false);
 }
 
 /* Returns true if one of the netdevs in 'dp' requires a reconfiguration */
@@ -5189,10 +5363,17 @@ get_dry_run_variance(struct dp_netdev *dp, uint32_t *core_list,
     for (int i = 0; i < n_rxqs; i++) {
         int numa_id = netdev_get_numa_id(rxqs[i]->port->netdev);
         numa = rr_numa_list_lookup(&rr, numa_id);
+        /* If there is no available pmd on the local numa but there is only one
+         * numa for cross-numa polling, we can estimate the dry run. */
+        if (!numa && rr_numa_list_count(&rr) == 1) {
+            numa = rr_numa_list_next(&rr, NULL);
+        }
         if (!numa) {
-            /* Abort if cross NUMA polling. */
-            VLOG_DBG("PMD auto lb dry run."
-                     " Aborting due to cross-numa polling.");
+            VLOG_DBG("PMD auto lb dry run: "
+                     "There's no available (non-isolated) PMD thread on NUMA "
+                     "node %d for port '%s' and there are PMD threads on more "
+                     "than one NUMA node available for cross-NUMA polling. "
+                     "Aborting.", numa_id, netdev_rxq_get_name(rxqs[i]->rx));
             goto cleanup;
         }
 
@@ -5320,7 +5501,7 @@ pmd_rebalance_dry_run(struct dp_netdev *dp)
             improvement =
                 ((curr_variance - new_variance) * 100) / curr_variance;
         }
-        if (improvement < ALB_ACCEPTABLE_IMPROVEMENT) {
+        if (improvement < dp->pmd_alb.rebalance_improve_thresh) {
             ret = false;
         }
     }
@@ -5787,12 +5968,14 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_,
     /* Update all bands and find the one hit with the highest rate for each
      * packet (if any). */
     for (int m = 0; m < meter->n_bands; ++m) {
-        band = &meter->bands[m];
+        uint64_t max_bucket_size;
 
+        band = &meter->bands[m];
+        max_bucket_size = band->burst_size * 1000ULL;
         /* Update band's bucket. */
-        band->bucket += delta_t * band->up.rate;
-        if (band->bucket > band->up.burst_size) {
-            band->bucket = band->up.burst_size;
+        band->bucket += (uint64_t) delta_t * band->rate;
+        if (band->bucket > max_bucket_size) {
+            band->bucket = max_bucket_size;
         }
 
         /* Drain the bucket for all the packets, if possible. */
@@ -5810,8 +5993,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_,
                  * (Only one band will be fired by a packet, and that
                  * can be different for each packet.) */
                 for (int i = band_exceeded_pkt; i < cnt; i++) {
-                    if (band->up.rate > exceeded_rate[i]) {
-                        exceeded_rate[i] = band->up.rate;
+                    if (band->rate > exceeded_rate[i]) {
+                        exceeded_rate[i] = band->rate;
                         exceeded_band[i] = m;
                     }
                 }
@@ -5830,8 +6013,8 @@ dp_netdev_run_meter(struct dp_netdev *dp, struct dp_packet_batch *packets_,
                         /* Update the exceeding band for the exceeding packet.
                          * (Only one band will be fired by a packet, and that
                          * can be different for each packet.) */
-                        if (band->up.rate > exceeded_rate[i]) {
-                            exceeded_rate[i] = band->up.rate;
+                        if (band->rate > exceeded_rate[i]) {
+                            exceeded_rate[i] = band->rate;
                             exceeded_band[i] = m;
                         }
                     }
@@ -5913,16 +6096,14 @@ dpif_netdev_meter_set(struct dpif *dpif, ofproto_meter_id meter_id,
             config->bands[i].burst_size = config->bands[i].rate;
         }
 
-        meter->bands[i].up = config->bands[i];
-        /* Convert burst size to the bucket units: */
-        /* pkts => 1/1000 packets, kilobits => bits. */
-        meter->bands[i].up.burst_size *= 1000;
-        /* Initialize bucket to empty. */
-        meter->bands[i].bucket = 0;
+        meter->bands[i].rate = config->bands[i].rate;
+        meter->bands[i].burst_size = config->bands[i].burst_size;
+        /* Start with a full bucket. */
+        meter->bands[i].bucket = meter->bands[i].burst_size * 1000ULL;
 
         /* Figure out max delta_t that is enough to fill any bucket. */
         band_max_delta_t
-            = meter->bands[i].up.burst_size / meter->bands[i].up.rate;
+            = meter->bands[i].bucket / meter->bands[i].rate;
         if (band_max_delta_t > meter->max_delta_t) {
             meter->max_delta_t = band_max_delta_t;
         }
@@ -7800,6 +7981,7 @@ const struct dpif_class dpif_netdev_class = {
     NULL,                       /* ct_timeout_policy_dump_next */
     NULL,                       /* ct_timeout_policy_dump_done */
     NULL,                       /* ct_get_timeout_policy_name */
+    NULL,                       /* ct_get_features */
     dpif_netdev_ipf_set_enabled,
     dpif_netdev_ipf_set_min_frag,
     dpif_netdev_ipf_set_max_nfrags,
@@ -8040,6 +8222,7 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
 
     if (pmd->ctx.now > pmd->rxq_next_cycle_store) {
         uint64_t curr_tsc;
+        uint8_t rebalance_load_trigger;
         struct pmd_auto_lb *pmd_alb = &pmd->dp->pmd_alb;
         if (pmd_alb->is_enabled && !pmd->isolated
             && (pmd->perf_stats.counters.n[PMD_CYCLES_ITER_IDLE] >=
@@ -8056,7 +8239,9 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
                 pmd_load = ((tot_proc * 100) / (tot_idle + tot_proc));
             }
 
-            if (pmd_load >= ALB_PMD_LOAD_THRESHOLD) {
+            atomic_read_relaxed(&pmd_alb->rebalance_load_thresh,
+                                &rebalance_load_trigger);
+            if (pmd_load >= rebalance_load_trigger) {
                 atomic_count_inc(&pmd->pmd_overloaded);
             } else {
                 atomic_count_set(&pmd->pmd_overloaded, 0);
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 5b5c96d727..2c6c23c645 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -691,6 +691,7 @@ dpif_netlink_set_features(struct dpif *dpif_, uint32_t new_features)
 
     dpif_netlink_dp_init(&request);
     request.cmd = OVS_DP_CMD_SET;
+    request.name = dpif_->base_name;
     request.dp_ifindex = dpif->dp_ifindex;
     request.user_features = dpif->user_features | new_features;
 
@@ -2046,6 +2047,7 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
     uint8_t csum_on = false;
     int err;
 
+    info.tc_modify_flow_deleted = false;
     if (put->flags & DPIF_FP_PROBE) {
         return EOPNOTSUPP;
     }
@@ -2141,7 +2143,11 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
 out:
     if (err && err != EEXIST && (put->flags & DPIF_FP_MODIFY)) {
         /* Modified rule can't be offloaded, try and delete from HW */
-        int del_err = netdev_flow_del(dev, put->ufid, put->stats);
+        int del_err = 0;
+
+        if (!info.tc_modify_flow_deleted) {
+            del_err = netdev_flow_del(dev, put->ufid, put->stats);
+        }
 
         if (!del_err) {
             /* Delete from hw success, so old flow was offloaded.
@@ -2902,8 +2908,6 @@ dpif_netlink_ct_set_limits(struct dpif *dpif OVS_UNUSED,
                            const uint32_t *default_limits,
                            const struct ovs_list *zone_limits)
 {
-    struct ovs_zone_limit req_zone_limit;
-
     if (ovs_ct_limit_family < 0) {
         return EOPNOTSUPP;
     }
@@ -2920,8 +2924,10 @@ dpif_netlink_ct_set_limits(struct dpif *dpif OVS_UNUSED,
     size_t opt_offset;
     opt_offset = nl_msg_start_nested(request, OVS_CT_LIMIT_ATTR_ZONE_LIMIT);
     if (default_limits) {
-        req_zone_limit.zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE;
-        req_zone_limit.limit = *default_limits;
+        struct ovs_zone_limit req_zone_limit = {
+            .zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE,
+            .limit   = *default_limits,
+        };
         nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit);
     }
 
@@ -2929,8 +2935,10 @@ dpif_netlink_ct_set_limits(struct dpif *dpif OVS_UNUSED,
         struct ct_dpif_zone_limit *zone_limit;
 
         LIST_FOR_EACH (zone_limit, node, zone_limits) {
-            req_zone_limit.zone_id = zone_limit->zone;
-            req_zone_limit.limit = zone_limit->limit;
+            struct ovs_zone_limit req_zone_limit = {
+                .zone_id = zone_limit->zone,
+                .limit   = zone_limit->limit,
+            };
             nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit);
         }
     }
@@ -3014,8 +3022,9 @@ dpif_netlink_ct_get_limits(struct dpif *dpif OVS_UNUSED,
         size_t opt_offset = nl_msg_start_nested(request,
                                                 OVS_CT_LIMIT_ATTR_ZONE_LIMIT);
 
-        struct ovs_zone_limit req_zone_limit;
-        req_zone_limit.zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE;
+        struct ovs_zone_limit req_zone_limit = {
+            .zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE,
+        };
         nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit);
 
         struct ct_dpif_zone_limit *zone_limit;
@@ -3065,8 +3074,9 @@ dpif_netlink_ct_del_limits(struct dpif *dpif OVS_UNUSED,
 
         struct ct_dpif_zone_limit *zone_limit;
         LIST_FOR_EACH (zone_limit, node, zone_limits) {
-            struct ovs_zone_limit req_zone_limit;
-            req_zone_limit.zone_id = zone_limit->zone;
+            struct ovs_zone_limit req_zone_limit = {
+                .zone_id = zone_limit->zone,
+            };
             nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit);
         }
         nl_msg_end_nested(request, opt_offset);
@@ -3140,6 +3150,20 @@ dpif_netlink_ct_get_timeout_policy_name(struct dpif *dpif OVS_UNUSED,
     return 0;
 }
 
+static int
+dpif_netlink_ct_get_features(struct dpif *dpif OVS_UNUSED,
+                             enum ct_features *features)
+{
+    if (features != NULL) {
+#ifndef _WIN32
+        *features = CONNTRACK_F_ZERO_SNAT;
+#else
+        *features = 0;
+#endif
+    }
+    return 0;
+}
+
 #define CT_DPIF_NL_TP_TCP_MAPPINGS                              \
     CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_SENT, SYN_SENT)         \
     CT_DPIF_NL_TP_MAPPING(TCP, TCP, SYN_RECV, SYN_RECV)         \
@@ -3982,6 +4006,7 @@ const struct dpif_class dpif_netlink_class = {
     dpif_netlink_ct_timeout_policy_dump_next,
     dpif_netlink_ct_timeout_policy_dump_done,
     dpif_netlink_ct_get_timeout_policy_name,
+    dpif_netlink_ct_get_features,
     NULL,                       /* ipf_set_enabled */
     NULL,                       /* ipf_set_min_frag */
     NULL,                       /* ipf_set_max_nfrags */
@@ -4638,7 +4663,7 @@ report_loss(struct dpif_netlink *dpif, struct dpif_channel *ch, uint32_t ch_idx,
                       time_msec() - ch->last_poll);
     }
 
-    VLOG_WARN("%s: lost packet on port channel %u of handler %u",
-              dpif_name(&dpif->dpif), ch_idx, handler_id);
+    VLOG_WARN("%s: lost packet on port channel %u of handler %u%s",
+              dpif_name(&dpif->dpif), ch_idx, handler_id, ds_cstr(&s));
     ds_destroy(&s);
 }
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index b77317bca1..9941c9ba8a 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -81,6 +81,7 @@ struct ct_dpif_dump_state;
 struct ct_dpif_entry;
 struct ct_dpif_tuple;
 struct ct_dpif_timeout_policy;
+enum ct_features;
 
 /* 'dpif_ipf_proto_status' and 'dpif_ipf_status' are presently in
  * sync with 'ipf_proto_status' and 'ipf_status', but more
@@ -562,6 +563,10 @@ struct dpif_class {
                                       uint16_t dl_type, uint8_t nw_proto,
                                       char **tp_name, bool *is_generic);
 
+    /* Stores the conntrack features supported by 'dpif' into features.
+     * The value is a bitmap of CONNTRACK_F_* bits. */
+    int (*ct_get_features)(struct dpif *, enum ct_features *features);
+
     /* IP Fragmentation. */
 
     /* Disables or enables conntrack fragment reassembly.  The default
diff --git a/lib/dpif.c b/lib/dpif.c
index 9d9c716c13..1847689114 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1235,6 +1235,7 @@ dpif_execute_helper_cb(void *aux_, struct dp_packet_batch *packets_,
         execute.needs_help = false;
         execute.probe = false;
         execute.mtu = 0;
+        execute.hash = 0;
         aux->error = dpif_execute(aux->dpif, &execute);
         log_execute_message(aux->dpif, &this_module, &execute,
                             true, aux->error);
diff --git a/lib/dpif.h b/lib/dpif.h
index 4df8f7c8b7..31d3139845 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -725,7 +725,7 @@ struct dpif_execute {
     bool probe;                     /* Suppress error messages. */
     unsigned int mtu;               /* Maximum transmission unit to fragment.
                                        0 if not a fragmented packet */
-    uint64_t hash;
+    uint64_t hash;                  /* Packet flow hash. 0 if not specified. */
     const struct flow *flow;         /* Flow extracted from 'packet'. */
 
     /* Input, but possibly modified as a side effect of execution. */
diff --git a/lib/dynamic-string.c b/lib/dynamic-string.c
index 6f7b610a99..fd0127ed17 100644
--- a/lib/dynamic-string.c
+++ b/lib/dynamic-string.c
@@ -460,6 +460,10 @@ ds_chomp(struct ds *ds, int c)
 void
 ds_clone(struct ds *dst, struct ds *source)
 {
+    if (!source->allocated) {
+        ds_init(dst);
+        return;
+    }
     dst->length = source->length;
     dst->allocated = dst->length;
     dst->string = xmalloc(dst->allocated + 1);
diff --git a/lib/flow.c b/lib/flow.c
index 45bb96b543..353d5cd3ed 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -655,7 +655,7 @@ ipv4_sanity_check(const struct ip_header *nh, size_t size,
 
     tot_len = ntohs(nh->ip_tot_len);
     if (OVS_UNLIKELY(tot_len > size || ip_len > tot_len ||
-                size - tot_len > UINT8_MAX)) {
+                size - tot_len > UINT16_MAX)) {
         return false;
     }
 
@@ -693,8 +693,8 @@ ipv6_sanity_check(const struct ovs_16aligned_ip6_hdr *nh, size_t size)
     if (OVS_UNLIKELY(plen + IPV6_HEADER_LEN > size)) {
         return false;
     }
-    /* Jumbo Payload option not supported yet. */
-    if (OVS_UNLIKELY(size - (plen + IPV6_HEADER_LEN) > UINT8_MAX)) {
+
+    if (OVS_UNLIKELY(size - (plen + IPV6_HEADER_LEN) > UINT16_MAX)) {
         return false;
     }
 
diff --git a/lib/ipf.c b/lib/ipf.c
index 446e89d13c..009f5d1e9b 100644
--- a/lib/ipf.c
+++ b/lib/ipf.c
@@ -93,7 +93,6 @@ struct ipf_frag {
     struct dp_packet *pkt;
     uint16_t start_data_byte;
     uint16_t end_data_byte;
-    bool dnsteal; /* 'do not steal': if true, ipf should not free packet. */
 };
 
 /* The key for a collection of fragments potentially making up an unfragmented
@@ -795,8 +794,7 @@ ipf_is_frag_duped(const struct ipf_frag *frag_list, int last_inuse_idx,
 static bool
 ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list,
                  struct dp_packet *pkt, uint16_t start_data_byte,
-                 uint16_t end_data_byte, bool ff, bool lf, bool v6,
-                 bool dnsteal)
+                 uint16_t end_data_byte, bool ff, bool lf, bool v6)
     OVS_REQUIRES(ipf->ipf_lock)
 {
     bool duped_frag = ipf_is_frag_duped(ipf_list->frag_list,
@@ -811,10 +809,9 @@ ipf_process_frag(struct ipf *ipf, struct ipf_list *ipf_list,
              * recommend not setting the mempool number of buffers too low
              * and also clamp the number of fragments. */
             struct ipf_frag *frag = &ipf_list->frag_list[last_inuse_idx + 1];
-            frag->pkt = pkt;
+            frag->pkt = dp_packet_clone(pkt);
             frag->start_data_byte = start_data_byte;
             frag->end_data_byte = end_data_byte;
-            frag->dnsteal = dnsteal;
             ipf_list->last_inuse_idx++;
             atomic_count_inc(&ipf->nfrag);
             ipf_count(ipf, v6, IPF_NFRAGS_ACCEPTED);
@@ -851,8 +848,7 @@ ipf_list_init(struct ipf_list *ipf_list, struct ipf_list_key *key,
  * to a list of fragemnts. */
 static bool
 ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type,
-                uint16_t zone, long long now, uint32_t hash_basis,
-                bool dnsteal)
+                uint16_t zone, long long now, uint32_t hash_basis)
     OVS_REQUIRES(ipf->ipf_lock)
 {
     struct ipf_list_key key;
@@ -921,7 +917,7 @@ ipf_handle_frag(struct ipf *ipf, struct dp_packet *pkt, ovs_be16 dl_type,
     }
 
     return ipf_process_frag(ipf, ipf_list, pkt, start_data_byte,
-                            end_data_byte, ff, lf, v6, dnsteal);
+                            end_data_byte, ff, lf, v6);
 }
 
 /* Filters out fragments from a batch of fragments and adjust the batch. */
@@ -942,9 +938,10 @@ ipf_extract_frags_from_batch(struct ipf *ipf, struct dp_packet_batch *pb,
                           ipf_is_valid_v6_frag(ipf, pkt)))) {
 
             ovs_mutex_lock(&ipf->ipf_lock);
-            if (!ipf_handle_frag(ipf, pkt, dl_type, zone, now, hash_basis,
-                                 pb->do_not_steal)) {
+            if (!ipf_handle_frag(ipf, pkt, dl_type, zone, now, hash_basis)) {
                 dp_packet_batch_refill(pb, pkt, pb_idx);
+            } else {
+                dp_packet_delete(pkt);
             }
             ovs_mutex_unlock(&ipf->ipf_lock);
         } else {
@@ -1153,59 +1150,64 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
         /* Inner batch loop is constant time since batch size is <=
          * NETDEV_MAX_BURST. */
         DP_PACKET_BATCH_REFILL_FOR_EACH (pb_idx, pb_cnt, pkt, pb) {
-            if (pkt == rp->list->reass_execute_ctx) {
+            if (rp && pkt == rp->list->reass_execute_ctx) {
+                const struct ipf_frag *frag_0 = &rp->list->frag_list[0];
+                void *l4_frag = dp_packet_l4(frag_0->pkt);
+                void *l4_reass = dp_packet_l4(pkt);
+                memcpy(l4_frag, l4_reass, dp_packet_l4_size(frag_0->pkt));
+
                 for (int i = 0; i <= rp->list->last_inuse_idx; i++) {
-                    rp->list->frag_list[i].pkt->md.ct_label = pkt->md.ct_label;
-                    rp->list->frag_list[i].pkt->md.ct_mark = pkt->md.ct_mark;
-                    rp->list->frag_list[i].pkt->md.ct_state = pkt->md.ct_state;
-                    rp->list->frag_list[i].pkt->md.ct_zone = pkt->md.ct_zone;
-                    rp->list->frag_list[i].pkt->md.ct_orig_tuple_ipv6 =
+                    const struct ipf_frag *frag_i = &rp->list->frag_list[i];
+
+                    frag_i->pkt->md.ct_label = pkt->md.ct_label;
+                    frag_i->pkt->md.ct_mark = pkt->md.ct_mark;
+                    frag_i->pkt->md.ct_state = pkt->md.ct_state;
+                    frag_i->pkt->md.ct_zone = pkt->md.ct_zone;
+                    frag_i->pkt->md.ct_orig_tuple_ipv6 =
                         pkt->md.ct_orig_tuple_ipv6;
                     if (pkt->md.ct_orig_tuple_ipv6) {
-                        rp->list->frag_list[i].pkt->md.ct_orig_tuple.ipv6 =
+                        frag_i->pkt->md.ct_orig_tuple.ipv6 =
                             pkt->md.ct_orig_tuple.ipv6;
                     } else {
-                        rp->list->frag_list[i].pkt->md.ct_orig_tuple.ipv4  =
+                        frag_i->pkt->md.ct_orig_tuple.ipv4 =
                             pkt->md.ct_orig_tuple.ipv4;
                     }
-                }
-
-                const struct ipf_frag *frag_0 = &rp->list->frag_list[0];
-                void *l4_frag = dp_packet_l4(frag_0->pkt);
-                void *l4_reass = dp_packet_l4(pkt);
-                memcpy(l4_frag, l4_reass, dp_packet_l4_size(frag_0->pkt));
-
-                if (v6) {
-                    struct ovs_16aligned_ip6_hdr *l3_frag
-                        = dp_packet_l3(frag_0->pkt);
-                    struct ovs_16aligned_ip6_hdr *l3_reass = dp_packet_l3(pkt);
-                    l3_frag->ip6_src = l3_reass->ip6_src;
-                    l3_frag->ip6_dst = l3_reass->ip6_dst;
-                } else {
-                    struct ip_header *l3_frag = dp_packet_l3(frag_0->pkt);
-                    struct ip_header *l3_reass = dp_packet_l3(pkt);
-                    if (!dp_packet_hwol_is_ipv4(frag_0->pkt)) {
-                        ovs_be32 reass_ip =
-                            get_16aligned_be32(&l3_reass->ip_src);
-                        ovs_be32 frag_ip =
-                            get_16aligned_be32(&l3_frag->ip_src);
-
-                        l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
-                                                         frag_ip, reass_ip);
-                        reass_ip = get_16aligned_be32(&l3_reass->ip_dst);
-                        frag_ip = get_16aligned_be32(&l3_frag->ip_dst);
-                        l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
-                                                         frag_ip, reass_ip);
+                    if (v6) {
+                        struct ovs_16aligned_ip6_hdr *l3_frag
+                            = dp_packet_l3(frag_i->pkt);
+                        struct ovs_16aligned_ip6_hdr *l3_reass
+                            = dp_packet_l3(pkt);
+                        l3_frag->ip6_src = l3_reass->ip6_src;
+                        l3_frag->ip6_dst = l3_reass->ip6_dst;
+                    } else {
+                        struct ip_header *l3_frag = dp_packet_l3(frag_i->pkt);
+                        struct ip_header *l3_reass = dp_packet_l3(pkt);
+                        if (!dp_packet_hwol_is_ipv4(frag_i->pkt)) {
+                            ovs_be32 reass_ip =
+                                get_16aligned_be32(&l3_reass->ip_src);
+                            ovs_be32 frag_ip =
+                                get_16aligned_be32(&l3_frag->ip_src);
+
+                            l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
+                                                             frag_ip,
+                                                             reass_ip);
+                            reass_ip = get_16aligned_be32(&l3_reass->ip_dst);
+                            frag_ip = get_16aligned_be32(&l3_frag->ip_dst);
+                            l3_frag->ip_csum = recalc_csum32(l3_frag->ip_csum,
+                                                             frag_ip,
+                                                             reass_ip);
+                        }
+
+                        l3_frag->ip_src = l3_reass->ip_src;
+                        l3_frag->ip_dst = l3_reass->ip_dst;
                     }
-
-                    l3_frag->ip_src = l3_reass->ip_src;
-                    l3_frag->ip_dst = l3_reass->ip_dst;
                 }
 
                 ipf_completed_list_add(&ipf->frag_complete_list, rp->list);
                 ipf_reassembled_list_remove(rp);
                 dp_packet_delete(rp->pkt);
                 free(rp);
+                rp = NULL;
             } else {
                 dp_packet_batch_refill(pb, pkt, pb_idx);
             }
@@ -1337,9 +1339,7 @@ ipf_destroy(struct ipf *ipf)
         while (ipf_list->last_sent_idx < ipf_list->last_inuse_idx) {
             struct dp_packet *pkt
                 = ipf_list->frag_list[ipf_list->last_sent_idx + 1].pkt;
-            if (!ipf_list->frag_list[ipf_list->last_sent_idx + 1].dnsteal) {
-                dp_packet_delete(pkt);
-            }
+            dp_packet_delete(pkt);
             atomic_count_dec(&ipf->nfrag);
             ipf_list->last_sent_idx++;
         }
diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c
index ed748dbde7..e74771e2bc 100644
--- a/lib/jsonrpc.c
+++ b/lib/jsonrpc.c
@@ -50,6 +50,10 @@ struct jsonrpc {
     struct ovs_list output;     /* Contains "struct ofpbuf"s. */
     size_t output_count;        /* Number of elements in "output". */
     size_t backlog;
+
+    /* Limits. */
+    size_t max_output;          /* 'output_count' disconnection threshold. */
+    size_t max_backlog;         /* 'backlog' disconnection threshold. */
 };
 
 /* Rate limit for error messages. */
@@ -178,6 +182,17 @@ jsonrpc_get_backlog(const struct jsonrpc *rpc)
     return rpc->status ? 0 : rpc->backlog;
 }
 
+/* Sets thresholds for send backlog.  If send backlog contains more than
+ * 'max_n_msgs' messages or is larger than 'max_backlog_bytes' bytes,
+ * connection will be dropped. */
+void
+jsonrpc_set_backlog_threshold(struct jsonrpc *rpc,
+                              size_t max_n_msgs, size_t max_backlog_bytes)
+{
+    rpc->max_output = max_n_msgs;
+    rpc->max_backlog = max_backlog_bytes;
+}
+
 /* Returns the number of bytes that have been received on 'rpc''s underlying
  * stream.  (The value wraps around if it exceeds UINT_MAX.) */
 unsigned int
@@ -261,9 +276,26 @@ jsonrpc_send(struct jsonrpc *rpc, struct jsonrpc_msg *msg)
     rpc->backlog += length;
 
     if (rpc->output_count >= 50) {
-        VLOG_INFO_RL(&rl, "excessive sending backlog, jsonrpc: %s, num of"
+        static struct vlog_rate_limit bl_rl = VLOG_RATE_LIMIT_INIT(5, 5);
+        bool disconnect = false;
+
+        VLOG_INFO_RL(&bl_rl, "excessive sending backlog, jsonrpc: %s, num of"
                      " msgs: %"PRIuSIZE", backlog: %"PRIuSIZE".", rpc->name,
                      rpc->output_count, rpc->backlog);
+        if (rpc->max_output && rpc->output_count > rpc->max_output) {
+            disconnect = true;
+            VLOG_WARN("sending backlog exceeded maximum number of messages (%"
+                      PRIuSIZE" > %"PRIuSIZE"), disconnecting, jsonrpc: %s.",
+                      rpc->output_count, rpc->max_output, rpc->name);
+        } else if (rpc->max_backlog && rpc->backlog > rpc->max_backlog) {
+            disconnect = true;
+            VLOG_WARN("sending backlog exceeded maximum size (%"PRIuSIZE" > %"
+                      PRIuSIZE" bytes), disconnecting, jsonrpc: %s.",
+                      rpc->backlog, rpc->max_backlog, rpc->name);
+        }
+        if (disconnect) {
+            jsonrpc_error(rpc, E2BIG);
+        }
     }
 
     if (rpc->backlog == length) {
@@ -787,6 +819,10 @@ struct jsonrpc_session {
     int last_error;
     unsigned int seqno;
     uint8_t dscp;
+
+    /* Limits for jsonrpc. */
+    size_t max_n_msgs;
+    size_t max_backlog_bytes;
 };
 
 static void
@@ -840,6 +876,8 @@ jsonrpc_session_open_multiple(const struct svec *remotes, bool retry)
     s->dscp = 0;
     s->last_error = 0;
 
+    jsonrpc_session_set_backlog_threshold(s, 0, 0);
+
     const char *name = reconnect_get_name(s->reconnect);
     if (!pstream_verify_name(name)) {
         reconnect_set_passive(s->reconnect, true, time_msec());
@@ -880,6 +918,7 @@ jsonrpc_session_open_unreliably(struct jsonrpc *jsonrpc, uint8_t dscp)
     s->pstream = NULL;
     s->seqno = 1;
 
+    jsonrpc_session_set_backlog_threshold(s, 0, 0);
     return s;
 }
 
@@ -968,6 +1007,8 @@ jsonrpc_session_run(struct jsonrpc_session *s)
             }
             reconnect_connected(s->reconnect, time_msec());
             s->rpc = jsonrpc_open(stream);
+            jsonrpc_set_backlog_threshold(s->rpc, s->max_n_msgs,
+                                                  s->max_backlog_bytes);
             s->seqno++;
         } else if (error != EAGAIN) {
             reconnect_listen_error(s->reconnect, time_msec(), error);
@@ -1008,6 +1049,8 @@ jsonrpc_session_run(struct jsonrpc_session *s)
         if (!error) {
             reconnect_connected(s->reconnect, time_msec());
             s->rpc = jsonrpc_open(s->stream);
+            jsonrpc_set_backlog_threshold(s->rpc, s->max_n_msgs,
+                                                  s->max_backlog_bytes);
             s->stream = NULL;
             s->seqno++;
         } else if (error != EAGAIN) {
@@ -1110,13 +1153,16 @@ jsonrpc_session_recv(struct jsonrpc_session *s)
 
         received_bytes = jsonrpc_get_received_bytes(s->rpc);
         jsonrpc_recv(s->rpc, &msg);
+
+        long long int now = time_msec();
+        reconnect_receive_attempted(s->reconnect, now);
         if (received_bytes != jsonrpc_get_received_bytes(s->rpc)) {
             /* Data was successfully received.
              *
              * Previously we only counted receiving a full message as activity,
              * but with large messages or a slow connection that policy could
              * time out the session mid-message. */
-            reconnect_activity(s->reconnect, time_msec());
+            reconnect_activity(s->reconnect, now);
         }
 
         if (msg) {
@@ -1248,3 +1294,18 @@ jsonrpc_session_set_dscp(struct jsonrpc_session *s, uint8_t dscp)
         jsonrpc_session_force_reconnect(s);
     }
 }
+
+/* Sets thresholds for send backlog.  If send backlog contains more than
+ * 'max_n_msgs' messages or is larger than 'max_backlog_bytes' bytes,
+ * connection will be closed (then reconnected, if that feature is enabled). */
+void
+jsonrpc_session_set_backlog_threshold(struct jsonrpc_session *s,
+                                      size_t max_n_msgs,
+                                      size_t max_backlog_bytes)
+{
+    s->max_n_msgs = max_n_msgs;
+    s->max_backlog_bytes = max_backlog_bytes;
+    if (s->rpc) {
+        jsonrpc_set_backlog_threshold(s->rpc, max_n_msgs, max_backlog_bytes);
+    }
+}
diff --git a/lib/jsonrpc.h b/lib/jsonrpc.h
index a44114e8dc..d75d66b863 100644
--- a/lib/jsonrpc.h
+++ b/lib/jsonrpc.h
@@ -51,6 +51,9 @@ void jsonrpc_wait(struct jsonrpc *);
 
 int jsonrpc_get_status(const struct jsonrpc *);
 size_t jsonrpc_get_backlog(const struct jsonrpc *);
+void jsonrpc_set_backlog_threshold(struct jsonrpc *, size_t max_n_msgs,
+                                                     size_t max_backlog_bytes);
+
 unsigned int jsonrpc_get_received_bytes(const struct jsonrpc *);
 const char *jsonrpc_get_name(const struct jsonrpc *);
 
@@ -140,6 +143,9 @@ void jsonrpc_session_set_probe_interval(struct jsonrpc_session *,
                                         int probe_interval);
 void jsonrpc_session_set_dscp(struct jsonrpc_session *,
                               uint8_t dscp);
+void jsonrpc_session_set_backlog_threshold(struct jsonrpc_session *,
+                                           size_t max_n_msgs,
+                                           size_t max_backlog_bytes);
 const char *jsonrpc_session_get_id(const struct jsonrpc_session *);
 
 #endif /* jsonrpc.h */
diff --git a/lib/lldp/lldp.c b/lib/lldp/lldp.c
index 74f747fcdc..18afbab9a7 100644
--- a/lib/lldp/lldp.c
+++ b/lib/lldp/lldp.c
@@ -59,7 +59,7 @@ VLOG_DEFINE_THIS_MODULE(lldp);
     } while (0)
 #define PEEK_DISCARD_UINT8 PEEK_DISCARD(1)
 #define PEEK_DISCARD_UINT16 PEEK_DISCARD(2)
-#define PEEK_DISCARD_UINT32 PEEK_DISCARD(3)
+#define PEEK_DISCARD_UINT32 PEEK_DISCARD(4)
 #define PEEK_CMP(value, bytes) \
      (length -= (bytes),       \
      pos += (bytes),           \
@@ -341,6 +341,12 @@ lldp_send(struct lldpd *global OVS_UNUSED,
 
     return dp_packet_size(p);
 }
+#define CHECK_TLV_MAX_SIZE(x, name)                                 \
+    do { if (tlv_size > (x)) {                                      \
+            VLOG_WARN(name " TLV too large received on %s",         \
+                      hardware->h_ifname);                          \
+            goto malformed;                                         \
+        } } while (0)
 
 int
 lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
@@ -359,7 +365,7 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
     int length, af;
     bool gotend = false;
     bool ttl_received = false;
-    int tlv_size, tlv_type, tlv_subtype;
+    int tlv_size, tlv_type, tlv_subtype, tlv_count = 0;
     u_int8_t *pos, *tlv;
     void *b;
     struct lldpd_aa_isid_vlan_maps_tlv *isid_vlan_map = NULL;
@@ -411,6 +417,31 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
                       hardware->h_ifname);
             goto malformed;
         }
+        /* Check order for mandatory TLVs */
+        tlv_count++;
+        switch (tlv_type) {
+        case LLDP_TLV_CHASSIS_ID:
+            if (tlv_count != 1) {
+                VLOG_WARN("first TLV should be a chassis ID on %s, not %d",
+                          hardware->h_ifname, tlv_type);
+                goto malformed;
+            }
+            break;
+        case LLDP_TLV_PORT_ID:
+            if (tlv_count != 2) {
+                VLOG_WARN("second TLV should be a port ID on %s, not %d",
+                          hardware->h_ifname, tlv_type);
+                goto malformed;
+            }
+            break;
+        case LLDP_TLV_TTL:
+            if (tlv_count != 3) {
+                VLOG_WARN("third TLV should be a TTL on %s, not %d",
+                          hardware->h_ifname, tlv_type);
+                goto malformed;
+            }
+            break;
+        }
 
         switch (tlv_type) {
         case LLDP_TLV_END:
@@ -428,7 +459,8 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
 
         case LLDP_TLV_CHASSIS_ID:
         case LLDP_TLV_PORT_ID:
-            CHECK_TLV_SIZE(2, "Port Id");
+            CHECK_TLV_SIZE(2, "Port/Chassis Id");
+            CHECK_TLV_MAX_SIZE(256, "Port/Chassis Id");
             tlv_subtype = PEEK_UINT8;
             if (tlv_subtype == 0 || tlv_subtype > 7) {
                 VLOG_WARN("unknown subtype for tlv id received on %s",
@@ -438,10 +470,22 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
             b = xzalloc(tlv_size - 1);
             PEEK_BYTES(b, tlv_size - 1);
             if (tlv_type == LLDP_TLV_PORT_ID) {
+                if (port->p_id != NULL) {
+                    VLOG_WARN("Port ID TLV received twice on %s",
+                              hardware->h_ifname);
+                    free(b);
+                    goto malformed;
+                }
                 port->p_id_subtype = tlv_subtype;
                 port->p_id = b;
                 port->p_id_len = tlv_size - 1;
             } else {
+                if (chassis->c_id != NULL) {
+                    VLOG_WARN("Chassis ID TLV received twice on %s",
+                              hardware->h_ifname);
+                    free(b);
+                    goto malformed;
+                }
                 chassis->c_id_subtype = tlv_subtype;
                 chassis->c_id = b;
                 chassis->c_id_len = tlv_size - 1;
@@ -449,6 +493,11 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
             break;
 
         case LLDP_TLV_TTL:
+            if (ttl_received) {
+                VLOG_WARN("TTL TLV received twice on %s",
+                          hardware->h_ifname);
+                goto malformed;
+            }
             CHECK_TLV_SIZE(2, "TTL");
             chassis->c_ttl = PEEK_UINT16;
             ttl_received = true;
@@ -464,10 +513,13 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
             b = xzalloc(tlv_size + 1);
             PEEK_BYTES(b, tlv_size);
             if (tlv_type == LLDP_TLV_PORT_DESCR) {
+                free(port->p_descr);
                 port->p_descr = b;
             } else if (tlv_type == LLDP_TLV_SYSTEM_NAME) {
+                free(chassis->c_name);
                 chassis->c_name = b;
             } else {
+                free(chassis->c_descr);
                 chassis->c_descr = b;
             }
             break;
@@ -481,6 +533,11 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
         case LLDP_TLV_MGMT_ADDR:
             CHECK_TLV_SIZE(1, "Management address");
             addr_str_length = PEEK_UINT8;
+            if (addr_str_length > sizeof(addr_str_buffer)) {
+                VLOG_WARN("too large management address on %s",
+                          hardware->h_ifname);
+                goto malformed;
+            }
             CHECK_TLV_SIZE(1 + addr_str_length, "Management address");
             PEEK_BYTES(addr_str_buffer, addr_str_length);
             addr_length = addr_str_length - 1;
@@ -505,7 +562,7 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
             break;
 
         case LLDP_TLV_ORG:
-            CHECK_TLV_SIZE(4, "Organisational");
+            CHECK_TLV_SIZE(1 + sizeof orgid, "Organisational");
             PEEK_BYTES(orgid, sizeof orgid);
             tlv_subtype = PEEK_UINT8;
             if (memcmp(dot1, orgid, sizeof orgid) == 0) {
@@ -625,6 +682,7 @@ lldp_decode(struct lldpd *cfg OVS_UNUSED, char *frame, int s,
             VLOG_WARN("unknown tlv (%d) received on %s",
                       tlv_type,
                       hardware->h_ifname);
+            hardware->h_rx_unrecognized_cnt++;
             goto malformed;
         }
         if (pos > tlv + tlv_size) {
diff --git a/lib/lldp/lldpd.c b/lib/lldp/lldpd.c
index 19e9305266..34738535db 100644
--- a/lib/lldp/lldpd.c
+++ b/lib/lldp/lldpd.c
@@ -244,6 +244,7 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s,
 
     if (s < sizeof(struct eth_header) + 4) {
         /* Too short, just discard it */
+        hw->h_rx_discarded_cnt++;
         return;
     }
 
@@ -284,6 +285,7 @@ lldpd_decode(struct lldpd *cfg, char *frame, int s,
                 VLOG_DBG("function for %s protocol did not "
                          "decode this frame",
                          cfg->g_protocols[i].name);
+                hw->h_rx_discarded_cnt++;
                 return;
             }
             chassis->c_protocol = port->p_protocol = cfg->g_protocols[i].mode;
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index 8b62e6d968..8a48a41197 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -1764,6 +1764,19 @@ mf_is_tun_metadata(const struct mf_field *mf)
            mf->id < MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS;
 }
 
+bool
+mf_is_frozen_metadata(const struct mf_field *mf)
+{
+    if (mf->id >= MFF_TUN_ID && mf->id <= MFF_IN_PORT_OXM) {
+        return true;
+    }
+
+    if (mf->id >= MFF_REG0 && mf->id < MFF_ETH_SRC) {
+        return true;
+    }
+    return false;
+}
+
 bool
 mf_is_pipeline_field(const struct mf_field *mf)
 {
@@ -2296,12 +2309,6 @@ mf_set(const struct mf_field *mf,
     switch (mf->id) {
     case MFF_CT_ZONE:
     case MFF_CT_NW_PROTO:
-    case MFF_CT_NW_SRC:
-    case MFF_CT_NW_DST:
-    case MFF_CT_IPV6_SRC:
-    case MFF_CT_IPV6_DST:
-    case MFF_CT_TP_SRC:
-    case MFF_CT_TP_DST:
     case MFF_RECIRC_ID:
     case MFF_PACKET_TYPE:
     case MFF_CONJ_ID:
@@ -2419,6 +2426,30 @@ mf_set(const struct mf_field *mf,
                                   ntoh128(mask->be128));
         break;
 
+    case MFF_CT_NW_SRC:
+        match_set_ct_nw_src_masked(match, value->be32, mask->be32);
+        break;
+
+    case MFF_CT_NW_DST:
+        match_set_ct_nw_dst_masked(match, value->be32, mask->be32);
+        break;
+
+    case MFF_CT_IPV6_SRC:
+        match_set_ct_ipv6_src_masked(match, &value->ipv6, &mask->ipv6);
+        break;
+
+    case MFF_CT_IPV6_DST:
+        match_set_ct_ipv6_dst_masked(match, &value->ipv6, &mask->ipv6);
+        break;
+
+    case MFF_CT_TP_SRC:
+        match_set_ct_tp_src_masked(match, value->be16, mask->be16);
+        break;
+
+    case MFF_CT_TP_DST:
+        match_set_ct_tp_dst_masked(match, value->be16, mask->be16);
+        break;
+
     case MFF_ETH_DST:
         match_set_dl_dst_masked(match, value->mac, mask->mac);
         break;
diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml
index 90b405c737..309dc59c5f 100644
--- a/lib/meta-flow.xml
+++ b/lib/meta-flow.xml
@@ -2566,8 +2566,8 @@ actions=clone(load:0->NXM_OF_IN_PORT[],output:123)
 
         <dt><code>est</code> (0x02)</dt>
         <dd>
-          Part of an existing connection.  Set to 1 if this is a committed
-          connection.
+          Part of an existing connection.  Set to 1 if packets of a committed
+          connection have been seen by conntrack from both directions.
         </dd>
 
         <dt><code>rel</code> (0x04)</dt>
@@ -3841,18 +3841,18 @@ r r c c c.
 
       <ul>
         <li>
-          When <ref field="mpls_bos"/> is 1, there is another MPLS label
+          When <ref field="mpls_bos"/> is 0, there is another MPLS label
           following this one, so the Ethertype passed to <code>pop_mpls</code>
           should be an MPLS Ethertype.  For example: <code>table=0,
-          dl_type=0x8847, mpls_bos=1, actions=pop_mpls:0x8847,
+          dl_type=0x8847, mpls_bos=0, actions=pop_mpls:0x8847,
           goto_table:1</code>
         </li>
 
         <li>
-          When <ref field="mpls_bos"/> is 0, this MPLS label is the last one,
+          When <ref field="mpls_bos"/> is 1, this MPLS label is the last one,
           so the Ethertype passed to <code>pop_mpls</code> should be a non-MPLS
           Ethertype such as IPv4.  For example: <code>table=1, dl_type=0x8847,
-          mpls_bos=0, actions=pop_mpls:0x0800, goto_table:2</code>
+          mpls_bos=1, actions=pop_mpls:0x0800, goto_table:2</code>
         </li>
       </ul>
     </field>
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 6187129c00..f080dec61f 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -152,9 +152,18 @@ typedef uint16_t dpdk_port_t;
 
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
 
+/* List of required flags advertised by the hardware that will be used
+ * if TSO is enabled. Ideally this should include DEV_TX_OFFLOAD_SCTP_CKSUM.
+ * However, very few drivers supports that the moment and SCTP is not a
+ * widely used protocol as TCP and UDP, so it's optional. */
+#define DPDK_TX_TSO_OFFLOAD_FLAGS (DEV_TX_OFFLOAD_TCP_TSO        \
+                                   | DEV_TX_OFFLOAD_TCP_CKSUM    \
+                                   | DEV_TX_OFFLOAD_UDP_CKSUM    \
+                                   | DEV_TX_OFFLOAD_IPV4_CKSUM)
+
+
 static const struct rte_eth_conf port_conf = {
     .rxmode = {
-        .mq_mode = ETH_MQ_RX_RSS,
         .split_hdr_size = 0,
         .offloads = 0,
     },
@@ -415,6 +424,7 @@ enum dpdk_hw_ol_features {
     NETDEV_RX_HW_CRC_STRIP = 1 << 1,
     NETDEV_RX_HW_SCATTER = 1 << 2,
     NETDEV_TX_TSO_OFFLOAD = 1 << 3,
+    NETDEV_TX_SCTP_CHECKSUM_OFFLOAD = 1 << 4,
 };
 
 /*
@@ -975,6 +985,14 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev, int n_rxq, int n_txq)
 
     rte_eth_dev_info_get(dev->port_id, &info);
 
+    /* As of DPDK 19.11, it is not allowed to set a mq_mode for
+     * virtio PMD driver. */
+    if (!strcmp(info.driver_name, "net_virtio")) {
+        conf.rxmode.mq_mode = ETH_MQ_RX_NONE;
+    } else {
+        conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
+    }
+
     /* As of DPDK 17.11.1 a few PMDs require to explicitly enable
      * scatter to support jumbo RX.
      * Setting scatter for the device is done after checking for
@@ -997,9 +1015,10 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev, int n_rxq, int n_txq)
     }
 
     if (dev->hw_ol_features & NETDEV_TX_TSO_OFFLOAD) {
-        conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_TSO;
-        conf.txmode.offloads |= DEV_TX_OFFLOAD_TCP_CKSUM;
-        conf.txmode.offloads |= DEV_TX_OFFLOAD_IPV4_CKSUM;
+        conf.txmode.offloads |= DPDK_TX_TSO_OFFLOAD_FLAGS;
+        if (dev->hw_ol_features & NETDEV_TX_SCTP_CHECKSUM_OFFLOAD) {
+            conf.txmode.offloads |= DEV_TX_OFFLOAD_SCTP_CKSUM;
+        }
     }
 
     /* Limit configured rss hash functions to only those supported
@@ -1100,12 +1119,10 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)
     struct rte_ether_addr eth_addr;
     int diag;
     int n_rxq, n_txq;
+    uint32_t tx_tso_offload_capa = DPDK_TX_TSO_OFFLOAD_FLAGS;
     uint32_t rx_chksm_offload_capa = DEV_RX_OFFLOAD_UDP_CKSUM |
                                      DEV_RX_OFFLOAD_TCP_CKSUM |
                                      DEV_RX_OFFLOAD_IPV4_CKSUM;
-    uint32_t tx_tso_offload_capa = DEV_TX_OFFLOAD_TCP_TSO |
-                                   DEV_TX_OFFLOAD_TCP_CKSUM |
-                                   DEV_TX_OFFLOAD_IPV4_CKSUM;
 
     rte_eth_dev_info_get(dev->port_id, &info);
 
@@ -1137,6 +1154,13 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)
         if ((info.tx_offload_capa & tx_tso_offload_capa)
             == tx_tso_offload_capa) {
             dev->hw_ol_features |= NETDEV_TX_TSO_OFFLOAD;
+            if (info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) {
+                dev->hw_ol_features |= NETDEV_TX_SCTP_CHECKSUM_OFFLOAD;
+            } else {
+                VLOG_WARN("%s: Tx SCTP checksum offload is not supported, "
+                          "SCTP packets sent to this device will be dropped",
+                          netdev_get_name(&dev->up));
+            }
         } else {
             VLOG_WARN("%s: Tx TSO offload is not supported.",
                       netdev_get_name(&dev->up));
@@ -2691,12 +2715,8 @@ dpdk_pktmbuf_attach_extbuf(struct rte_mbuf *pkt, uint32_t data_len)
     uint16_t buf_len;
     void *buf;
 
-    if (rte_pktmbuf_tailroom(pkt) >= sizeof *shinfo) {
-        shinfo = rte_pktmbuf_mtod(pkt, struct rte_mbuf_ext_shared_info *);
-    } else {
-        total_len += sizeof *shinfo + sizeof(uintptr_t);
-        total_len = RTE_ALIGN_CEIL(total_len, sizeof(uintptr_t));
-    }
+    total_len += sizeof *shinfo + sizeof(uintptr_t);
+    total_len = RTE_ALIGN_CEIL(total_len, sizeof(uintptr_t));
 
     if (OVS_UNLIKELY(total_len > UINT16_MAX)) {
         VLOG_ERR("Can't copy packet: too big %u", total_len);
@@ -2711,20 +2731,14 @@ dpdk_pktmbuf_attach_extbuf(struct rte_mbuf *pkt, uint32_t data_len)
     }
 
     /* Initialize shinfo. */
-    if (shinfo) {
-        shinfo->free_cb = netdev_dpdk_extbuf_free;
-        shinfo->fcb_opaque = buf;
-        rte_mbuf_ext_refcnt_set(shinfo, 1);
-    } else {
-        shinfo = rte_pktmbuf_ext_shinfo_init_helper(buf, &buf_len,
-                                                    netdev_dpdk_extbuf_free,
-                                                    buf);
-        if (OVS_UNLIKELY(shinfo == NULL)) {
-            rte_free(buf);
-            VLOG_ERR("Failed to initialize shared info for mbuf while "
-                     "attempting to attach an external buffer.");
-            return NULL;
-        }
+    shinfo = rte_pktmbuf_ext_shinfo_init_helper(buf, &buf_len,
+                                                netdev_dpdk_extbuf_free,
+                                                buf);
+    if (OVS_UNLIKELY(shinfo == NULL)) {
+        rte_free(buf);
+        VLOG_ERR("Failed to initialize shared info for mbuf while "
+                 "attempting to attach an external buffer.");
+        return NULL;
     }
 
     rte_pktmbuf_attach_extbuf(pkt, buf, rte_malloc_virt2iova(buf), buf_len,
@@ -5110,7 +5124,11 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
     if (dev->hw_ol_features & NETDEV_TX_TSO_OFFLOAD) {
         netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
         netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
+        netdev->ol_flags |= NETDEV_TX_OFFLOAD_UDP_CKSUM;
         netdev->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
+        if (dev->hw_ol_features & NETDEV_TX_SCTP_CHECKSUM_OFFLOAD) {
+            netdev->ol_flags |= NETDEV_TX_OFFLOAD_SCTP_CKSUM;
+        }
     }
 
     dev->tx_q = netdev_dpdk_alloc_txq(netdev->n_txq);
@@ -5186,6 +5204,7 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
     int err;
     uint64_t vhost_flags = 0;
+    uint64_t vhost_unsup_flags;
     bool zc_enabled;
 
     ovs_mutex_lock(&dev->mutex);
@@ -5251,17 +5270,24 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
         if (userspace_tso_enabled()) {
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
+            netdev->ol_flags |= NETDEV_TX_OFFLOAD_UDP_CKSUM;
+            netdev->ol_flags |= NETDEV_TX_OFFLOAD_SCTP_CKSUM;
             netdev->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
+            vhost_unsup_flags = 1ULL << VIRTIO_NET_F_HOST_ECN
+                                | 1ULL << VIRTIO_NET_F_HOST_UFO;
         } else {
-            err = rte_vhost_driver_disable_features(dev->vhost_id,
-                                        1ULL << VIRTIO_NET_F_HOST_TSO4
-                                        | 1ULL << VIRTIO_NET_F_HOST_TSO6
-                                        | 1ULL << VIRTIO_NET_F_CSUM);
-            if (err) {
-                VLOG_ERR("rte_vhost_driver_disable_features failed for "
-                         "vhost user client port: %s\n", dev->up.name);
-                goto unlock;
-            }
+            /* This disables checksum offloading and all the features
+             * that depends on it (TSO, UFO, ECN) according to virtio
+             * specification. */
+            vhost_unsup_flags = 1ULL << VIRTIO_NET_F_CSUM;
+        }
+
+        err = rte_vhost_driver_disable_features(dev->vhost_id,
+                                                vhost_unsup_flags);
+        if (err) {
+            VLOG_ERR("rte_vhost_driver_disable_features failed for "
+                     "vhost user client port: %s\n", dev->up.name);
+            goto unlock;
         }
 
         err = rte_vhost_driver_start(dev->vhost_id);
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index c6f3d27409..216ea208a7 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -231,6 +231,14 @@ struct rtnl_link_stats64 {
     uint64_t tx_compressed;
 };
 
+/* Linux 3.19 introduced virtio_types.h.  It might be missing
+ * if we are using old kernel. */
+#ifndef HAVE_VIRTIO_TYPES
+typedef __u16 __bitwise__ __virtio16;
+typedef __u32 __bitwise__ __virtio32;
+typedef __u64 __bitwise__ __virtio64;
+#endif
+
 enum {
     VALID_IFINDEX           = 1 << 0,
     VALID_ETHERADDR         = 1 << 1,
@@ -621,6 +629,7 @@ netdev_linux_notify_sock(void)
         if (!error) {
             size_t i;
 
+            nl_sock_listen_all_nsid(sock, true);
             for (i = 0; i < ARRAY_SIZE(mcgroups); i++) {
                 error = nl_sock_join_mcgroup(sock, mcgroups[i]);
                 if (error) {
@@ -630,7 +639,6 @@ netdev_linux_notify_sock(void)
                 }
             }
         }
-        nl_sock_listen_all_nsid(sock, true);
         ovsthread_once_done(&once);
     }
 
@@ -659,10 +667,6 @@ netdev_linux_update_lag(struct rtnetlink_change *change)
 {
     struct linux_lag_slave *lag;
 
-    if (!rtnetlink_type_is_rtnlgrp_link(change->nlmsg_type)) {
-        return;
-    }
-
     if (change->slave && netdev_linux_kind_is_lag(change->slave)) {
         lag = shash_find_data(&lag_shash, change->ifname);
 
@@ -672,7 +676,9 @@ netdev_linux_update_lag(struct rtnetlink_change *change)
             uint32_t block_id;
             int error = 0;
 
-            if_indextoname(change->master_ifindex, master_name);
+            if (!if_indextoname(change->master_ifindex, master_name)) {
+                return;
+            }
             master_netdev = netdev_from_name(master_name);
             if (!master_netdev) {
                 return;
@@ -760,8 +766,11 @@ netdev_linux_run(const struct netdev_class *netdev_class OVS_UNUSED)
                     netdev_linux_update(netdev, nsid, &change);
                     ovs_mutex_unlock(&netdev->mutex);
                 }
-                else if (!netdev_ && change.ifname) {
-                    /* Netdev is not present in OvS but its master could be. */
+
+                if (change.ifname &&
+                    rtnetlink_type_is_rtnlgrp_link(change.nlmsg_type)) {
+
+                    /* Need to try updating the LAG information. */
                     ovs_mutex_lock(&lag_mutex);
                     netdev_linux_update_lag(&change);
                     ovs_mutex_unlock(&lag_mutex);
@@ -923,6 +932,8 @@ netdev_linux_common_construct(struct netdev *netdev_)
     if (userspace_tso_enabled()) {
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
+        netdev_->ol_flags |= NETDEV_TX_OFFLOAD_UDP_CKSUM;
+        netdev_->ol_flags |= NETDEV_TX_OFFLOAD_SCTP_CKSUM;
         netdev_->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
     }
 
@@ -1233,21 +1244,21 @@ netdev_linux_batch_rxq_recv_sock(struct netdev_rxq_linux *rx, int mtu,
      * aux_buf is allocated so that it can be prepended to TSO buffer. */
     std_len = virtio_net_hdr_size + VLAN_ETH_HEADER_LEN + mtu;
     for (i = 0; i < NETDEV_MAX_BURST; i++) {
-         buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM);
-         iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]);
-         iovs[i][IOV_PACKET].iov_len = std_len;
-         if (iovlen == IOV_TSO_SIZE) {
-             iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]);
-             iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]);
-         }
+        buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM);
+        iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]);
+        iovs[i][IOV_PACKET].iov_len = std_len;
+        if (iovlen == IOV_TSO_SIZE) {
+            iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]);
+            iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]);
+        }
 
-         mmsgs[i].msg_hdr.msg_name = NULL;
-         mmsgs[i].msg_hdr.msg_namelen = 0;
-         mmsgs[i].msg_hdr.msg_iov = iovs[i];
-         mmsgs[i].msg_hdr.msg_iovlen = iovlen;
-         mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i];
-         mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i];
-         mmsgs[i].msg_hdr.msg_flags = 0;
+        mmsgs[i].msg_hdr.msg_name = NULL;
+        mmsgs[i].msg_hdr.msg_namelen = 0;
+        mmsgs[i].msg_hdr.msg_iov = iovs[i];
+        mmsgs[i].msg_hdr.msg_iovlen = iovlen;
+        mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i];
+        mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i];
+        mmsgs[i].msg_hdr.msg_flags = 0;
     }
 
     do {
@@ -1266,14 +1277,28 @@ netdev_linux_batch_rxq_recv_sock(struct netdev_rxq_linux *rx, int mtu,
     for (i = 0; i < retval; i++) {
         struct dp_packet *pkt;
 
-        if (mmsgs[i].msg_len < ETH_HEADER_LEN) {
+        if (mmsgs[i].msg_hdr.msg_flags & MSG_TRUNC
+            || mmsgs[i].msg_len < ETH_HEADER_LEN) {
             struct netdev *netdev_ = netdev_rxq_get_netdev(&rx->up);
             struct netdev_linux *netdev = netdev_linux_cast(netdev_);
 
+            /* The rx->aux_bufs[i] will be re-used next time. */
             dp_packet_delete(buffers[i]);
             netdev->rx_dropped += 1;
-            VLOG_WARN_RL(&rl, "%s: Dropped packet: less than ether hdr size",
-                         netdev_get_name(netdev_));
+            if (mmsgs[i].msg_hdr.msg_flags & MSG_TRUNC) {
+                /* Data is truncated, so the packet is corrupted, and needs
+                 * to be dropped. This can happen if TSO/GRO is enabled in
+                 * the kernel, but not in userspace, i.e. there is no dp
+                 * buffer to store the full packet. */
+                VLOG_WARN_RL(&rl,
+                             "%s: Dropped packet: Too big. GRO/TSO enabled?",
+                             netdev_get_name(netdev_));
+            } else {
+                VLOG_WARN_RL(&rl,
+                             "%s: Dropped packet: less than ether hdr size",
+                             netdev_get_name(netdev_));
+            }
+
             continue;
         }
 
@@ -2562,7 +2587,7 @@ exit:
 static struct tc_police
 tc_matchall_fill_police(uint32_t kbits_rate, uint32_t kbits_burst)
 {
-    unsigned int bsize = MIN(UINT32_MAX / 1024, kbits_burst) * 1024 / 64;
+    unsigned int bsize = MIN(UINT32_MAX / 1024, kbits_burst) * 1024 / 8;
     unsigned int bps = ((uint64_t) kbits_rate * 1000) / 8;
     struct tc_police police;
     struct tc_ratespec rate;
diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
index f8c46bbaad..b42d314b65 100644
--- a/lib/netdev-offload-dpdk.c
+++ b/lib/netdev-offload-dpdk.c
@@ -76,7 +76,7 @@ ufid_to_rte_flow_data_find(const ovs_u128 *ufid)
     return NULL;
 }
 
-static inline void
+static inline struct ufid_to_rte_flow_data *
 ufid_to_rte_flow_associate(const ovs_u128 *ufid,
                            struct rte_flow *rte_flow, bool actions_offloaded)
 {
@@ -101,6 +101,7 @@ ufid_to_rte_flow_associate(const ovs_u128 *ufid,
 
     cmap_insert(&ufid_to_rte_flow,
                 CONST_CAST(struct cmap_node *, &data->node), hash);
+    return data;
 }
 
 static inline void
@@ -565,8 +566,18 @@ parse_flow_match(struct flow_patterns *patterns,
     uint8_t proto = 0;
 
     /* Eth */
-    if (!eth_addr_is_zero(match->wc.masks.dl_src) ||
-        !eth_addr_is_zero(match->wc.masks.dl_dst)) {
+    if (match->wc.masks.dl_type == OVS_BE16_MAX && is_ip_any(&match->flow)
+        && eth_addr_is_zero(match->wc.masks.dl_dst)
+        && eth_addr_is_zero(match->wc.masks.dl_src)) {
+        /*
+         * This is a temporary work around to fix ethernet pattern for partial
+         * hardware offload for X710 devices. This fix will be reverted once
+         * the issue is fixed within the i40e PMD driver.
+         */
+        add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, NULL, NULL);
+    } else if (match->wc.masks.dl_type ||
+               !eth_addr_is_zero(match->wc.masks.dl_src) ||
+               !eth_addr_is_zero(match->wc.masks.dl_dst)) {
         struct rte_flow_item_eth *spec, *mask;
 
         spec = xzalloc(sizeof *spec);
@@ -581,15 +592,6 @@ parse_flow_match(struct flow_patterns *patterns,
         mask->type = match->wc.masks.dl_type;
 
         add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, spec, mask);
-    } else {
-        /*
-         * If user specifies a flow (like UDP flow) without L2 patterns,
-         * OVS will at least set the dl_type. Normally, it's enough to
-         * create an eth pattern just with it. Unluckily, some Intel's
-         * NIC (such as XL710) doesn't support that. Below is a workaround,
-         * which simply matches any L2 pkts.
-         */
-        add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, NULL, NULL);
     }
 
     /* VLAN */
@@ -1037,7 +1039,7 @@ out:
     return flow;
 }
 
-static int
+static struct ufid_to_rte_flow_data *
 netdev_offload_dpdk_add_flow(struct netdev *netdev,
                              const struct match *match,
                              struct nlattr *nl_actions,
@@ -1046,12 +1048,11 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
                              struct offload_info *info)
 {
     struct flow_patterns patterns = { .items = NULL, .cnt = 0 };
+    struct ufid_to_rte_flow_data *flows_data = NULL;
     bool actions_offloaded = true;
     struct rte_flow *flow;
-    int ret = 0;
 
-    ret = parse_flow_match(&patterns, match);
-    if (ret) {
+    if (parse_flow_match(&patterns, match)) {
         goto out;
     }
 
@@ -1067,16 +1068,15 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev,
     }
 
     if (!flow) {
-        ret = -1;
         goto out;
     }
-    ufid_to_rte_flow_associate(ufid, flow, actions_offloaded);
+    flows_data = ufid_to_rte_flow_associate(ufid, flow, actions_offloaded);
     VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT"\n",
              netdev_get_name(netdev), flow, UUID_ARGS((struct uuid *)ufid));
 
 out:
     free_flow_patterns(&patterns);
-    return ret;
+    return flows_data;
 }
 
 /*
@@ -1179,14 +1179,19 @@ netdev_offload_dpdk_flow_put(struct netdev *netdev, struct match *match,
                              struct dpif_flow_stats *stats)
 {
     struct ufid_to_rte_flow_data *rte_flow_data;
+    struct dpif_flow_stats old_stats;
+    bool modification = false;
     int ret;
 
     /*
      * If an old rte_flow exists, it means it's a flow modification.
      * Here destroy the old rte flow first before adding a new one.
+     * Keep the stats for the newly created rule.
      */
     rte_flow_data = ufid_to_rte_flow_data_find(ufid);
     if (rte_flow_data && rte_flow_data->rte_flow) {
+        old_stats = rte_flow_data->stats;
+        modification = true;
         ret = netdev_offload_dpdk_destroy_flow(netdev, ufid,
                                                rte_flow_data->rte_flow);
         if (ret < 0) {
@@ -1199,11 +1204,18 @@ netdev_offload_dpdk_flow_put(struct netdev *netdev, struct match *match,
         return ret;
     }
 
+    rte_flow_data = netdev_offload_dpdk_add_flow(netdev, match, actions,
+                                                 actions_len, ufid, info);
+    if (!rte_flow_data) {
+        return -1;
+    }
+    if (modification) {
+        rte_flow_data->stats = old_stats;
+    }
     if (stats) {
-        memset(stats, 0, sizeof *stats);
+        *stats = rte_flow_data->stats;
     }
-    return netdev_offload_dpdk_add_flow(netdev, match, actions,
-                                        actions_len, ufid, info);
+    return 0;
 }
 
 static int
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
index 550e440b3a..89d3324e60 100644
--- a/lib/netdev-offload-tc.c
+++ b/lib/netdev-offload-tc.c
@@ -48,6 +48,7 @@ static struct hmap ufid_to_tc = HMAP_INITIALIZER(&ufid_to_tc);
 static struct hmap tc_to_ufid = HMAP_INITIALIZER(&tc_to_ufid);
 static bool multi_mask_per_prio = false;
 static bool block_support = false;
+static uint16_t ct_state_support;
 
 struct netlink_field {
     int offset;
@@ -198,7 +199,9 @@ del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid)
     int err;
 
     err = tc_del_filter(id);
-    del_ufid_tc_mapping(ufid);
+    if (!err) {
+        del_ufid_tc_mapping(ufid);
+    }
     return err;
 }
 
@@ -757,8 +760,7 @@ parse_tc_flower_to_match(struct tc_flower *flower,
                                     action->encap.tp_dst);
                 }
                 if (!action->encap.no_csum) {
-                    nl_msg_put_u8(buf, OVS_TUNNEL_KEY_ATTR_CSUM,
-                                  !action->encap.no_csum);
+                    nl_msg_put_flag(buf, OVS_TUNNEL_KEY_ATTR_CSUM);
                 }
 
                 parse_tc_flower_geneve_opts(action, buf);
@@ -1352,6 +1354,66 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl,
     flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len;
 }
 
+static void
+parse_match_ct_state_to_flower(struct tc_flower *flower, struct match *match)
+{
+    const struct flow *key = &match->flow;
+    struct flow *mask = &match->wc.masks;
+
+    if (!ct_state_support) {
+        return;
+    }
+
+    if ((ct_state_support & mask->ct_state) == mask->ct_state) {
+        if (mask->ct_state & OVS_CS_F_NEW) {
+            if (key->ct_state & OVS_CS_F_NEW) {
+                flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
+            }
+            flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
+            mask->ct_state &= ~OVS_CS_F_NEW;
+        }
+
+        if (mask->ct_state & OVS_CS_F_ESTABLISHED) {
+            if (key->ct_state & OVS_CS_F_ESTABLISHED) {
+                flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
+            }
+            flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
+            mask->ct_state &= ~OVS_CS_F_ESTABLISHED;
+        }
+
+        if (mask->ct_state & OVS_CS_F_TRACKED) {
+            if (key->ct_state & OVS_CS_F_TRACKED) {
+                flower->key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
+            }
+            flower->mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
+            mask->ct_state &= ~OVS_CS_F_TRACKED;
+        }
+
+        if (flower->key.ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) {
+            flower->key.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW);
+            flower->mask.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW);
+        }
+    }
+
+    if (mask->ct_zone) {
+        flower->key.ct_zone = key->ct_zone;
+        flower->mask.ct_zone = mask->ct_zone;
+        mask->ct_zone = 0;
+    }
+
+    if (mask->ct_mark) {
+        flower->key.ct_mark = key->ct_mark;
+        flower->mask.ct_mark = mask->ct_mark;
+        mask->ct_mark = 0;
+    }
+
+    if (!ovs_u128_is_zero(mask->ct_label)) {
+        flower->key.ct_label = key->ct_label;
+        flower->mask.ct_label = mask->ct_label;
+        mask->ct_label = OVS_U128_ZERO;
+    }
+}
+
 static int
 netdev_tc_flow_put(struct netdev *netdev, struct match *match,
                    struct nlattr *actions, size_t actions_len,
@@ -1572,53 +1634,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
         }
     }
 
-    if (mask->ct_state) {
-        if (mask->ct_state & OVS_CS_F_NEW) {
-            if (key->ct_state & OVS_CS_F_NEW) {
-                flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
-            }
-            flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
-        }
-
-        if (mask->ct_state & OVS_CS_F_ESTABLISHED) {
-            if (key->ct_state & OVS_CS_F_ESTABLISHED) {
-                flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
-            }
-            flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
-        }
-
-        if (mask->ct_state & OVS_CS_F_TRACKED) {
-            if (key->ct_state & OVS_CS_F_TRACKED) {
-                flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
-            }
-            flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
-        }
-
-        if (flower.key.ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) {
-            flower.key.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW);
-            flower.mask.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW);
-        }
-
-        mask->ct_state = 0;
-    }
-
-    if (mask->ct_zone) {
-        flower.key.ct_zone = key->ct_zone;
-        flower.mask.ct_zone = mask->ct_zone;
-        mask->ct_zone = 0;
-    }
-
-    if (mask->ct_mark) {
-        flower.key.ct_mark = key->ct_mark;
-        flower.mask.ct_mark = mask->ct_mark;
-        mask->ct_mark = 0;
-    }
-
-    if (!ovs_u128_is_zero(mask->ct_label)) {
-        flower.key.ct_label = key->ct_label;
-        flower.mask.ct_label = mask->ct_label;
-        mask->ct_label = OVS_U128_ZERO;
-    }
+    parse_match_ct_state_to_flower(&flower, match);
 
     /* ignore exact match on skb_mark of 0. */
     if (mask->pkt_mark == UINT32_MAX && !key->pkt_mark) {
@@ -1699,6 +1715,10 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
             const struct nlattr *ct = nl_attr_get(nla);
             const size_t ct_len = nl_attr_get_size(nla);
 
+            if (!ct_state_support) {
+                return -EOPNOTSUPP;
+            }
+
             err = parse_put_flow_ct_action(&flower, action, ct, ct_len);
             if (err) {
                 return err;
@@ -1727,7 +1747,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
     if (get_ufid_tc_mapping(ufid, &id) == 0) {
         VLOG_DBG_RL(&rl, "updating old handle: %d prio: %d",
                     id.handle, id.prio);
-        del_filter_and_ufid_mapping(&id, ufid);
+        info->tc_modify_flow_deleted = !del_filter_and_ufid_mapping(&id, ufid);
     }
 
     prio = get_prio_for_tc_flower(&flower);
@@ -1837,6 +1857,7 @@ probe_multi_mask_per_prio(int ifindex)
 
     memset(&flower, 0, sizeof flower);
 
+    flower.tc_policy = TC_POLICY_SKIP_HW;
     flower.key.eth_type = htons(ETH_P_IP);
     flower.mask.eth_type = OVS_BE16_MAX;
     memset(&flower.key.dst_mac, 0x11, sizeof flower.key.dst_mac);
@@ -1868,6 +1889,96 @@ out:
     tc_add_del_qdisc(ifindex, false, block_id, TC_INGRESS);
 }
 
+
+static int
+probe_insert_ct_state_rule(int ifindex, uint16_t ct_state, struct tcf_id *id)
+{
+    int prio = TC_RESERVED_PRIORITY_MAX + 1;
+    struct tc_flower flower;
+
+    memset(&flower, 0, sizeof flower);
+    flower.key.ct_state = ct_state;
+    flower.mask.ct_state = ct_state;
+    flower.tc_policy = TC_POLICY_SKIP_HW;
+    flower.key.eth_type = htons(ETH_P_IP);
+    flower.mask.eth_type = OVS_BE16_MAX;
+
+    *id = tc_make_tcf_id(ifindex, 0, prio, TC_INGRESS);
+    return tc_replace_flower(id, &flower);
+}
+
+static void
+probe_ct_state_support(int ifindex)
+{
+    struct tc_flower flower;
+    uint16_t ct_state;
+    struct tcf_id id;
+    int error;
+
+    error = tc_add_del_qdisc(ifindex, true, 0, TC_INGRESS);
+    if (error) {
+        return;
+    }
+
+    /* Test for base ct_state match support */
+    ct_state = TCA_FLOWER_KEY_CT_FLAGS_NEW | TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
+    error = probe_insert_ct_state_rule(ifindex, ct_state, &id);
+    if (error) {
+        goto out;
+    }
+
+    error = tc_get_flower(&id, &flower);
+    if (error || flower.mask.ct_state != ct_state) {
+        goto out_del;
+    }
+
+    tc_del_filter(&id);
+    ct_state_support = OVS_CS_F_NEW |
+                       OVS_CS_F_ESTABLISHED |
+                       OVS_CS_F_TRACKED |
+                       OVS_CS_F_RELATED;
+
+    /* Test for reject, ct_state >= MAX */
+    ct_state = ~0;
+    error = probe_insert_ct_state_rule(ifindex, ct_state, &id);
+    if (!error) {
+        /* No reject, can't continue probing other flags */
+        goto out_del;
+    }
+
+    tc_del_filter(&id);
+
+    /* Test for ct_state INVALID support */
+    memset(&flower, 0, sizeof flower);
+    ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED |
+               TCA_FLOWER_KEY_CT_FLAGS_INVALID;
+    error = probe_insert_ct_state_rule(ifindex, ct_state, &id);
+    if (error) {
+        goto out;
+    }
+
+    tc_del_filter(&id);
+    ct_state_support |= OVS_CS_F_INVALID;
+
+    /* Test for ct_state REPLY support */
+    memset(&flower, 0, sizeof flower);
+    ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED |
+               TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED |
+               TCA_FLOWER_KEY_CT_FLAGS_REPLY;
+    error = probe_insert_ct_state_rule(ifindex, ct_state, &id);
+    if (error) {
+        goto out;
+    }
+
+    ct_state_support |= OVS_CS_F_REPLY_DIR;
+
+out_del:
+    tc_del_filter(&id);
+out:
+    tc_add_del_qdisc(ifindex, false, 0, TC_INGRESS);
+    VLOG_INFO("probe tc: supported ovs ct_state bits: 0x%x", ct_state_support);
+}
+
 static void
 probe_tc_block_support(int ifindex)
 {
@@ -1884,6 +1995,7 @@ probe_tc_block_support(int ifindex)
 
     memset(&flower, 0, sizeof flower);
 
+    flower.tc_policy = TC_POLICY_SKIP_HW;
     flower.key.eth_type = htons(ETH_P_IP);
     flower.mask.eth_type = OVS_BE16_MAX;
     memset(&flower.key.dst_mac, 0x11, sizeof flower.key.dst_mac);
@@ -1907,6 +2019,7 @@ netdev_tc_init_flow_api(struct netdev *netdev)
     static struct ovsthread_once block_once = OVSTHREAD_ONCE_INITIALIZER;
     enum tc_qdisc_hook hook = get_tc_qdisc_hook(netdev);
     uint32_t block_id = 0;
+    struct tcf_id id;
     int ifindex;
     int error;
 
@@ -1917,20 +2030,30 @@ netdev_tc_init_flow_api(struct netdev *netdev)
         return -ifindex;
     }
 
+    block_id = get_block_id_from_netdev(netdev);
+
+    /* Flush rules explicitly needed when we work with ingress_block,
+     * so we will not fail with reattaching block to bond iface, for ex.
+     */
+    id = tc_make_tcf_id(ifindex, block_id, 0, hook);
+    tc_del_filter(&id);
+
     /* make sure there is no ingress/egress qdisc */
     tc_add_del_qdisc(ifindex, false, 0, hook);
 
     if (ovsthread_once_start(&block_once)) {
         probe_tc_block_support(ifindex);
+        /* Need to re-fetch block id as it depends on feature availability. */
+        block_id = get_block_id_from_netdev(netdev);
         ovsthread_once_done(&block_once);
     }
 
     if (ovsthread_once_start(&multi_mask_once)) {
         probe_multi_mask_per_prio(ifindex);
+        probe_ct_state_support(ifindex);
         ovsthread_once_done(&multi_mask_once);
     }
 
-    block_id = get_block_id_from_netdev(netdev);
     error = tc_add_del_qdisc(ifindex, true, block_id, hook);
 
     if (error && error != EEXIST) {
diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h
index cd6dfdfff4..b4b882a56a 100644
--- a/lib/netdev-offload.h
+++ b/lib/netdev-offload.h
@@ -74,6 +74,9 @@ struct offload_info {
      * it will be in the pkt meta data.
      */
     uint32_t flow_mark;
+
+    bool tc_modify_flow_deleted; /* Indicate the tc modify flow put success
+                                  * to delete the original flow. */
 };
 
 int netdev_flow_flush(struct netdev *);
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 22f4cde333..6f509424bc 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -40,7 +40,9 @@ struct netdev_tnl_build_header_params;
 enum netdev_ol_flags {
     NETDEV_TX_OFFLOAD_IPV4_CKSUM = 1 << 0,
     NETDEV_TX_OFFLOAD_TCP_CKSUM = 1 << 1,
-    NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 2,
+    NETDEV_TX_OFFLOAD_UDP_CKSUM = 1 << 2,
+    NETDEV_TX_OFFLOAD_SCTP_CKSUM = 1 << 3,
+    NETDEV_TX_OFFLOAD_TCP_TSO = 1 << 4,
 };
 
 /* A network device (e.g. an Ethernet device).
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index b57d21ff8d..be5ed099fd 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -736,6 +736,14 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
                     goto out;
                 }
             }
+        } else if (!strcmp(node->key, "remote_cert") ||
+                   !strcmp(node->key, "remote_name") ||
+                   !strcmp(node->key, "psk")) {
+            /* When configuring OVS for IPsec, these keys may be set in the
+               tunnel port's 'options' column. 'ovs-vswitchd' does not directly
+               use them, but they are read by 'ovs-monitor-ipsec'. In order to
+               suppress the "unknown %s argument" warning message below, we
+               handle them here by ignoring them. */
         } else {
             ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name,
                           type, node->key);
diff --git a/lib/netdev.c b/lib/netdev.c
index f95b19af4d..8c44eee8e9 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -791,6 +791,8 @@ static bool
 netdev_send_prepare_packet(const uint64_t netdev_flags,
                            struct dp_packet *packet, char **errormsg)
 {
+    uint64_t l4_mask;
+
     if (dp_packet_hwol_is_tso(packet)
         && !(netdev_flags & NETDEV_TX_OFFLOAD_TCP_TSO)) {
             /* Fall back to GSO in software. */
@@ -798,11 +800,31 @@ netdev_send_prepare_packet(const uint64_t netdev_flags,
             return false;
     }
 
-    if (dp_packet_hwol_l4_mask(packet)
-        && !(netdev_flags & NETDEV_TX_OFFLOAD_TCP_CKSUM)) {
-            /* Fall back to L4 csum in software. */
-            VLOG_ERR_BUF(errormsg, "No L4 checksum support");
+    l4_mask = dp_packet_hwol_l4_mask(packet);
+    if (l4_mask) {
+        if (dp_packet_hwol_l4_is_tcp(packet)) {
+            if (!(netdev_flags & NETDEV_TX_OFFLOAD_TCP_CKSUM)) {
+                /* Fall back to TCP csum in software. */
+                VLOG_ERR_BUF(errormsg, "No TCP checksum support");
+                return false;
+            }
+        } else if (dp_packet_hwol_l4_is_udp(packet)) {
+            if (!(netdev_flags & NETDEV_TX_OFFLOAD_UDP_CKSUM)) {
+                /* Fall back to UDP csum in software. */
+                VLOG_ERR_BUF(errormsg, "No UDP checksum support");
+                return false;
+            }
+        } else if (dp_packet_hwol_l4_is_sctp(packet)) {
+            if (!(netdev_flags & NETDEV_TX_OFFLOAD_SCTP_CKSUM)) {
+                /* Fall back to SCTP csum in software. */
+                VLOG_ERR_BUF(errormsg, "No SCTP checksum support");
+                return false;
+            }
+        } else {
+            VLOG_ERR_BUF(errormsg, "No L4 checksum support: mask: %"PRIu64,
+                         l4_mask);
             return false;
+        }
     }
 
     return true;
diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c
index 47077e9478..5cb96fa6ec 100644
--- a/lib/netlink-socket.c
+++ b/lib/netlink-socket.c
@@ -917,7 +917,7 @@ nl_sock_transact_multiple__(struct nl_sock *sock,
             }
             if (txn->error) {
                 VLOG_DBG_RL(&rl, "received NAK error=%d (%s)",
-                            error, ovs_strerror(txn->error));
+                            txn->error, ovs_strerror(txn->error));
             }
         } else {
             txn->error = 0;
diff --git a/lib/netlink.c b/lib/netlink.c
index de3ebcd0e7..26ab20bb4b 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -498,6 +498,7 @@ void
 nl_msg_end_nested(struct ofpbuf *msg, size_t offset)
 {
     struct nlattr *attr = ofpbuf_at_assert(msg, offset, sizeof *attr);
+    ovs_assert(!nl_attr_oversized(msg->size - offset - NLA_HDRLEN));
     attr->nla_len = msg->size - offset;
 }
 
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 0432ad4de6..260f30d13e 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -1133,6 +1133,11 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
                       mpls_lse_to_bos(flow->mpls_lse[0]));
         }
 
+        if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TTL_MASK)) {
+            nxm_put_8(&ctx, MFF_MPLS_TTL, oxm,
+                      mpls_lse_to_ttl(flow->mpls_lse[0]));
+        }
+
         if (match->wc.masks.mpls_lse[0] & htonl(MPLS_LABEL_MASK)) {
             nxm_put_32(&ctx, MFF_MPLS_LABEL, oxm,
                        htonl(mpls_lse_to_label(flow->mpls_lse[0])));
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index 42d3335f0f..97320a4dba 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -761,10 +761,11 @@ odp_execute_check_pkt_len(void *dp, struct dp_packet *packet, bool steal,
 
     const struct nlattr *a;
     struct dp_packet_batch pb;
+    uint32_t size = dp_packet_get_send_len(packet)
+                    - dp_packet_l2_pad_size(packet);
 
     a = attrs[OVS_CHECK_PKT_LEN_ATTR_PKT_LEN];
-    bool is_greater = dp_packet_size(packet) > nl_attr_get_u16(a);
-    if (is_greater) {
+    if (size > nl_attr_get_u16(a)) {
         a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER];
     } else {
         a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL];
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 746d1e97d4..57943df9ed 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -390,7 +390,8 @@ format_odp_push_nsh_action(struct ds *ds,
         break;
     }
     default:
-        OVS_NOT_REACHED();
+        ds_put_cstr(ds, ",<error: unknown mdtype>");
+        break;
     }
     ds_put_format(ds, ")");
 }
@@ -1441,14 +1442,20 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
         int n1 = -1;
         if (ovs_scan(&s[n], ",tunnel_out_port=%"SCNi32")%n",
                      &tunnel_out_port, &n1)) {
-            odp_put_userspace_action(pid, user_data, user_data_size,
-                                     tunnel_out_port, include_actions, actions);
-            res = n + n1;
+            res = odp_put_userspace_action(pid, user_data, user_data_size,
+                                           tunnel_out_port, include_actions,
+                                           actions, NULL);
+            if (!res) {
+                res = n + n1;
+            }
             goto out;
         } else if (s[n] == ')') {
-            odp_put_userspace_action(pid, user_data, user_data_size,
-                                     ODPP_NONE, include_actions, actions);
-            res = n + 1;
+            res = odp_put_userspace_action(pid, user_data, user_data_size,
+                                           ODPP_NONE, include_actions,
+                                           actions, NULL);
+            if (!res) {
+                res = n + 1;
+            }
             goto out;
         }
     }
@@ -2891,7 +2898,7 @@ odp_nsh_key_from_attr__(const struct nlattr *attr, bool is_mask,
             const struct ovs_nsh_key_md1 *md1 = nl_attr_get(a);
             has_md1 = true;
             memcpy(nsh->context, md1->context, sizeof md1->context);
-            if (len == 2 * sizeof(*md1)) {
+            if (nsh_mask && (len == 2 * sizeof *md1)) {
                 const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
                 memcpy(nsh_mask->context, md1_mask->context,
                        sizeof(*md1_mask));
@@ -3136,17 +3143,17 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
     if ((!tnl_type || !strcmp(tnl_type, "erspan") ||
         !strcmp(tnl_type, "ip6erspan")) &&
         (tun_key->erspan_ver == 1 || tun_key->erspan_ver == 2)) {
-        struct erspan_metadata opts;
+        struct erspan_metadata *opts;
 
-        opts.version = tun_key->erspan_ver;
-        if (opts.version == 1) {
-            opts.u.index = htonl(tun_key->erspan_idx);
+        opts = nl_msg_put_unspec_zero(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
+                                      sizeof *opts);
+        opts->version = tun_key->erspan_ver;
+        if (opts->version == 1) {
+            opts->u.index = htonl(tun_key->erspan_idx);
         } else {
-            opts.u.md2.dir = tun_key->erspan_dir;
-            set_hwid(&opts.u.md2, tun_key->erspan_hwid);
+            opts->u.md2.dir = tun_key->erspan_dir;
+            set_hwid(&opts->u.md2, tun_key->erspan_hwid);
         }
-        nl_msg_put_unspec(a, OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
-                          &opts, sizeof(opts));
     }
 
     nl_msg_end_nested(a, tun_key_ofs);
@@ -4531,7 +4538,7 @@ odp_flow_format(const struct nlattr *key, size_t key_len,
             }
             ds_put_char(ds, ')');
         }
-        if (!has_ethtype_key) {
+        if (!has_ethtype_key && mask) {
             const struct nlattr *ma = nl_attr_find__(mask, mask_len,
                                                      OVS_KEY_ATTR_ETHERTYPE);
             if (ma) {
@@ -5428,13 +5435,16 @@ erspan_to_attr(struct ofpbuf *a, const void *data_)
         do {                                               \
             len = 0;
 
-#define SCAN_END_NESTED()                               \
-        SCAN_FINISH();                                  \
-        nl_msg_end_nested(key, key_offset);             \
-        if (mask) {                                     \
-            nl_msg_end_nested(mask, mask_offset);       \
-        }                                               \
-        return s - start;                               \
+#define SCAN_END_NESTED()                                                     \
+        SCAN_FINISH();                                                        \
+        if (nl_attr_oversized(key->size - key_offset - NLA_HDRLEN)) {         \
+            return -E2BIG;                                                    \
+        }                                                                     \
+        nl_msg_end_nested(key, key_offset);                                   \
+        if (mask) {                                                           \
+            nl_msg_end_nested(mask, mask_offset);                             \
+        }                                                                     \
+        return s - start;                                                     \
     }
 
 #define SCAN_FIELD_NESTED__(NAME, TYPE, SCAN_AS, ATTR, FUNC)  \
@@ -6225,7 +6235,9 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
                     struct ovs_key_nd_extensions *nd_ext_key;
 
                     if (data->igmp_group_ip4 != 0 || data->tcp_flags != 0) {
-                        nd_ext_key = nl_msg_put_unspec_uninit(buf,
+                        /* 'struct ovs_key_nd_extensions' has padding,
+                         * clear it. */
+                        nd_ext_key = nl_msg_put_unspec_zero(buf,
                                             OVS_KEY_ATTR_ND_EXTENSIONS,
                                             sizeof *nd_ext_key);
                         nd_ext_key->nd_reserved = data->igmp_group_ip4;
@@ -6275,6 +6287,10 @@ odp_key_from_dp_packet(struct ofpbuf *buf, const struct dp_packet *packet)
 
     nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority);
 
+    if (md->dp_hash) {
+        nl_msg_put_u32(buf, OVS_KEY_ATTR_DP_HASH, md->dp_hash);
+    }
+
     if (flow_tnl_dst_is_set(&md->tunnel)) {
         tun_key_to_attr(buf, &md->tunnel, &md->tunnel, NULL, NULL);
     }
@@ -7416,15 +7432,18 @@ odp_key_fitness_to_string(enum odp_key_fitness fitness)
 
 /* Appends an OVS_ACTION_ATTR_USERSPACE action to 'odp_actions' that specifies
  * Netlink PID 'pid'.  If 'userdata' is nonnull, adds a userdata attribute
- * whose contents are the 'userdata_size' bytes at 'userdata' and returns the
- * offset within 'odp_actions' of the start of the cookie.  (If 'userdata' is
- * null, then the return value is not meaningful.) */
-size_t
+ * whose contents are the 'userdata_size' bytes at 'userdata' and sets
+ * 'odp_actions_ofs' if nonnull with the offset within 'odp_actions' of the
+ * start of the cookie.  (If 'userdata' is null, then the 'odp_actions_ofs'
+ * value is not meaningful.)
+ *
+ * Returns negative error code on failure. */
+int
 odp_put_userspace_action(uint32_t pid,
                          const void *userdata, size_t userdata_size,
                          odp_port_t tunnel_out_port,
                          bool include_actions,
-                         struct ofpbuf *odp_actions)
+                         struct ofpbuf *odp_actions, size_t *odp_actions_ofs)
 {
     size_t userdata_ofs;
     size_t offset;
@@ -7432,6 +7451,9 @@ odp_put_userspace_action(uint32_t pid,
     offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_USERSPACE);
     nl_msg_put_u32(odp_actions, OVS_USERSPACE_ATTR_PID, pid);
     if (userdata) {
+        if (nl_attr_oversized(userdata_size)) {
+            return -E2BIG;
+        }
         userdata_ofs = odp_actions->size + NLA_HDRLEN;
 
         /* The OVS kernel module before OVS 1.11 and the upstream Linux kernel
@@ -7457,9 +7479,16 @@ odp_put_userspace_action(uint32_t pid,
     if (include_actions) {
         nl_msg_put_flag(odp_actions, OVS_USERSPACE_ATTR_ACTIONS);
     }
+    if (nl_attr_oversized(odp_actions->size - offset - NLA_HDRLEN)) {
+        return -E2BIG;
+    }
     nl_msg_end_nested(odp_actions, offset);
 
-    return userdata_ofs;
+    if (odp_actions_ofs) {
+        *odp_actions_ofs = userdata_ofs;
+    }
+
+    return 0;
 }
 
 void
@@ -7565,6 +7594,28 @@ struct offsetof_sizeof {
     int size;
 };
 
+
+/* Performs bitwise OR over the fields in 'dst_' and 'src_' specified in
+ * 'offsetof_sizeof_arr' array.  Result is stored in 'dst_'. */
+static void
+or_masks(void *dst_, const void *src_,
+         struct offsetof_sizeof *offsetof_sizeof_arr)
+{
+    int field, size, offset;
+    const uint8_t *src = src_;
+    uint8_t *dst = dst_;
+
+    for (field = 0; ; field++) {
+        size   = offsetof_sizeof_arr[field].size;
+        offset = offsetof_sizeof_arr[field].offset;
+
+        if (!size) {
+            return;
+        }
+        or_bytes(dst + offset, src + offset, size);
+    }
+}
+
 /* Compares each of the fields in 'key0' and 'key1'.  The fields are specified
  * in 'offsetof_sizeof_arr', which is an array terminated by a 0-size field.
  * Returns true if all of the fields are equal, false if at least one differs.
@@ -7643,9 +7694,10 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
                         struct flow_wildcards *wc,
                         bool use_masked)
 {
-    struct ovs_key_ethernet key, base, mask;
+    struct ovs_key_ethernet key, base, mask, orig_mask;
     struct offsetof_sizeof ovs_key_ethernet_offsetof_sizeof_arr[] =
         OVS_KEY_ETHERNET_OFFSETOF_SIZEOF_ARR;
+
     if (flow->packet_type != htonl(PT_ETH)) {
         return;
     }
@@ -7653,11 +7705,13 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
     get_ethernet_key(flow, &key);
     get_ethernet_key(base_flow, &base);
     get_ethernet_key(&wc->masks, &mask);
+    memcpy(&orig_mask, &mask, sizeof mask);
 
     if (commit(OVS_KEY_ATTR_ETHERNET, use_masked,
                &key, &base, &mask, sizeof key,
                ovs_key_ethernet_offsetof_sizeof_arr, odp_actions)) {
         put_ethernet_key(&base, base_flow);
+        or_masks(&mask, &orig_mask, ovs_key_ethernet_offsetof_sizeof_arr);
         put_ethernet_key(&mask, &wc->masks);
     }
 }
@@ -7781,7 +7835,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
                        struct ofpbuf *odp_actions, struct flow_wildcards *wc,
                        bool use_masked)
 {
-    struct ovs_key_ipv4 key, mask, base;
+    struct ovs_key_ipv4 key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_ipv4_offsetof_sizeof_arr[] =
         OVS_KEY_IPV4_OFFSETOF_SIZEOF_ARR;
 
@@ -7792,6 +7846,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
     get_ipv4_key(flow, &key, false);
     get_ipv4_key(base_flow, &base, false);
     get_ipv4_key(&wc->masks, &mask, true);
+    memcpy(&orig_mask, &mask, sizeof mask);
     mask.ipv4_proto = 0;        /* Not writeable. */
     mask.ipv4_frag = 0;         /* Not writable. */
 
@@ -7803,9 +7858,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
     if (commit(OVS_KEY_ATTR_IPV4, use_masked, &key, &base, &mask, sizeof key,
                ovs_key_ipv4_offsetof_sizeof_arr, odp_actions)) {
         put_ipv4_key(&base, base_flow, false);
-        if (mask.ipv4_proto != 0) { /* Mask was changed by commit(). */
-            put_ipv4_key(&mask, &wc->masks, true);
-        }
+        or_masks(&mask, &orig_mask, ovs_key_ipv4_offsetof_sizeof_arr);
+        put_ipv4_key(&mask, &wc->masks, true);
    }
 }
 
@@ -7838,7 +7892,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
                        struct ofpbuf *odp_actions, struct flow_wildcards *wc,
                        bool use_masked)
 {
-    struct ovs_key_ipv6 key, mask, base;
+    struct ovs_key_ipv6 key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_ipv6_offsetof_sizeof_arr[] =
         OVS_KEY_IPV6_OFFSETOF_SIZEOF_ARR;
 
@@ -7849,6 +7903,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
     get_ipv6_key(flow, &key, false);
     get_ipv6_key(base_flow, &base, false);
     get_ipv6_key(&wc->masks, &mask, true);
+    memcpy(&orig_mask, &mask, sizeof mask);
     mask.ipv6_proto = 0;        /* Not writeable. */
     mask.ipv6_frag = 0;         /* Not writable. */
     mask.ipv6_label &= htonl(IPV6_LABEL_MASK); /* Not writable. */
@@ -7861,9 +7916,8 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
     if (commit(OVS_KEY_ATTR_IPV6, use_masked, &key, &base, &mask, sizeof key,
                ovs_key_ipv6_offsetof_sizeof_arr, odp_actions)) {
         put_ipv6_key(&base, base_flow, false);
-        if (mask.ipv6_proto != 0) { /* Mask was changed by commit(). */
-            put_ipv6_key(&mask, &wc->masks, true);
-        }
+        or_masks(&mask, &orig_mask, ovs_key_ipv6_offsetof_sizeof_arr);
+        put_ipv6_key(&mask, &wc->masks, true);
     }
 }
 
@@ -7894,17 +7948,19 @@ static enum slow_path_reason
 commit_set_arp_action(const struct flow *flow, struct flow *base_flow,
                       struct ofpbuf *odp_actions, struct flow_wildcards *wc)
 {
-    struct ovs_key_arp key, mask, base;
+    struct ovs_key_arp key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_arp_offsetof_sizeof_arr[] =
         OVS_KEY_ARP_OFFSETOF_SIZEOF_ARR;
 
     get_arp_key(flow, &key);
     get_arp_key(base_flow, &base);
     get_arp_key(&wc->masks, &mask);
+    memcpy(&orig_mask, &mask, sizeof mask);
 
     if (commit(OVS_KEY_ATTR_ARP, true, &key, &base, &mask, sizeof key,
                ovs_key_arp_offsetof_sizeof_arr, odp_actions)) {
         put_arp_key(&base, base_flow);
+        or_masks(&mask, &orig_mask, ovs_key_arp_offsetof_sizeof_arr);
         put_arp_key(&mask, &wc->masks);
         return SLOW_ACTION;
     }
@@ -7931,7 +7987,7 @@ static enum slow_path_reason
 commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
                        struct ofpbuf *odp_actions, struct flow_wildcards *wc)
 {
-    struct ovs_key_icmp key, mask, base;
+    struct ovs_key_icmp key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_icmp_offsetof_sizeof_arr[] =
         OVS_KEY_ICMP_OFFSETOF_SIZEOF_ARR;
     enum ovs_key_attr attr;
@@ -7947,10 +8003,12 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
     get_icmp_key(flow, &key);
     get_icmp_key(base_flow, &base);
     get_icmp_key(&wc->masks, &mask);
+    memcpy(&orig_mask, &mask, sizeof mask);
 
     if (commit(attr, false, &key, &base, &mask, sizeof key,
                ovs_key_icmp_offsetof_sizeof_arr, odp_actions)) {
         put_icmp_key(&base, base_flow);
+        or_masks(&mask, &orig_mask, ovs_key_icmp_offsetof_sizeof_arr);
         put_icmp_key(&mask, &wc->masks);
         return SLOW_ACTION;
     }
@@ -7998,17 +8056,19 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow,
                      struct ofpbuf *odp_actions,
                      struct flow_wildcards *wc, bool use_masked)
 {
-    struct ovs_key_nd key, mask, base;
+    struct ovs_key_nd key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_nd_offsetof_sizeof_arr[] =
         OVS_KEY_ND_OFFSETOF_SIZEOF_ARR;
 
     get_nd_key(flow, &key);
     get_nd_key(base_flow, &base);
     get_nd_key(&wc->masks, &mask);
+    memcpy(&orig_mask, &mask, sizeof mask);
 
     if (commit(OVS_KEY_ATTR_ND, use_masked, &key, &base, &mask, sizeof key,
                ovs_key_nd_offsetof_sizeof_arr, odp_actions)) {
         put_nd_key(&base, base_flow);
+        or_masks(&mask, &orig_mask, ovs_key_nd_offsetof_sizeof_arr);
         put_nd_key(&mask, &wc->masks);
         return SLOW_ACTION;
     }
@@ -8022,18 +8082,20 @@ commit_set_nd_extensions_action(const struct flow *flow,
                                 struct ofpbuf *odp_actions,
                                 struct flow_wildcards *wc, bool use_masked)
 {
-    struct ovs_key_nd_extensions key, mask, base;
+    struct ovs_key_nd_extensions key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_nd_extensions_offsetof_sizeof_arr[] =
         OVS_KEY_ND_EXTENSIONS_OFFSETOF_SIZEOF_ARR;
 
     get_nd_extensions_key(flow, &key);
     get_nd_extensions_key(base_flow, &base);
     get_nd_extensions_key(&wc->masks, &mask);
+    memcpy(&orig_mask, &mask, sizeof mask);
 
     if (commit(OVS_KEY_ATTR_ND_EXTENSIONS, use_masked, &key, &base, &mask,
                sizeof key, ovs_key_nd_extensions_offsetof_sizeof_arr,
                odp_actions)) {
         put_nd_extensions_key(&base, base_flow);
+        or_masks(&mask, &orig_mask, ovs_key_nd_extensions_offsetof_sizeof_arr);
         put_nd_extensions_key(&mask, &wc->masks);
         return SLOW_ACTION;
     }
@@ -8248,7 +8310,7 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
                        bool use_masked)
 {
     enum ovs_key_attr key_type;
-    union ovs_key_tp key, mask, base;
+    union ovs_key_tp key, mask, orig_mask, base;
     struct offsetof_sizeof ovs_key_tp_offsetof_sizeof_arr[] =
         OVS_KEY_TCP_OFFSETOF_SIZEOF_ARR;
 
@@ -8274,10 +8336,12 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
     get_tp_key(flow, &key);
     get_tp_key(base_flow, &base);
     get_tp_key(&wc->masks, &mask);
+    memcpy(&orig_mask, &mask, sizeof mask);
 
     if (commit(key_type, use_masked, &key, &base, &mask, sizeof key,
                ovs_key_tp_offsetof_sizeof_arr, odp_actions)) {
         put_tp_key(&base, base_flow);
+        or_masks(&mask, &orig_mask, ovs_key_tp_offsetof_sizeof_arr);
         put_tp_key(&mask, &wc->masks);
     }
 }
@@ -8301,7 +8365,7 @@ commit_set_priority_action(const struct flow *flow, struct flow *base_flow,
     if (commit(OVS_KEY_ATTR_PRIORITY, use_masked, &key, &base, &mask,
                sizeof key, ovs_key_prio_offsetof_sizeof_arr, odp_actions)) {
         base_flow->skb_priority = base;
-        wc->masks.skb_priority = mask;
+        wc->masks.skb_priority |= mask;
     }
 }
 
@@ -8325,7 +8389,7 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow,
                sizeof key, ovs_key_pkt_mark_offsetof_sizeof_arr,
                odp_actions)) {
         base_flow->pkt_mark = base;
-        wc->masks.pkt_mark = mask;
+        wc->masks.pkt_mark |= mask;
     }
 }
 
diff --git a/lib/odp-util.h b/lib/odp-util.h
index 4ecce1aac5..936fadf175 100644
--- a/lib/odp-util.h
+++ b/lib/odp-util.h
@@ -356,11 +356,12 @@ struct user_action_cookie {
 };
 BUILD_ASSERT_DECL(sizeof(struct user_action_cookie) == 48);
 
-size_t odp_put_userspace_action(uint32_t pid,
-                                const void *userdata, size_t userdata_size,
-                                odp_port_t tunnel_out_port,
-                                bool include_actions,
-                                struct ofpbuf *odp_actions);
+int odp_put_userspace_action(uint32_t pid,
+                             const void *userdata, size_t userdata_size,
+                             odp_port_t tunnel_out_port,
+                             bool include_actions,
+                             struct ofpbuf *odp_actions,
+                             size_t *odp_actions_ofs);
 void odp_put_tunnel_action(const struct flow_tnl *tunnel,
                            struct ofpbuf *odp_actions,
                            const char *tnl_type);
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index ddef3b0c87..7d729a0e2d 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -3773,11 +3773,22 @@ parse_SET_MPLS_LABEL(char *arg, const struct ofpact_parse_params *pp)
 {
     struct ofpact_mpls_label *mpls_label
         = ofpact_put_SET_MPLS_LABEL(pp->ofpacts);
+    uint32_t label;
+    char *error;
+
     if (*arg == '\0') {
         return xstrdup("set_mpls_label: expected label.");
     }
 
-    mpls_label->label = htonl(atoi(arg));
+    error = str_to_u32(arg, &label);
+    if (error) {
+        return error;
+    }
+
+    if (label & ~0xfffff) {
+        return xasprintf("%s: not a valid MPLS label", arg);
+    }
+    mpls_label->label = htonl(label);
     return NULL;
 }
 
@@ -3833,12 +3844,22 @@ static char * OVS_WARN_UNUSED_RESULT
 parse_SET_MPLS_TC(char *arg, const struct ofpact_parse_params *pp)
 {
     struct ofpact_mpls_tc *mpls_tc = ofpact_put_SET_MPLS_TC(pp->ofpacts);
+    uint8_t tc;
+    char *error;
 
     if (*arg == '\0') {
         return xstrdup("set_mpls_tc: expected tc.");
     }
 
-    mpls_tc->tc = atoi(arg);
+    error = str_to_u8(arg, "MPLS TC", &tc);
+    if (error) {
+        return error;
+    }
+
+    if (tc & ~7) {
+        return xasprintf("%s: not a valid MPLS TC", arg);
+    }
+    mpls_tc->tc = tc;
     return NULL;
 }
 
@@ -3846,7 +3867,7 @@ static void
 format_SET_MPLS_TC(const struct ofpact_mpls_tc *a,
                    const struct ofpact_format_params *fp)
 {
-    ds_put_format(fp->s, "%sset_mpls_ttl(%s%"PRIu8"%s)%s",
+    ds_put_format(fp->s, "%sset_mpls_tc(%s%"PRIu8"%s)%s",
                   colors.paren, colors.end, a->tc,
                   colors.paren, colors.end);
 }
@@ -3885,12 +3906,18 @@ static char * OVS_WARN_UNUSED_RESULT
 parse_SET_MPLS_TTL(char *arg, const struct ofpact_parse_params *pp)
 {
     struct ofpact_mpls_ttl *mpls_ttl = ofpact_put_SET_MPLS_TTL(pp->ofpacts);
+    uint8_t ttl;
+    char *error;
 
     if (*arg == '\0') {
         return xstrdup("set_mpls_ttl: expected ttl.");
     }
 
-    mpls_ttl->ttl = atoi(arg);
+    error = str_to_u8(arg, "MPLS TTL", &ttl);
+    if (error) {
+        return error;
+    }
+    mpls_ttl->ttl = ttl;
     return NULL;
 }
 
@@ -4346,6 +4373,7 @@ decode_NXAST_RAW_ENCAP(const struct nx_action_encap *nae,
 {
     struct ofpact_encap *encap;
     const struct ofp_ed_prop_header *ofp_prop;
+    const size_t encap_ofs = out->size;
     size_t props_len;
     uint16_t n_props = 0;
     int err;
@@ -4373,6 +4401,7 @@ decode_NXAST_RAW_ENCAP(const struct nx_action_encap *nae,
         }
         n_props++;
     }
+    encap = ofpbuf_at_assert(out, encap_ofs, sizeof *encap);
     encap->n_props = n_props;
     out->header = &encap->ofpact;
     ofpact_finish_ENCAP(out, &encap);
@@ -6657,6 +6686,7 @@ parse_CT(char *arg, const struct ofpact_parse_params *pp)
     }
 
     if (ofpbuf_oversized(pp->ofpacts)) {
+        free(error);
         return xasprintf("input too big");
     }
 
diff --git a/lib/ofp-ed-props.c b/lib/ofp-ed-props.c
index 28382e0123..02a9235d51 100644
--- a/lib/ofp-ed-props.c
+++ b/lib/ofp-ed-props.c
@@ -49,7 +49,7 @@ decode_ed_prop(const struct ofp_ed_prop_header **ofp_prop,
                 return OFPERR_NXBAC_BAD_ED_PROP;
             }
             struct ofpact_ed_prop_nsh_md_type *pnmt =
-                    ofpbuf_put_uninit(out, sizeof(*pnmt));
+                    ofpbuf_put_zeros(out, sizeof *pnmt);
             pnmt->header.prop_class = prop_class;
             pnmt->header.type = prop_type;
             pnmt->header.len = len;
@@ -108,6 +108,7 @@ encode_ed_prop(const struct ofpact_ed_prop **prop,
             opnmt->header.len =
                     offsetof(struct ofp_ed_prop_nsh_md_type, pad);
             opnmt->md_type = pnmt->md_type;
+            memset(opnmt->pad, 0, sizeof opnmt->pad);
             prop_len = sizeof(*pnmt);
             break;
         }
diff --git a/lib/ofp-group.c b/lib/ofp-group.c
index b675e802c3..cc33feda4a 100644
--- a/lib/ofp-group.c
+++ b/lib/ofp-group.c
@@ -64,7 +64,7 @@ ofputil_group_from_string(const char *s, uint32_t *group_idp)
 void
 ofputil_format_group(uint32_t group_id, struct ds *s)
 {
-    char name[MAX_GROUP_NAME_LEN];
+    char name[MAX_GROUP_NAME_LEN + 1];
 
     ofputil_group_to_string(group_id, name, sizeof name);
     ds_put_cstr(s, name);
diff --git a/lib/ovs-actions.xml b/lib/ovs-actions.xml
index ab8e08b84d..8f8c9041ac 100644
--- a/lib/ovs-actions.xml
+++ b/lib/ovs-actions.xml
@@ -1649,7 +1649,7 @@ for <var>i</var> in [1,<var>n_slaves</var>]:
 
     <action name="CT">
       <h2>The <code>ct</code> action</h2>
-      <syntax><code>ct(<var>argument</var></code>]...<code>)</code></syntax>
+      <syntax><code>ct(</code>[<code><var>argument</var></code>]...<code>)</code></syntax>
       <syntax><code>ct(commit</code>[<code>, <var>argument</var></code>]...<code>)</code></syntax>
 
       <p>
@@ -1816,6 +1816,16 @@ for <var>i</var> in [1,<var>n_slaves</var>]:
             connection, will behave the same as a bare <code>nat</code>.
           </p>
 
+          <p>
+            For SNAT, there is a special case when the <code>src</code> IP
+            address is configured as all 0's, i.e.,
+            <code>nat(src=0.0.0.0)</code>. In this case, when a source port
+            collision is detected during the commit, the source port will be
+            translated to an ephemeral port. If there is no collision, no SNAT
+            is performed. Note that this is currently only implemented in the
+            Linux kernel datapath.
+          </p>
+
           <p>
             Open vSwitch 2.6 introduced <code>nat</code>.  Linux 4.6 was the
             earliest upstream kernel that implemented <code>ct</code> support for
diff --git a/lib/ovs-rcu.c b/lib/ovs-rcu.c
index ebc8120f0f..cde1e925ba 100644
--- a/lib/ovs-rcu.c
+++ b/lib/ovs-rcu.c
@@ -30,6 +30,8 @@
 
 VLOG_DEFINE_THIS_MODULE(ovs_rcu);
 
+#define MIN_CBS 16
+
 struct ovsrcu_cb {
     void (*function)(void *aux);
     void *aux;
@@ -37,7 +39,8 @@ struct ovsrcu_cb {
 
 struct ovsrcu_cbset {
     struct ovs_list list_node;
-    struct ovsrcu_cb cbs[16];
+    struct ovsrcu_cb *cbs;
+    size_t n_allocated;
     int n_cbs;
 };
 
@@ -310,16 +313,19 @@ ovsrcu_postpone__(void (*function)(void *aux), void *aux)
     cbset = perthread->cbset;
     if (!cbset) {
         cbset = perthread->cbset = xmalloc(sizeof *perthread->cbset);
+        cbset->cbs = xmalloc(MIN_CBS * sizeof *cbset->cbs);
+        cbset->n_allocated = MIN_CBS;
         cbset->n_cbs = 0;
     }
 
+    if (cbset->n_cbs == cbset->n_allocated) {
+        cbset->cbs = x2nrealloc(cbset->cbs, &cbset->n_allocated,
+                                sizeof *cbset->cbs);
+    }
+
     cb = &cbset->cbs[cbset->n_cbs++];
     cb->function = function;
     cb->aux = aux;
-
-    if (cbset->n_cbs >= ARRAY_SIZE(cbset->cbs)) {
-        ovsrcu_flush_cbset(perthread);
-    }
 }
 
 static bool
@@ -341,6 +347,7 @@ ovsrcu_call_postponed(void)
         for (cb = cbset->cbs; cb < &cbset->cbs[cbset->n_cbs]; cb++) {
             cb->function(cb->aux);
         }
+        free(cbset->cbs);
         free(cbset);
     }
 
diff --git a/lib/ovs-router.c b/lib/ovs-router.c
index bfb2b7071b..09b81c6e5a 100644
--- a/lib/ovs-router.c
+++ b/lib/ovs-router.c
@@ -505,7 +505,7 @@ ovs_router_flush(void)
     ovs_mutex_lock(&mutex);
     classifier_defer(&cls);
     CLS_FOR_EACH(rt, cr, &cls) {
-        if (rt->priority == rt->plen) {
+        if (rt->priority == rt->plen || rt->local) {
             rt_entry_delete__(&rt->cr);
         }
     }
diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h
index 30d1d08eba..00497d940c 100644
--- a/lib/ovsdb-idl-provider.h
+++ b/lib/ovsdb-idl-provider.h
@@ -122,8 +122,12 @@ struct ovsdb_idl_table {
     unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX];
     struct ovs_list indexes;    /* Contains "struct ovsdb_idl_index"s */
     struct ovs_list track_list; /* Tracked rows (ovsdb_idl_row.track_node). */
-    struct ovsdb_idl_condition condition;
-    bool cond_changed;
+    struct ovsdb_idl_condition *ack_cond; /* Last condition acked by the
+                                           * server. */
+    struct ovsdb_idl_condition *req_cond; /* Last condition requested to the
+                                           * server. */
+    struct ovsdb_idl_condition *new_cond; /* Latest condition set by the IDL
+                                           * client. */
 };
 
 struct ovsdb_idl_class {
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 190143f363..325050f21e 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -219,9 +219,12 @@ struct ovsdb_idl_db {
 
     /* Last db txn id, used for fast resync through monitor_cond_since */
     struct uuid last_id;
+    struct ovs_list deleted_untracked_rows; /* Stores rows deleted in the
+                                             * current run, that are not yet
+                                             * added to the track_list. */
 };
 
-static void ovsdb_idl_db_track_clear(struct ovsdb_idl_db *);
+static void ovsdb_idl_db_track_clear(struct ovsdb_idl_db *, bool flush_all);
 static void ovsdb_idl_db_add_column(struct ovsdb_idl_db *,
                                     const struct ovsdb_idl_column *);
 static void ovsdb_idl_db_omit(struct ovsdb_idl_db *,
@@ -240,6 +243,10 @@ static void ovsdb_idl_send_monitor_request(struct ovsdb_idl *,
                                            struct ovsdb_idl_db *,
                                            enum ovsdb_idl_monitor_method);
 static void ovsdb_idl_db_clear(struct ovsdb_idl_db *db);
+static void ovsdb_idl_db_ack_condition(struct ovsdb_idl_db *db);
+static void ovsdb_idl_db_sync_condition(struct ovsdb_idl_db *db);
+static void ovsdb_idl_condition_move(struct ovsdb_idl_condition **dst,
+                                     struct ovsdb_idl_condition **src);
 
 struct ovsdb_idl {
     struct ovsdb_idl_db server;
@@ -330,6 +337,7 @@ static void ovsdb_idl_delete_row(struct ovsdb_idl_row *);
 static bool ovsdb_idl_modify_row(struct ovsdb_idl_row *, const struct json *);
 static bool ovsdb_idl_modify_row_by_diff(struct ovsdb_idl_row *,
                                          const struct json *);
+static void ovsdb_idl_reparse_deleted(struct ovsdb_idl_db *);
 
 static bool ovsdb_idl_row_is_orphan(const struct ovsdb_idl_row *);
 static struct ovsdb_idl_row *ovsdb_idl_row_create__(
@@ -346,6 +354,10 @@ static void ovsdb_idl_row_unparse(struct ovsdb_idl_row *);
 static void ovsdb_idl_row_clear_old(struct ovsdb_idl_row *);
 static void ovsdb_idl_row_clear_new(struct ovsdb_idl_row *);
 static void ovsdb_idl_row_clear_arcs(struct ovsdb_idl_row *, bool destroy_dsts);
+static void ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *);
+static void ovsdb_idl_row_track_change(struct ovsdb_idl_row *,
+                                       enum ovsdb_idl_change);
+static void ovsdb_idl_row_untrack_change(struct ovsdb_idl_row *);
 
 static void ovsdb_idl_db_txn_abort_all(struct ovsdb_idl_db *);
 static void ovsdb_idl_txn_abort_all(struct ovsdb_idl *);
@@ -379,7 +391,6 @@ ovsdb_idl_db_table_from_class(const struct ovsdb_idl_db *,
 static struct ovsdb_idl_table *
 ovsdb_idl_table_from_class(const struct ovsdb_idl *,
                            const struct ovsdb_idl_table_class *);
-static bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table);
 static void ovsdb_idl_send_cond_change(struct ovsdb_idl *idl);
 
 static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *);
@@ -422,15 +433,20 @@ ovsdb_idl_db_init(struct ovsdb_idl_db *db, const struct ovsdb_idl_class *class,
             = table->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
             = table->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0;
         table->db = db;
-        ovsdb_idl_condition_init(&table->condition);
-        ovsdb_idl_condition_add_clause_true(&table->condition);
-        table->cond_changed = false;
+        table->ack_cond = NULL;
+        table->req_cond = NULL;
+        table->new_cond = xmalloc(sizeof *table->new_cond);
+        ovsdb_idl_condition_init(table->new_cond);
+        ovsdb_idl_condition_add_clause_true(table->new_cond);
     }
     db->monitor_id = json_array_create_2(json_string_create("monid"),
                                          json_string_create(class->database));
     hmap_init(&db->outstanding_txns);
+    ovs_list_init(&db->deleted_untracked_rows);
 }
 
+static void add_tracked_change_for_references(struct ovsdb_idl_row *);
+
 /* Creates and returns a connection to database 'remote', which should be in a
  * form acceptable to jsonrpc_session_open().  The connection will maintain an
  * in-memory replica of the remote database whose schema is described by
@@ -556,12 +572,15 @@ ovsdb_idl_set_shuffle_remotes(struct ovsdb_idl *idl, bool shuffle)
 static void
 ovsdb_idl_db_destroy(struct ovsdb_idl_db *db)
 {
+    struct ovsdb_idl_condition *null_cond = NULL;
     ovs_assert(!db->txn);
     ovsdb_idl_db_txn_abort_all(db);
     ovsdb_idl_db_clear(db);
     for (size_t i = 0; i < db->class_->n_tables; i++) {
         struct ovsdb_idl_table *table = &db->tables[i];
-        ovsdb_idl_condition_destroy(&table->condition);
+        ovsdb_idl_condition_move(&table->ack_cond, &null_cond);
+        ovsdb_idl_condition_move(&table->req_cond, &null_cond);
+        ovsdb_idl_condition_move(&table->new_cond, &null_cond);
         ovsdb_idl_destroy_indexes(table);
         shash_destroy(&table->columns);
         hmap_destroy(&table->rows);
@@ -606,11 +625,18 @@ ovsdb_idl_db_clear(struct ovsdb_idl_db *db)
     bool changed = false;
     size_t i;
 
+    /* Process deleted rows, removing them from the 'deleted_untracked_rows'
+     * list and reparsing their backrefs.
+     */
+    ovsdb_idl_reparse_deleted(db);
+
+    /* Cleanup all rows; each row gets added to its own table's
+     * 'track_list'.
+     */
     for (i = 0; i < db->class_->n_tables; i++) {
         struct ovsdb_idl_table *table = &db->tables[i];
         struct ovsdb_idl_row *row, *next_row;
 
-        table->cond_changed = false;
         if (hmap_is_empty(&table->rows)) {
             continue;
         }
@@ -624,19 +650,27 @@ ovsdb_idl_db_clear(struct ovsdb_idl_db *db)
                 ovsdb_idl_row_unparse(row);
             }
             LIST_FOR_EACH_SAFE (arc, next_arc, src_node, &row->src_arcs) {
+                ovs_list_remove(&arc->src_node);
+                ovs_list_remove(&arc->dst_node);
+                free(arc);
+            }
+            LIST_FOR_EACH_SAFE (arc, next_arc, dst_node, &row->dst_arcs) {
+                ovs_list_remove(&arc->src_node);
+                ovs_list_remove(&arc->dst_node);
                 free(arc);
             }
-            /* No need to do anything with dst_arcs: some node has those arcs
-             * as forward arcs and will destroy them itself. */
 
             ovsdb_idl_row_destroy(row);
         }
     }
+
+    /* Free rows deleted from tables with change tracking disabled. */
     ovsdb_idl_row_destroy_postprocess(db);
 
-    db->cond_changed = false;
     db->cond_seqno = 0;
-    ovsdb_idl_db_track_clear(db);
+    /* Free rows deleted from tables with change tracking enabled. */
+    ovsdb_idl_db_track_clear(db, true);
+    ovs_assert(ovs_list_is_empty(&db->deleted_untracked_rows));
 
     if (changed) {
         db->change_seqno++;
@@ -692,6 +726,12 @@ ovsdb_idl_send_request(struct ovsdb_idl *idl, struct jsonrpc_msg *request)
 static void
 ovsdb_idl_restart_fsm(struct ovsdb_idl *idl)
 {
+    /* Resync data DB table conditions to avoid missing updates due to
+     * conditions that were in flight or changed locally while the connection
+     * was down.
+     */
+    ovsdb_idl_db_sync_condition(&idl->data);
+
     ovsdb_idl_send_schema_request(idl, &idl->server);
     ovsdb_idl_transition(idl, IDL_S_SERVER_SCHEMA_REQUESTED);
     idl->data.monitoring = OVSDB_IDL_NOT_MONITORING;
@@ -799,7 +839,9 @@ ovsdb_idl_process_response(struct ovsdb_idl *idl, struct jsonrpc_msg *msg)
          * do, it's a "monitor_cond_change", which means that the conditional
          * monitor clauses were updated.
          *
-         * If further condition changes were pending, send them now. */
+         * Mark the last requested conditions as acked and if further
+         * condition changes were pending, send them now. */
+        ovsdb_idl_db_ack_condition(&idl->data);
         ovsdb_idl_send_cond_change(idl);
         idl->data.cond_seqno++;
         break;
@@ -912,6 +954,7 @@ ovsdb_idl_run(struct ovsdb_idl *idl)
         ovsdb_idl_process_msg(idl, msg);
         jsonrpc_msg_destroy(msg);
     }
+    ovsdb_idl_reparse_deleted(&idl->data);
     ovsdb_idl_row_destroy_postprocess(&idl->data);
 }
 
@@ -1495,17 +1538,34 @@ ovsdb_idl_condition_equals(const struct ovsdb_idl_condition *a,
 }
 
 static void
-ovsdb_idl_condition_clone(struct ovsdb_idl_condition *dst,
+ovsdb_idl_condition_clone(struct ovsdb_idl_condition **dst,
                           const struct ovsdb_idl_condition *src)
 {
-    ovsdb_idl_condition_init(dst);
+    if (*dst) {
+        ovsdb_idl_condition_destroy(*dst);
+    } else {
+        *dst = xmalloc(sizeof **dst);
+    }
+    ovsdb_idl_condition_init(*dst);
 
-    dst->is_true = src->is_true;
+    (*dst)->is_true = src->is_true;
 
     const struct ovsdb_idl_clause *clause;
     HMAP_FOR_EACH (clause, hmap_node, &src->clauses) {
-        ovsdb_idl_condition_add_clause__(dst, clause, clause->hmap_node.hash);
+        ovsdb_idl_condition_add_clause__(*dst, clause, clause->hmap_node.hash);
+    }
+}
+
+static void
+ovsdb_idl_condition_move(struct ovsdb_idl_condition **dst,
+                         struct ovsdb_idl_condition **src)
+{
+    if (*dst) {
+        ovsdb_idl_condition_destroy(*dst);
+        free(*dst);
     }
+    *dst = *src;
+    *src = NULL;
 }
 
 static unsigned int
@@ -1513,17 +1573,49 @@ ovsdb_idl_db_set_condition(struct ovsdb_idl_db *db,
                            const struct ovsdb_idl_table_class *tc,
                            const struct ovsdb_idl_condition *condition)
 {
+    struct ovsdb_idl_condition *table_cond;
     struct ovsdb_idl_table *table = ovsdb_idl_db_table_from_class(db, tc);
-    unsigned int seqno = db->cond_seqno;
-    if (!ovsdb_idl_condition_equals(condition, &table->condition)) {
-        ovsdb_idl_condition_destroy(&table->condition);
-        ovsdb_idl_condition_clone(&table->condition, condition);
-        db->cond_changed = table->cond_changed = true;
+
+    /* Compare the new condition to the last known condition which can be
+     * either "new" (not sent yet), "requested" or "acked", in this order.
+     */
+    if (table->new_cond) {
+        table_cond = table->new_cond;
+    } else if (table->req_cond) {
+        table_cond = table->req_cond;
+    } else {
+        table_cond = table->ack_cond;
+    }
+    ovs_assert(table_cond);
+
+    if (!ovsdb_idl_condition_equals(condition, table_cond)) {
+        ovsdb_idl_condition_clone(&table->new_cond, condition);
+        db->cond_changed = true;
         poll_immediate_wake();
-        return seqno + 1;
     }
 
-    return seqno;
+    /* Conditions will be up to date when we receive replies for already
+     * requested and new conditions, if any.  This includes condition change
+     * requests for other tables too.
+     */
+    if (table->new_cond) {
+        /* New condition will be sent out after all already requested ones
+         * are acked.
+         */
+        bool any_req_cond = false;
+        for (size_t i = 0; i < db->class_->n_tables; i++) {
+            if (db->tables[i].req_cond) {
+                any_req_cond = true;
+                break;
+            }
+        }
+        return db->cond_seqno + any_req_cond + 1;
+    } else {
+        /* Already requested conditions should be up to date at
+         * db->cond_seqno + 1 while acked conditions are already up to date.
+         */
+        return db->cond_seqno + !!table->req_cond;
+    }
 }
 
 /* Sets the replication condition for 'tc' in 'idl' to 'condition' and
@@ -1563,9 +1655,8 @@ ovsdb_idl_condition_to_json(const struct ovsdb_idl_condition *cnd)
 }
 
 static struct json *
-ovsdb_idl_create_cond_change_req(struct ovsdb_idl_table *table)
+ovsdb_idl_create_cond_change_req(const struct ovsdb_idl_condition *cond)
 {
-    const struct ovsdb_idl_condition *cond = &table->condition;
     struct json *monitor_cond_change_request = json_object_create();
     struct json *cond_json = ovsdb_idl_condition_to_json(cond);
 
@@ -1585,8 +1676,12 @@ ovsdb_idl_db_compose_cond_change(struct ovsdb_idl_db *db)
     for (size_t i = 0; i < db->class_->n_tables; i++) {
         struct ovsdb_idl_table *table = &db->tables[i];
 
-        if (table->cond_changed) {
-            struct json *req = ovsdb_idl_create_cond_change_req(table);
+        /* Always use the most recent conditions set by the IDL client when
+         * requesting monitor_cond_change, i.e., table->new_cond.
+         */
+        if (table->new_cond) {
+            struct json *req =
+                ovsdb_idl_create_cond_change_req(table->new_cond);
             if (req) {
                 if (!monitor_cond_change_requests) {
                     monitor_cond_change_requests = json_object_create();
@@ -1595,7 +1690,11 @@ ovsdb_idl_db_compose_cond_change(struct ovsdb_idl_db *db)
                              table->class_->name,
                              json_array_create_1(req));
             }
-            table->cond_changed = false;
+            /* Mark the new condition as requested by moving it to req_cond.
+             * If there's already requested condition that's a bug.
+             */
+            ovs_assert(table->req_cond == NULL);
+            ovsdb_idl_condition_move(&table->req_cond, &table->new_cond);
         }
     }
 
@@ -1610,6 +1709,73 @@ ovsdb_idl_db_compose_cond_change(struct ovsdb_idl_db *db)
     return jsonrpc_create_request("monitor_cond_change", params, NULL);
 }
 
+/* Marks all requested table conditions in 'db' as acked by the server.
+ * It should be called when the server replies to monitor_cond_change
+ * requests.
+ */
+static void
+ovsdb_idl_db_ack_condition(struct ovsdb_idl_db *db)
+{
+    for (size_t i = 0; i < db->class_->n_tables; i++) {
+        struct ovsdb_idl_table *table = &db->tables[i];
+
+        if (table->req_cond) {
+            ovsdb_idl_condition_move(&table->ack_cond, &table->req_cond);
+        }
+    }
+}
+
+/* Should be called when the IDL fsm is restarted and resyncs table conditions
+ * based on the state the DB is in:
+ * - if a non-zero last_id is available for the DB then upon reconnect
+ *   the IDL should first request acked conditions to avoid missing updates
+ *   about records that were added before the transaction with
+ *   txn-id == last_id. If there were requested condition changes in flight
+ *   (i.e., req_cond not NULL) and the IDL client didn't set new conditions
+ *   (i.e., new_cond is NULL) then move req_cond to new_cond to trigger a
+ *   follow up monitor_cond_change request.
+ * - if there's no last_id available for the DB then it's safe to use the
+ *   latest conditions set by the IDL client even if they weren't acked yet.
+ */
+static void
+ovsdb_idl_db_sync_condition(struct ovsdb_idl_db *db)
+{
+    bool ack_all = uuid_is_zero(&db->last_id);
+
+    db->cond_changed = false;
+    for (size_t i = 0; i < db->class_->n_tables; i++) {
+        struct ovsdb_idl_table *table = &db->tables[i];
+
+        /* When monitor_cond_since requests will be issued, the
+         * table->ack_cond condition will be added to the "where" clause".
+         * Follow up monitor_cond_change requests will use table->new_cond.
+         */
+        if (ack_all) {
+            if (table->new_cond) {
+                ovsdb_idl_condition_move(&table->req_cond, &table->new_cond);
+            }
+
+            if (table->req_cond) {
+                ovsdb_idl_condition_move(&table->ack_cond, &table->req_cond);
+            }
+        } else {
+            /* If there was no "unsent" condition but instead a
+             * monitor_cond_change request was in flight, move table->req_cond
+             * to table->new_cond and set db->cond_changed to trigger a new
+             * monitor_cond_change request.
+             *
+             * However, if a new condition has been set by the IDL client,
+             * monitor_cond_change will be sent anyway and will use the most
+             * recent table->new_cond so there's no need to update it here.
+             */
+            if (table->req_cond && !table->new_cond) {
+                ovsdb_idl_condition_move(&table->new_cond, &table->req_cond);
+                db->cond_changed = true;
+            }
+        }
+    }
+}
+
 static void
 ovsdb_idl_send_cond_change(struct ovsdb_idl *idl)
 {
@@ -1739,7 +1905,7 @@ ovsdb_idl_track_add_all(struct ovsdb_idl *idl)
 }
 
 /* Returns true if 'table' has any tracked column. */
-static bool
+bool
 ovsdb_idl_track_is_set(struct ovsdb_idl_table *table)
 {
     size_t i;
@@ -1753,29 +1919,37 @@ ovsdb_idl_track_is_set(struct ovsdb_idl_table *table)
 }
 
 /* Returns the first tracked row in table with class 'table_class'
- * for the specified 'idl'. Returns NULL if there are no tracked rows */
+ * for the specified 'idl'. Returns NULL if there are no tracked rows.
+ * Pure orphan rows, i.e. rows that never had any datum, are skipped. */
 const struct ovsdb_idl_row *
 ovsdb_idl_track_get_first(const struct ovsdb_idl *idl,
                           const struct ovsdb_idl_table_class *table_class)
 {
     struct ovsdb_idl_table *table
         = ovsdb_idl_db_table_from_class(&idl->data, table_class);
+    struct ovsdb_idl_row *row;
 
-    if (!ovs_list_is_empty(&table->track_list)) {
-        return CONTAINER_OF(ovs_list_front(&table->track_list), struct ovsdb_idl_row, track_node);
+    LIST_FOR_EACH (row, track_node, &table->track_list) {
+        if (!ovsdb_idl_row_is_orphan(row) || row->tracked_old_datum) {
+            return row;
+        }
     }
     return NULL;
 }
 
 /* Returns the next tracked row in table after the specified 'row'
- * (in no particular order). Returns NULL if there are no tracked rows */
+ * (in no particular order). Returns NULL if there are no tracked rows.
+ * Pure orphan rows, i.e. rows that never had any datum, are skipped.*/
 const struct ovsdb_idl_row *
 ovsdb_idl_track_get_next(const struct ovsdb_idl_row *row)
 {
-    if (row->track_node.next != &row->table->track_list) {
-        return CONTAINER_OF(row->track_node.next, struct ovsdb_idl_row, track_node);
-    }
+    struct ovsdb_idl_table *table = row->table;
 
+    LIST_FOR_EACH_CONTINUE (row, track_node, &table->track_list) {
+        if (!ovsdb_idl_row_is_orphan(row) || row->tracked_old_datum) {
+            return row;
+        }
+    }
     return NULL;
 }
 
@@ -1808,7 +1982,7 @@ ovsdb_idl_track_is_updated(const struct ovsdb_idl_row *row,
  * loop when it is ready to do ovsdb_idl_run() again.
  */
 static void
-ovsdb_idl_db_track_clear(struct ovsdb_idl_db *db)
+ovsdb_idl_db_track_clear(struct ovsdb_idl_db *db, bool flush_all)
 {
     size_t i;
 
@@ -1823,19 +1997,34 @@ ovsdb_idl_db_track_clear(struct ovsdb_idl_db *db)
                     free(row->updated);
                     row->updated = NULL;
                 }
-                ovs_list_remove(&row->track_node);
-                ovs_list_init(&row->track_node);
-                if (ovsdb_idl_row_is_orphan(row) && row->tracked_old_datum) {
+                ovsdb_idl_row_untrack_change(row);
+
+                if (ovsdb_idl_row_is_orphan(row)) {
                     ovsdb_idl_row_unparse(row);
-                    const struct ovsdb_idl_table_class *class =
-                                                        row->table->class_;
-                    for (size_t c = 0; c < class->n_columns; c++) {
-                        ovsdb_datum_destroy(&row->tracked_old_datum[c],
-                                            &class->columns[c].type);
+                    if (row->tracked_old_datum) {
+                        const struct ovsdb_idl_table_class *class =
+                            row->table->class_;
+                        for (size_t c = 0; c < class->n_columns; c++) {
+                            ovsdb_datum_destroy(&row->tracked_old_datum[c],
+                                                &class->columns[c].type);
+                        }
+                        free(row->tracked_old_datum);
+                        row->tracked_old_datum = NULL;
+                    }
+
+                    /* Rows that were reused as orphan after being processed
+                     * for deletion are still in the table hmap and will be
+                     * cleaned up when their src arcs are removed.  These rows
+                     * will not be reported anymore as "deleted" to IDL
+                     * clients.
+                     *
+                     * The exception is when 'destroy' is explicitly set to
+                     * 'true' which usually happens when the complete IDL
+                     * contents are being flushed.
+                     */
+                    if (flush_all || ovs_list_is_empty(&row->dst_arcs)) {
+                        free(row);
                     }
-                    free(row->tracked_old_datum);
-                    row->tracked_old_datum = NULL;
-                    free(row);
                 }
             }
         }
@@ -1850,7 +2039,7 @@ ovsdb_idl_db_track_clear(struct ovsdb_idl_db *db)
 void
 ovsdb_idl_track_clear(struct ovsdb_idl *idl)
 {
-    ovsdb_idl_db_track_clear(&idl->data);
+    ovsdb_idl_db_track_clear(&idl->data, false);
 }
 
 static void
@@ -2064,13 +2253,15 @@ ovsdb_idl_send_monitor_request(struct ovsdb_idl *idl, struct ovsdb_idl_db *db,
             monitor_request = json_object_create();
             json_object_put(monitor_request, "columns", columns);
 
-            const struct ovsdb_idl_condition *cond = &table->condition;
+            /* Always use acked conditions when requesting
+             * monitor_cond/monitor_cond_since.
+             */
+            const struct ovsdb_idl_condition *cond = table->ack_cond;
             if ((monitor_method == OVSDB_IDL_MM_MONITOR_COND ||
                  monitor_method == OVSDB_IDL_MM_MONITOR_COND_SINCE) &&
-                !ovsdb_idl_condition_is_true(cond)) {
+                cond && !ovsdb_idl_condition_is_true(cond)) {
                 json_object_put(monitor_request, "where",
                                 ovsdb_idl_condition_to_json(cond));
-                table->cond_changed = false;
             }
             json_object_put(monitor_requests, tc->name,
                             json_array_create_1(monitor_request));
@@ -2078,8 +2269,6 @@ ovsdb_idl_send_monitor_request(struct ovsdb_idl *idl, struct ovsdb_idl_db *db,
     }
     free_schema(schema);
 
-    db->cond_changed = false;
-
     struct json *params = json_array_create_3(
                               json_string_create(db->class_->database),
                               json_clone(db->monitor_id),
@@ -2379,6 +2568,33 @@ ovsdb_idl_db_parse_update(struct ovsdb_idl_db *db,
     }
 }
 
+/* Reparses references to rows that have been deleted in the current IDL run.
+ *
+ * To ensure that reference sources that are deleted are not reparsed,
+ * this function must be called after all updates have been processed in
+ * the current IDL run, i.e., after all calls to ovsdb_idl_parse_update().
+ */
+static void
+ovsdb_idl_reparse_deleted(struct ovsdb_idl_db *db)
+{
+    struct ovsdb_idl_row *row, *next;
+
+    LIST_FOR_EACH_SAFE (row, next, track_node, &db->deleted_untracked_rows) {
+        ovsdb_idl_row_untrack_change(row);
+        add_tracked_change_for_references(row);
+        ovsdb_idl_row_reparse_backrefs(row);
+
+        /* Orphan rows that are still unreferenced or are part of tables that
+         * have change tracking enabled should be added to their table's
+         * 'track_list'.
+         */
+        if (ovs_list_is_empty(&row->dst_arcs)
+                || ovsdb_idl_track_is_set(row->table)) {
+            ovsdb_idl_row_track_change(row, OVSDB_IDL_CHANGE_DELETE);
+        }
+    }
+}
+
 static struct ovsdb_idl_row *
 ovsdb_idl_get_row(struct ovsdb_idl_table *table, const struct uuid *uuid)
 {
@@ -2418,6 +2634,7 @@ ovsdb_idl_process_update(struct ovsdb_idl_table *table,
         if (!row) {
             ovsdb_idl_insert_row(ovsdb_idl_row_create(table, uuid), new);
         } else if (ovsdb_idl_row_is_orphan(row)) {
+            ovsdb_idl_row_untrack_change(row);
             ovsdb_idl_insert_row(row, new);
         } else {
             VLOG_WARN_RL(&semantic_rl, "cannot add existing row "UUID_FMT" to "
@@ -2504,22 +2721,20 @@ ovsdb_idl_process_update2(struct ovsdb_idl_table *table,
     return true;
 }
 
-/* Recursively add rows to tracked change lists for current row
- * and the rows that reference this row. */
+/* Recursively add rows to tracked change lists for all rows that reference
+   'row'. */
 static void
 add_tracked_change_for_references(struct ovsdb_idl_row *row)
 {
-    if (ovs_list_is_empty(&row->track_node) &&
-            ovsdb_idl_track_is_set(row->table)) {
-        ovs_list_push_back(&row->table->track_list,
-                           &row->track_node);
-        row->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
-            = row->table->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
-            = row->table->db->change_seqno + 1;
+    const struct ovsdb_idl_arc *arc;
+    LIST_FOR_EACH (arc, dst_node, &row->dst_arcs) {
+        struct ovsdb_idl_row *ref = arc->src;
+
+        if (ovs_list_is_empty(&ref->track_node) &&
+            ovsdb_idl_track_is_set(ref->table)) {
 
-        const struct ovsdb_idl_arc *arc;
-        LIST_FOR_EACH (arc, dst_node, &row->dst_arcs) {
-            add_tracked_change_for_references(arc->src);
+            ovsdb_idl_row_track_change(ref, OVSDB_IDL_CHANGE_MODIFY);
+            add_tracked_change_for_references(ref);
         }
     }
 }
@@ -2587,7 +2802,14 @@ ovsdb_idl_row_change__(struct ovsdb_idl_row *row, const struct json *row_json,
                     row->change_seqno[change]
                         = row->table->change_seqno[change]
                         = row->table->db->change_seqno + 1;
+
                     if (table->modes[column_idx] & OVSDB_IDL_TRACK) {
+                        if (ovs_list_is_empty(&row->track_node) &&
+                            ovsdb_idl_track_is_set(row->table)) {
+                            ovs_list_push_back(&row->table->track_list,
+                                               &row->track_node);
+                        }
+
                         add_tracked_change_for_references(row);
                         if (!row->updated) {
                             row->updated = bitmap_allocate(class->n_columns);
@@ -3021,7 +3243,7 @@ ovsdb_idl_row_clear_old(struct ovsdb_idl_row *row)
 {
     ovs_assert(row->old_datum == row->new_datum);
     if (!ovsdb_idl_row_is_orphan(row)) {
-        if (ovsdb_idl_track_is_set(row->table)) {
+        if (ovsdb_idl_track_is_set(row->table) && !row->tracked_old_datum) {
             row->tracked_old_datum = row->old_datum;
         } else {
             const struct ovsdb_idl_table_class *class = row->table->class_;
@@ -3104,6 +3326,32 @@ ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *row)
     }
 }
 
+static void
+ovsdb_idl_row_track_change(struct ovsdb_idl_row *row,
+                           enum ovsdb_idl_change change)
+{
+    row->change_seqno[change]
+        = row->table->change_seqno[change]
+        = row->table->db->change_seqno + 1;
+    if (ovs_list_is_empty(&row->track_node)) {
+        ovs_list_push_back(&row->table->track_list, &row->track_node);
+    }
+}
+
+static void
+ovsdb_idl_row_untrack_change(struct ovsdb_idl_row *row)
+{
+    if (ovs_list_is_empty(&row->track_node)) {
+        return;
+    }
+
+    row->change_seqno[OVSDB_IDL_CHANGE_INSERT] =
+        row->change_seqno[OVSDB_IDL_CHANGE_MODIFY] =
+        row->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0;
+    ovs_list_remove(&row->track_node);
+    ovs_list_init(&row->track_node);
+}
+
 static struct ovsdb_idl_row *
 ovsdb_idl_row_create__(const struct ovsdb_idl_table_class *class)
 {
@@ -3130,22 +3378,26 @@ ovsdb_idl_row_create(struct ovsdb_idl_table *table, const struct uuid *uuid)
     return row;
 }
 
+/* If 'row' is not referenced anymore, removes 'row' from the table hmap,
+ * clears the old datum and adds 'row' to the table's track_list.
+ *
+ * If 'row' is still referenced, i.e., became "orphan", queues 'row' for
+ * reparsing after all updates have been processed by adding it to the
+ * 'deleted_untracked_rows' list.
+ */
 static void
 ovsdb_idl_row_destroy(struct ovsdb_idl_row *row)
 {
-    if (row) {
-        ovsdb_idl_row_clear_old(row);
+    ovsdb_idl_row_clear_old(row);
+    if (ovs_list_is_empty(&row->dst_arcs)) {
         hmap_remove(&row->table->rows, &row->hmap_node);
         ovsdb_idl_destroy_all_map_op_lists(row);
         ovsdb_idl_destroy_all_set_op_lists(row);
-        if (ovsdb_idl_track_is_set(row->table)) {
-            row->change_seqno[OVSDB_IDL_CHANGE_DELETE]
-                = row->table->change_seqno[OVSDB_IDL_CHANGE_DELETE]
-                = row->table->db->change_seqno + 1;
-        }
-        if (ovs_list_is_empty(&row->track_node)) {
-            ovs_list_push_back(&row->table->track_list, &row->track_node);
-        }
+        ovsdb_idl_row_track_change(row, OVSDB_IDL_CHANGE_DELETE);
+    } else {
+        ovsdb_idl_row_untrack_change(row);
+        ovs_list_push_back(&row->table->db->deleted_untracked_rows,
+                           &row->track_node);
     }
 }
 
@@ -3237,12 +3489,7 @@ ovsdb_idl_delete_row(struct ovsdb_idl_row *row)
 {
     ovsdb_idl_remove_from_indexes(row);
     ovsdb_idl_row_clear_arcs(row, true);
-    ovsdb_idl_row_clear_old(row);
-    if (ovs_list_is_empty(&row->dst_arcs)) {
-        ovsdb_idl_row_destroy(row);
-    } else {
-        ovsdb_idl_row_reparse_backrefs(row);
-    }
+    ovsdb_idl_row_destroy(row);
 }
 
 /* Returns true if a column with mode OVSDB_IDL_MODE_RW changed, false
@@ -4663,6 +4910,7 @@ ovsdb_idl_txn_insert(struct ovsdb_idl_txn *txn,
     hmap_insert(&row->table->rows, &row->hmap_node, uuid_hash(&row->uuid));
     hmap_insert(&txn->txn_rows, &row->txn_node, uuid_hash(&row->uuid));
     ovsdb_idl_add_to_indexes(row);
+
     return row;
 }
 
diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h
index 9f12ce3206..6ad6d3a54e 100644
--- a/lib/ovsdb-idl.h
+++ b/lib/ovsdb-idl.h
@@ -53,6 +53,7 @@ struct ovsdb_datum;
 struct ovsdb_idl_class;
 struct ovsdb_idl_row;
 struct ovsdb_idl_column;
+struct ovsdb_idl_table;
 struct ovsdb_idl_table_class;
 struct uuid;
 
@@ -217,6 +218,7 @@ unsigned int ovsdb_idl_row_get_seqno(
 void ovsdb_idl_track_add_column(struct ovsdb_idl *idl,
                                 const struct ovsdb_idl_column *column);
 void ovsdb_idl_track_add_all(struct ovsdb_idl *idl);
+bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table);
 const struct ovsdb_idl_row *ovsdb_idl_track_get_first(
     const struct ovsdb_idl *, const struct ovsdb_idl_table_class *);
 const struct ovsdb_idl_row *ovsdb_idl_track_get_next(const struct ovsdb_idl_row *);
diff --git a/lib/pcap-file.c b/lib/pcap-file.c
index f0cac8e0fa..7f5561f827 100644
--- a/lib/pcap-file.c
+++ b/lib/pcap-file.c
@@ -89,6 +89,7 @@ ovs_pcap_open(const char *file_name, const char *mode)
                    : mode[0] == 'w' ? "writing"
                    : "appending"),
                   ovs_strerror(errno));
+        free(p_file);
         return NULL;
     }
 
diff --git a/lib/pvector.c b/lib/pvector.c
index aaeee92147..cc527fdc41 100644
--- a/lib/pvector.c
+++ b/lib/pvector.c
@@ -33,7 +33,7 @@ pvector_impl_alloc(size_t size)
     struct pvector_impl *impl;
 
     impl = xmalloc(sizeof *impl + size * sizeof impl->vector[0]);
-    impl->size = 0;
+    atomic_init(&impl->size, 0);
     impl->allocated = size;
 
     return impl;
@@ -117,18 +117,22 @@ pvector_insert(struct pvector *pvec, void *ptr, int priority)
 {
     struct pvector_impl *temp = pvec->temp;
     struct pvector_impl *old = pvector_impl_get(pvec);
+    size_t size;
 
     ovs_assert(ptr != NULL);
 
+    /* There is no possible concurrent writer. Insertions must be protected
+     * by mutex or be always excuted from the same thread. */
+    atomic_read_relaxed(&old->size, &size);
+
     /* Check if can add to the end without reallocation. */
-    if (!temp && old->allocated > old->size &&
-        (!old->size || priority <= old->vector[old->size - 1].priority)) {
-        old->vector[old->size].ptr = ptr;
-        old->vector[old->size].priority = priority;
+    if (!temp && old->allocated > size &&
+        (!size || priority <= old->vector[size - 1].priority)) {
+        old->vector[size].ptr = ptr;
+        old->vector[size].priority = priority;
         /* Size increment must not be visible to the readers before the new
          * entry is stored. */
-        atomic_thread_fence(memory_order_release);
-        ++old->size;
+        atomic_store_explicit(&old->size, size + 1, memory_order_release);
     } else {
         if (!temp) {
             temp = pvector_impl_dup(old);
diff --git a/lib/pvector.h b/lib/pvector.h
index b990ed9d59..0d3290dc37 100644
--- a/lib/pvector.h
+++ b/lib/pvector.h
@@ -69,8 +69,8 @@ struct pvector_entry {
 };
 
 struct pvector_impl {
-    size_t size;       /* Number of entries in the vector. */
-    size_t allocated;  /* Number of allocated entries. */
+    atomic_size_t size;   /* Number of entries in the vector. */
+    size_t allocated;     /* Number of allocated entries. */
     struct pvector_entry vector[];
 };
 
@@ -181,12 +181,17 @@ pvector_cursor_init(const struct pvector *pvec,
 {
     const struct pvector_impl *impl;
     struct pvector_cursor cursor;
+    size_t size;
 
     impl = ovsrcu_get(struct pvector_impl *, &pvec->impl);
 
-    ovs_prefetch_range(impl->vector, impl->size * sizeof impl->vector[0]);
+    /* Use memory_order_acquire to ensure entry access can not be
+     * reordered to happen before size read. */
+    atomic_read_explicit(&CONST_CAST(struct pvector_impl *, impl)->size,
+                         &size, memory_order_acquire);
+    ovs_prefetch_range(impl->vector, size * sizeof impl->vector[0]);
 
-    cursor.size = impl->size;
+    cursor.size = size;
     cursor.vector = impl->vector;
     cursor.entry_idx = -1;
 
diff --git a/lib/reconnect.c b/lib/reconnect.c
index c89abab889..a929ddfd2d 100644
--- a/lib/reconnect.c
+++ b/lib/reconnect.c
@@ -61,6 +61,7 @@ struct reconnect {
     long long int last_activity;
     long long int last_connected;
     long long int last_disconnected;
+    long long int last_receive_attempt;
     unsigned int max_tries;
     unsigned int backoff_free_tries;
 
@@ -109,6 +110,7 @@ reconnect_create(long long int now)
     fsm->last_activity = now;
     fsm->last_connected = LLONG_MAX;
     fsm->last_disconnected = LLONG_MAX;
+    fsm->last_receive_attempt = now;
     fsm->max_tries = UINT_MAX;
     fsm->creation_time = now;
 
@@ -501,6 +503,19 @@ reconnect_activity(struct reconnect *fsm, long long int now)
     fsm->last_activity = now;
 }
 
+/* Tell 'fsm' that some attempt to receive data on the connection was made at
+ * 'now'.  The FSM only allows probe interval timer to expire when some attempt
+ * to receive data on the connection was received after the time when it should
+ * have expired.  This helps in the case where there's a long delay in the poll
+ * loop and then reconnect_run() executes before the code to try to receive
+ * anything from the remote runs.  (To disable this feature, just call
+ * reconnect_receive_attempted(fsm, LLONG_MAX).) */
+void
+reconnect_receive_attempted(struct reconnect *fsm, long long int now)
+{
+    fsm->last_receive_attempt = now;
+}
+
 static void
 reconnect_transition__(struct reconnect *fsm, long long int now,
                        enum state state)
@@ -541,13 +556,19 @@ reconnect_deadline__(const struct reconnect *fsm)
     case S_ACTIVE:
         if (fsm->probe_interval) {
             long long int base = MAX(fsm->last_activity, fsm->state_entered);
-            return base + fsm->probe_interval;
+            long long int expiration = base + fsm->probe_interval;
+            if (fsm->last_receive_attempt >= expiration) {
+                return expiration;
+            }
         }
         return LLONG_MAX;
 
     case S_IDLE:
         if (fsm->probe_interval) {
-            return fsm->state_entered + fsm->probe_interval;
+            long long int expiration = fsm->state_entered + fsm->probe_interval;
+            if (fsm->last_receive_attempt >= expiration) {
+                return expiration;
+            }
         }
         return LLONG_MAX;
 
diff --git a/lib/reconnect.h b/lib/reconnect.h
index 9f2d469e2d..40cc569c42 100644
--- a/lib/reconnect.h
+++ b/lib/reconnect.h
@@ -83,6 +83,7 @@ void reconnect_connected(struct reconnect *, long long int now);
 void reconnect_connect_failed(struct reconnect *, long long int now,
                               int error);
 void reconnect_activity(struct reconnect *, long long int now);
+void reconnect_receive_attempted(struct reconnect *, long long int now);
 
 enum reconnect_action {
     RECONNECT_CONNECT = 1,
diff --git a/lib/sha1.c b/lib/sha1.c
index 4f48ef2102..87360d9cd0 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -197,7 +197,7 @@ sha1_init(struct sha1_ctx *sha_info)
  * inputLen: The length of the input buffer.
  */
 void
-sha1_update(struct sha1_ctx *ctx, const void *buffer_, size_t count)
+sha1_update(struct sha1_ctx *ctx, const void *buffer_, uint32_t count)
 {
     const uint8_t *buffer = buffer_;
     unsigned int i;
@@ -274,7 +274,7 @@ sha1_final(struct sha1_ctx *ctx, uint8_t digest[SHA1_DIGEST_SIZE])
 
 /* Computes the hash of 'n' bytes in 'data' into 'digest'. */
 void
-sha1_bytes(const void *data, size_t n, uint8_t digest[SHA1_DIGEST_SIZE])
+sha1_bytes(const void *data, uint32_t n, uint8_t digest[SHA1_DIGEST_SIZE])
 {
     struct sha1_ctx ctx;
 
diff --git a/lib/sha1.h b/lib/sha1.h
index eda265dfc5..a635ff7689 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -45,9 +45,9 @@ struct sha1_ctx {
 };
 
 void sha1_init(struct sha1_ctx *);
-void sha1_update(struct sha1_ctx *, const void *, size_t);
+void sha1_update(struct sha1_ctx *, const void *, uint32_t size);
 void sha1_final(struct sha1_ctx *, uint8_t digest[SHA1_DIGEST_SIZE]);
-void sha1_bytes(const void *, size_t, uint8_t digest[SHA1_DIGEST_SIZE]);
+void sha1_bytes(const void *, uint32_t size, uint8_t digest[SHA1_DIGEST_SIZE]);
 
 #define SHA1_FMT \
         "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
diff --git a/lib/tc.c b/lib/tc.c
index 12af0192b6..1acca38218 100644
--- a/lib/tc.c
+++ b/lib/tc.c
@@ -60,12 +60,6 @@ VLOG_DEFINE_THIS_MODULE(tc);
 
 static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(60, 5);
 
-enum tc_offload_policy {
-    TC_POLICY_NONE,
-    TC_POLICY_SKIP_SW,
-    TC_POLICY_SKIP_HW
-};
-
 static enum tc_offload_policy tc_policy = TC_POLICY_NONE;
 
 struct tc_pedit_key_ex {
@@ -456,7 +450,7 @@ nl_parse_flower_mpls(struct nlattr **attrs, struct tc_flower *flower)
     if (attrs[TCA_FLOWER_KEY_MPLS_BOS]) {
         bos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_MPLS_BOS]);
         set_mpls_lse_bos(&flower->key.mpls_lse, bos);
-        set_mpls_lse_ttl(&flower->mask.mpls_lse, 0xff);
+        set_mpls_lse_bos(&flower->mask.mpls_lse, 0xff);
     }
 
     if (attrs[TCA_FLOWER_KEY_MPLS_TC]) {
@@ -934,6 +928,7 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower)
             int flower_off = m->flower_offset;
             int sz = m->size;
             int mf = m->offset;
+            int ef = ROUND_UP(mf, 4);
 
             if (m->htype != type) {
                continue;
@@ -941,9 +936,10 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower)
 
             /* check overlap between current pedit key, which is always
              * 4 bytes (range [off, off + 3]), and a map entry in
-             * flower_pedit_map (range [mf, mf + sz - 1]) */
+             * flower_pedit_map sf = ROUND_DOWN(mf, 4)
+             * (range [sf|mf, (mf + sz - 1)|ef]) */
             if ((keys->off >= mf && keys->off < mf + sz)
-                || (keys->off + 3 >= mf && keys->off + 3 < mf + sz)) {
+                || (keys->off + 3 >= mf && keys->off + 3 < ef)) {
                 int diff = flower_off + (keys->off - mf);
                 ovs_be32 *dst = (void *) (rewrite_key + diff);
                 ovs_be32 *dst_m = (void *) (rewrite_mask + diff);
@@ -1647,8 +1643,10 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower)
     }
 
     bs = nl_attr_get_unspec(stats_attrs[TCA_STATS_BASIC], sizeof *bs);
-    put_32aligned_u64(&stats->n_packets, bs->packets);
-    put_32aligned_u64(&stats->n_bytes, bs->bytes);
+    if (bs->packets) {
+        put_32aligned_u64(&stats->n_packets, bs->packets);
+        put_32aligned_u64(&stats->n_bytes, bs->bytes);
+    }
 
     return 0;
 }
@@ -2462,6 +2460,7 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower)
                 if (!released && flower->tunnel) {
                     act_offset = nl_msg_start_nested(request, act_index++);
                     nl_msg_put_act_tunnel_key_release(request);
+                    nl_msg_put_act_flags(request);
                     nl_msg_end_nested(request, act_offset);
                     released = true;
                 }
@@ -2645,6 +2644,7 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
     bool is_vlan = eth_type_vlan(flower->key.eth_type);
     bool is_qinq = is_vlan && eth_type_vlan(flower->key.encap_eth_type[0]);
     bool is_mpls = eth_type_mpls(flower->key.eth_type);
+    enum tc_offload_policy policy = flower->tc_policy;
     int err;
 
     /* need to parse acts first as some acts require changing the matching
@@ -2762,7 +2762,11 @@ nl_msg_put_flower_options(struct ofpbuf *request, struct tc_flower *flower)
         }
     }
 
-    nl_msg_put_u32(request, TCA_FLOWER_FLAGS, tc_get_tc_cls_policy(tc_policy));
+    if (policy == TC_POLICY_NONE) {
+        policy = tc_policy;
+    }
+
+    nl_msg_put_u32(request, TCA_FLOWER_FLAGS, tc_get_tc_cls_policy(policy));
 
     if (flower->tunnel) {
         nl_msg_put_flower_tunnel(request, flower);
diff --git a/lib/tc.h b/lib/tc.h
index d31c0953ed..0dc62bd83f 100644
--- a/lib/tc.h
+++ b/lib/tc.h
@@ -235,7 +235,7 @@ struct tc_action {
                     } ipv6;
                 };
 
-                union {
+                struct {
                     ovs_be16 min;
                     ovs_be16 max;
                 } port;
@@ -304,6 +304,14 @@ is_tcf_id_eq(struct tcf_id *id1, struct tcf_id *id2)
            && id1->chain == id2->chain;
 }
 
+enum tc_offload_policy {
+    TC_POLICY_NONE = 0,
+    TC_POLICY_SKIP_SW,
+    TC_POLICY_SKIP_HW
+};
+
+BUILD_ASSERT_DECL(TC_POLICY_NONE == 0);
+
 struct tc_flower {
     struct tc_flower_key key;
     struct tc_flower_key mask;
@@ -329,6 +337,8 @@ struct tc_flower {
     bool needs_full_ip_proto_mask;
 
     enum tc_offloaded_state offloaded_state;
+    /* Used to force skip_hw when probing tc features. */
+    enum tc_offload_policy tc_policy;
 };
 
 /* assert that if we overflow with a masked write of uint32_t to the last byte
diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c
index f8a0e19524..d177333297 100644
--- a/lib/tun-metadata.c
+++ b/lib/tun-metadata.c
@@ -811,7 +811,7 @@ tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
         } else {
             tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
         }
-    } else if (flow->metadata.present.len || is_mask) {
+    } else {
         nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
                           tun->metadata.opts.gnv,
                           flow->metadata.present.len);
diff --git a/lib/util.c b/lib/util.c
index 830e14516f..25635b27ff 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -1395,6 +1395,19 @@ is_all_ones(const void *p, size_t n)
     return is_all_byte(p, n, 0xff);
 }
 
+/* *dst |= *src for 'n' bytes. */
+void
+or_bytes(void *dst_, const void *src_, size_t n)
+{
+    const uint8_t *src = src_;
+    uint8_t *dst = dst_;
+    size_t i;
+
+    for (i = 0; i < n; i++) {
+        *dst++ |= *src++;
+    }
+}
+
 /* Copies 'n_bits' bits starting from bit 'src_ofs' in 'src' to the 'n_bits'
  * starting from bit 'dst_ofs' in 'dst'.  'src' is 'src_len' bytes long and
  * 'dst' is 'dst_len' bytes long.
diff --git a/lib/util.h b/lib/util.h
index 7ad8758fe6..067dcad157 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -484,6 +484,7 @@ be64_is_superset(ovs_be64 super, ovs_be64 sub)
 bool is_all_zeros(const void *, size_t);
 bool is_all_ones(const void *, size_t);
 bool is_all_byte(const void *, size_t, uint8_t byte);
+void or_bytes(void *dst, const void *src, size_t n);
 void bitwise_copy(const void *src, unsigned int src_len, unsigned int src_ofs,
                   void *dst, unsigned int dst_len, unsigned int dst_ofs,
                   unsigned int n_bits);
diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
index 51d656cba9..fd926cbb82 100644
--- a/ofproto/connmgr.c
+++ b/ofproto/connmgr.c
@@ -190,8 +190,8 @@ struct ofservice {
 
 static void ofservice_run(struct ofservice *);
 static void ofservice_wait(struct ofservice *);
-static void ofservice_reconfigure(struct ofservice *,
-                                  const struct ofproto_controller *)
+static int ofservice_reconfigure(struct ofservice *,
+                                 const struct ofproto_controller *)
     OVS_REQUIRES(ofproto_mutex);
 static void ofservice_create(struct connmgr *mgr, const char *target,
                              const struct ofproto_controller *)
@@ -602,7 +602,15 @@ connmgr_set_controllers(struct connmgr *mgr, struct shash *controllers)
                       target);
             ofservice_destroy(ofservice);
         } else {
-            ofservice_reconfigure(ofservice, c);
+            if (ofservice_reconfigure(ofservice, c)) {
+                char *target_to_restore = xstrdup(target);
+                VLOG_INFO("%s: Changes to controller \"%s\" "
+                          "expects re-initialization: Re-initializing now.",
+                          mgr->name, target);
+                ofservice_destroy(ofservice);
+                ofservice_create(mgr, target_to_restore, c);
+                free(target_to_restore);
+            }
         }
     }
 
@@ -2011,16 +2019,15 @@ ofservice_wait(struct ofservice *ofservice)
     }
 }
 
-static void
+static int
 ofservice_reconfigure(struct ofservice *ofservice,
                       const struct ofproto_controller *settings)
     OVS_REQUIRES(ofproto_mutex)
 {
-    /* If the allowed OpenFlow versions change, close all of the existing
-     * connections to allow them to reconnect and possibly negotiate a new
-     * version. */
+    /* If the allowed OpenFlow versions change, a full cleanup is needed
+     * for the ofservice and connections. */
     if (ofservice->s.allowed_versions != settings->allowed_versions) {
-        ofservice_close_all(ofservice);
+        return -EINVAL;
     }
 
     ofservice->s = *settings;
@@ -2029,6 +2036,8 @@ ofservice_reconfigure(struct ofservice *ofservice,
     LIST_FOR_EACH (ofconn, ofservice_node, &ofservice->conns) {
         ofconn_reconfigure(ofconn, settings);
     }
+
+    return 0;
 }
 
 /* Finds and returns the ofservice within 'mgr' that has the given
@@ -2131,7 +2140,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
                  const struct rule_actions *old_actions)
     OVS_REQUIRES(ofproto_mutex)
 {
-    if (rule_is_hidden(rule)) {
+    if (!mgr || rule_is_hidden(rule)) {
         return;
     }
 
@@ -2235,6 +2244,10 @@ ofmonitor_flush(struct connmgr *mgr)
 {
     struct ofconn *ofconn;
 
+    if (!mgr) {
+        return;
+    }
+
     LIST_FOR_EACH (ofconn, connmgr_node, &mgr->conns) {
         struct rconn_packet_counter *counter = ofconn->monitor_counter;
 
diff --git a/ofproto/ipfix-gen-entities b/ofproto/ipfix-gen-entities
index 0be719967d..dcecdab212 100755
--- a/ofproto/ipfix-gen-entities
+++ b/ofproto/ipfix-gen-entities
@@ -1,14 +1,12 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
 #
-# Copyright (C) 2012 Nicira, Inc.
+# Copyright (C) 2012, 2020 Nicira, Inc.
 #
 # Copying and distribution of this file, with or without modification,
 # are permitted in any medium without royalty provided the copyright
 # notice and this notice are preserved.  This file is offered as-is,
 # without warranty of any kind.
 
-from __future__ import print_function
-
 import getopt
 import re
 import sys
diff --git a/ofproto/ofproto-dpif-rid.h b/ofproto/ofproto-dpif-rid.h
index 147ef9c333..97699cb905 100644
--- a/ofproto/ofproto-dpif-rid.h
+++ b/ofproto/ofproto-dpif-rid.h
@@ -22,6 +22,7 @@
 
 #include "cmap.h"
 #include "ofproto-dpif-mirror.h"
+#include "ofproto/ofproto-provider.h"
 #include "openvswitch/list.h"
 #include "openvswitch/ofp-actions.h"
 #include "ovs-thread.h"
@@ -115,16 +116,25 @@ frozen_metadata_from_flow(struct frozen_metadata *md,
 {
     memset(md, 0, sizeof *md);
     md->tunnel = flow->tunnel;
+    /* It is unsafe for frozen_state to reference tun_table because
+     * tun_table is protected by RCU while the lifecycle of frozen_state
+     * can span several RCU quiesce states.
+     *
+     * The latest valid tun_table can be found by ofproto_get_tun_tab()
+     * efficiently. */
+    md->tunnel.metadata.tab = NULL;
     md->metadata = flow->metadata;
     memcpy(md->regs, flow->regs, sizeof md->regs);
     md->in_port = flow->in_port.ofp_port;
 }
 
 static inline void
-frozen_metadata_to_flow(const struct frozen_metadata *md,
+frozen_metadata_to_flow(struct ofproto *ofproto,
+                        const struct frozen_metadata *md,
                         struct flow *flow)
 {
     flow->tunnel = md->tunnel;
+    flow->tunnel.metadata.tab = ofproto_get_tun_tab(ofproto);
     flow->metadata = md->metadata;
     memcpy(flow->regs, md->regs, sizeof flow->regs);
     flow->in_port.ofp_port = md->in_port;
diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index f9ea47a2f1..6324e74d52 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -1291,10 +1291,10 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct dp_packet *packet,
     ovs_be16 vlan_tci;
 
     ovs_mutex_lock(&mutex);
-    sampler = ds->sflow_agent->samplers;
-    if (!sampler) {
+    if (!ds->sflow_agent || !ds->sflow_agent->samplers) {
         goto out;
     }
+    sampler = ds->sflow_agent->samplers;
 
     /* Build a flow sample. */
     memset(&fs, 0, sizeof fs);
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 409286ab15..cb197e9010 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -1093,7 +1093,7 @@ compose_slow_path(struct udpif *udpif, struct xlate_out *xout,
     }
 
     odp_put_userspace_action(pid, &cookie, sizeof cookie,
-                             ODPP_NONE, false, buf);
+                             ODPP_NONE, false, buf, NULL);
 
     if (meter_id != UINT32_MAX) {
         nl_msg_end_nested(buf, ac_offset);
@@ -1545,7 +1545,8 @@ process_upcall(struct udpif *udpif, struct upcall *upcall,
                 flow_clear_conntrack(&frozen_flow);
             }
 
-            frozen_metadata_to_flow(&state->metadata, &frozen_flow);
+            frozen_metadata_to_flow(&upcall->ofproto->up, &state->metadata,
+                                    &frozen_flow);
             flow_get_metadata(&frozen_flow, &am->pin.up.base.flow_metadata);
 
             ofproto_dpif_send_async_msg(upcall->ofproto, am);
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 4407f9c97a..72c0a0efce 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -1516,15 +1516,32 @@ xlate_lookup_ofproto_(const struct dpif_backer *backer,
             return NULL;
         }
 
-        /* If recirculation was initiated due to bond (in_port = OFPP_NONE)
-         * then frozen state is static and xport_uuid is not defined, so xport
-         * cannot be restored from frozen state. */
-        if (recirc_id_node->state.metadata.in_port != OFPP_NONE) {
+        ofp_port_t in_port = recirc_id_node->state.metadata.in_port;
+        if (in_port != OFPP_NONE && in_port != OFPP_CONTROLLER) {
             struct uuid xport_uuid = recirc_id_node->state.xport_uuid;
             xport = xport_lookup_by_uuid(xcfg, &xport_uuid);
             if (xport && xport->xbridge && xport->xbridge->ofproto) {
                 goto out;
             }
+        } else {
+            /* OFPP_NONE and OFPP_CONTROLLER are not real ports.  They indicate
+             * that the packet originated from the controller via an OpenFlow
+             * "packet-out".  The right thing to do is to find just the
+             * ofproto.  There is no xport, which is OK.
+             *
+             * OFPP_NONE can also indicate that a bond caused recirculation. */
+            struct uuid uuid = recirc_id_node->state.ofproto_uuid;
+            const struct xbridge *bridge = xbridge_lookup_by_uuid(xcfg, &uuid);
+            if (bridge && bridge->ofproto) {
+                if (errorp) {
+                    *errorp = NULL;
+                }
+                *xportp = NULL;
+                if (ofp_in_port) {
+                    *ofp_in_port = in_port;
+                }
+                return bridge->ofproto;
+            }
         }
     }
 
@@ -3076,6 +3093,7 @@ xlate_normal(struct xlate_ctx *ctx)
                 xlate_report(ctx, OFT_DETAIL, "MLD query, flooding");
                 xlate_normal_flood(ctx, in_xbundle, &xvlan);
             }
+            return;
         } else {
             if (is_ip_local_multicast(flow, wc)) {
                 /* RFC4541: section 2.1.2, item 2: Packets with a dst IP
@@ -3198,12 +3216,11 @@ compose_sample_action(struct xlate_ctx *ctx,
     odp_port_t odp_port = ofp_port_to_odp_port(
         ctx->xbridge, ctx->xin->flow.in_port.ofp_port);
     uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port);
-    size_t cookie_offset = odp_put_userspace_action(pid, cookie,
-                                                    sizeof *cookie,
-                                                    tunnel_out_port,
-                                                    include_actions,
-                                                    ctx->odp_actions);
-
+    size_t cookie_offset;
+    int res = odp_put_userspace_action(pid, cookie, sizeof *cookie,
+                                       tunnel_out_port, include_actions,
+                                       ctx->odp_actions, &cookie_offset);
+    ovs_assert(res == 0);
     if (is_sample) {
         nl_msg_end_nested(ctx->odp_actions, actions_offset);
         nl_msg_end_nested(ctx->odp_actions, sample_offset);
@@ -4796,7 +4813,7 @@ put_controller_user_action(struct xlate_ctx *ctx,
                                              ctx->xin->flow.in_port.ofp_port);
     uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port);
     odp_put_userspace_action(pid, &cookie, sizeof cookie, ODPP_NONE,
-                             false, ctx->odp_actions);
+                             false, ctx->odp_actions, NULL);
 }
 
 static void
@@ -6123,11 +6140,32 @@ static void
 compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
                          bool is_last_action)
 {
-    ovs_u128 old_ct_label_mask = ctx->wc->masks.ct_label;
-    uint32_t old_ct_mark_mask = ctx->wc->masks.ct_mark;
-    size_t ct_offset;
     uint16_t zone;
+    if (ofc->zone_src.field) {
+        union mf_subvalue value;
+        memset(&value, 0xff, sizeof(value));
+
+        zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow);
+        if (ctx->xin->frozen_state) {
+            /* If the upcall is a resume of a recirculation, we only need to
+             * unwildcard the fields that are not in the frozen_metadata, as
+             * when the rules update, OVS will generate a new recirc_id,
+             * which will invalidate the megaflow with old the recirc_id.
+             */
+            if (!mf_is_frozen_metadata(ofc->zone_src.field)) {
+                mf_write_subfield_flow(&ofc->zone_src, &value,
+                                       &ctx->wc->masks);
+            }
+        } else {
+            mf_write_subfield_flow(&ofc->zone_src, &value, &ctx->wc->masks);
+        }
+    } else {
+        zone = ofc->zone_imm;
+    }
 
+    size_t ct_offset;
+    ovs_u128 old_ct_label_mask = ctx->wc->masks.ct_label;
+    uint32_t old_ct_mark_mask = ctx->wc->masks.ct_mark;
     /* Ensure that any prior actions are applied before composing the new
      * conntrack action. */
     xlate_commit_actions(ctx);
@@ -6139,11 +6177,6 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
     do_xlate_actions(ofc->actions, ofpact_ct_get_action_len(ofc), ctx,
                      is_last_action, false);
 
-    if (ofc->zone_src.field) {
-        zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow);
-    } else {
-        zone = ofc->zone_imm;
-    }
 
     ct_offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_CT);
     if (ofc->flags & NX_CT_F_COMMIT) {
@@ -7519,7 +7552,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
 
         /* Restore pipeline metadata. May change flow's in_port and other
          * metadata to the values that existed when freezing was triggered. */
-        frozen_metadata_to_flow(&state->metadata, flow);
+        frozen_metadata_to_flow(&ctx.xbridge->ofproto->up,
+                                &state->metadata, flow);
 
         /* Restore stack, if any. */
         if (state->stack) {
@@ -7571,14 +7605,10 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
             ctx.error = XLATE_INVALID_TUNNEL_METADATA;
             goto exit;
         }
-    } else if (!flow->tunnel.metadata.tab || xin->frozen_state) {
+    } else if (!flow->tunnel.metadata.tab) {
         /* If the original flow did not come in on a tunnel, then it won't have
          * FLOW_TNL_F_UDPIF set. However, we still need to have a metadata
          * table in case we generate tunnel actions. */
-        /* If the translation is from a frozen state, we use the latest
-         * TLV map to avoid segmentation fault in case the old TLV map is
-         * replaced by a new one.
-         * XXX: It is better to abort translation if the table is changed. */
         flow->tunnel.metadata.tab = ofproto_get_tun_tab(
             &ctx.xbridge->ofproto->up);
     }
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d3cb392077..12a1d3ca7e 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1381,6 +1381,24 @@ check_ct_timeout_policy(struct dpif_backer *backer)
     return !error;
 }
 
+/* Tests whether 'backer''s datapath supports the all-zero SNAT case. */
+static bool
+dpif_supports_ct_zero_snat(struct dpif_backer *backer)
+{
+    enum ct_features features;
+    bool supported = false;
+
+    if (!ct_dpif_get_features(backer->dpif, &features)) {
+        if (features & CONNTRACK_F_ZERO_SNAT) {
+            supported = true;
+        }
+    }
+    VLOG_INFO("%s: Datapath %s ct_zero_snat",
+              dpif_name(backer->dpif), (supported) ? "supports"
+                                                   : "does not support");
+    return supported;
+}
+
 /* Tests whether 'backer''s datapath supports the
  * OVS_ACTION_ATTR_CHECK_PKT_LEN action. */
 static bool
@@ -1580,6 +1598,7 @@ check_support(struct dpif_backer *backer)
     backer->rt_support.ct_timeout = check_ct_timeout_policy(backer);
     backer->rt_support.explicit_drop_action =
         dpif_supports_explicit_drop_action(backer->dpif);
+    backer->rt_support.ct_zero_snat = dpif_supports_ct_zero_snat(backer);
 
     /* Flow fields. */
     backer->rt_support.odp.ct_state = check_ct_state(backer);
@@ -5375,6 +5394,8 @@ ct_add_timeout_policy_to_dpif(struct dpif *dpif,
     struct ct_dpif_timeout_policy cdtp;
     struct simap_node *node;
 
+    memset(&cdtp, 0, sizeof cdtp);
+
     cdtp.id = ct_tp->tp_id;
     SIMAP_FOR_EACH (node, &ct_tp->tp) {
         ct_dpif_set_timeout_policy_attr_by_name(&cdtp, node->name, node->data);
@@ -5563,6 +5584,7 @@ get_datapath_cap(const char *datapath_type, struct smap *cap)
     smap_add(cap, "ct_timeout", s.ct_timeout ? "true" : "false");
     smap_add(cap, "explicit_drop_action",
              s.explicit_drop_action ? "true" :"false");
+    smap_add(cap, "ct_zero_snat", s.ct_zero_snat ? "true" : "false");
 }
 
 /* Gets timeout policy name in 'backer' based on 'zone', 'dl_type' and
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index c9d5df34b0..4d1f126910 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -202,7 +202,10 @@ struct group_dpif *group_dpif_lookup(struct ofproto_dpif *,
     DPIF_SUPPORT_FIELD(bool, ct_timeout, "Conntrack timeout policy")        \
                                                                             \
     /* True if the datapath supports explicit drop action. */               \
-    DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop action")
+    DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop action")  \
+                                                                            \
+    /* True if the datapath supports all-zero IP SNAT. */                   \
+    DPIF_SUPPORT_FIELD(bool, ct_zero_snat, "Conntrack all-zero IP SNAT")
 
 
 /* Stores the various features which the corresponding backer supports. */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 08830d8371..4e9569e4ad 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -961,7 +961,7 @@ ofproto_get_datapath_cap(const char *datapath_type, struct smap *dp_cap)
     datapath_type = ofproto_normalize_type(datapath_type);
     const struct ofproto_class *class = ofproto_class_find__(datapath_type);
 
-    if (class->get_datapath_cap) {
+    if (class && class->get_datapath_cap) {
         class->get_datapath_cap(datapath_type, dp_cap);
     }
 }
@@ -974,7 +974,7 @@ ofproto_ct_set_zone_timeout_policy(const char *datapath_type, uint16_t zone_id,
     datapath_type = ofproto_normalize_type(datapath_type);
     const struct ofproto_class *class = ofproto_class_find__(datapath_type);
 
-    if (class->ct_set_zone_timeout_policy) {
+    if (class && class->ct_set_zone_timeout_policy) {
         class->ct_set_zone_timeout_policy(datapath_type, zone_id,
                                           timeout_policy);
     }
@@ -986,7 +986,7 @@ ofproto_ct_del_zone_timeout_policy(const char *datapath_type, uint16_t zone_id)
     datapath_type = ofproto_normalize_type(datapath_type);
     const struct ofproto_class *class = ofproto_class_find__(datapath_type);
 
-    if (class->ct_del_zone_timeout_policy) {
+    if (class && class->ct_del_zone_timeout_policy) {
         class->ct_del_zone_timeout_policy(datapath_type, zone_id);
     }
 
@@ -6077,8 +6077,8 @@ ofproto_rule_send_removed(struct rule *rule)
     fr.hard_timeout = rule->hard_timeout;
     ovs_mutex_unlock(&rule->mutex);
     rule->ofproto->ofproto_class->rule_get_stats(rule, &stats, &used);
-    fr.packet_count += stats.n_packets;
-    fr.byte_count += stats.n_bytes;
+    fr.packet_count = stats.n_packets;
+    fr.byte_count = stats.n_bytes;
     connmgr_send_flow_removed(connmgr, &fr);
     ovs_mutex_unlock(&ofproto_mutex);
 }
diff --git a/ovsdb/automake.mk b/ovsdb/automake.mk
index b895f42925..446d6c1362 100644
--- a/ovsdb/automake.mk
+++ b/ovsdb/automake.mk
@@ -106,11 +106,12 @@ CLEANFILES += $(OVSIDL_BUILT)
 # However, current versions of Automake seem to output all variable
 # assignments before any targets, so it doesn't seem to be a problem,
 # at least for now.
-$(OVSIDL_BUILT): ovsdb/ovsdb-idlc.in
+$(OVSIDL_BUILT): ovsdb/ovsdb-idlc.in python/ovs/dirs.py
 
 # ovsdb-doc
 EXTRA_DIST += ovsdb/ovsdb-doc
 OVSDB_DOC = $(run_python) $(srcdir)/ovsdb/ovsdb-doc
+ovsdb/ovsdb-doc: python/ovs/dirs.py
 
 # ovsdb-dot
 EXTRA_DIST += ovsdb/ovsdb-dot.in ovsdb/dot2pic
diff --git a/ovsdb/dot2pic b/ovsdb/dot2pic
index de67261ac6..2f858e19d5 100755
--- a/ovsdb/dot2pic
+++ b/ovsdb/dot2pic
@@ -1,6 +1,6 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
 
-# Copyright (c) 2009, 2010, 2011, 2013, 2017 Nicira, Inc.
+# Copyright (c) 2009, 2010, 2011, 2013, 2017, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/ovsdb/execution.c b/ovsdb/execution.c
index e45f3d6796..3a0dad5d0a 100644
--- a/ovsdb/execution.c
+++ b/ovsdb/execution.c
@@ -712,7 +712,7 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser,
     long long int timeout_msec = 0;
     size_t i;
 
-    timeout = ovsdb_parser_member(parser, "timeout", OP_NUMBER | OP_OPTIONAL);
+    timeout = ovsdb_parser_member(parser, "timeout", OP_INTEGER | OP_OPTIONAL);
     where = ovsdb_parser_member(parser, "where", OP_ARRAY);
     columns_json = ovsdb_parser_member(parser, "columns",
                                        OP_ARRAY | OP_OPTIONAL);
@@ -730,7 +730,7 @@ ovsdb_execute_wait(struct ovsdb_execution *x, struct ovsdb_parser *parser,
     }
     if (!error) {
         if (timeout) {
-            timeout_msec = MIN(LLONG_MAX, json_real(timeout));
+            timeout_msec = json_integer(timeout);
             if (timeout_msec < 0) {
                 error = ovsdb_syntax_error(timeout, NULL,
                                            "timeout must be nonnegative");
diff --git a/ovsdb/log.c b/ovsdb/log.c
index c82a79c9ff..f35faadfe0 100644
--- a/ovsdb/log.c
+++ b/ovsdb/log.c
@@ -212,7 +212,7 @@ ovsdb_log_open(const char *name, const char *magic,
     if (!strcmp(name, "/dev/stdin") && open_mode == OVSDB_LOG_READ_ONLY) {
         fd = dup(STDIN_FILENO);
     } else {
-        fd = open(name, flags, 0666);
+        fd = open(name, flags, 0660);
     }
     if (fd < 0) {
         const char *op = (open_mode == OVSDB_LOG_CREATE_EXCL ? "create"
diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
index 72756eb1f2..ba28e36d78 100644
--- a/ovsdb/ovsdb-client.c
+++ b/ovsdb/ovsdb-client.c
@@ -1664,14 +1664,15 @@ static void
 do_needs_conversion(struct jsonrpc *rpc, const char *database_ OVS_UNUSED,
                     int argc OVS_UNUSED, char *argv[])
 {
+    const char *schema_file_name = argv[argc - 1];
     struct ovsdb_schema *schema1;
-    check_ovsdb_error(ovsdb_schema_from_file(argv[0], &schema1));
+    check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema1));
 
     char *database = schema1->name;
     open_rpc(1, NEED_DATABASE, argc, argv, &rpc, &database);
 
     if (is_database_clustered(rpc, database)) {
-        ovsdb_schema_persist_ephemeral_columns(schema1, argv[0]);
+        ovsdb_schema_persist_ephemeral_columns(schema1, schema_file_name);
     }
 
     struct ovsdb_schema *schema2 = fetch_schema(rpc, schema1->name);
diff --git a/ovsdb/ovsdb-doc b/ovsdb/ovsdb-doc
index 406c293114..10d0c0c134 100755
--- a/ovsdb/ovsdb-doc
+++ b/ovsdb/ovsdb-doc
@@ -1,6 +1,6 @@
-#! /usr/bin/python
+#!/usr/bin/python3
 
-# Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+# Copyright (c) 2010, 2011, 2012, 2013, 2014, 2015, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/ovsdb/ovsdb-idlc.in b/ovsdb/ovsdb-idlc.in
index c285ee4b3c..9bec653421 100755
--- a/ovsdb/ovsdb-idlc.in
+++ b/ovsdb/ovsdb-idlc.in
@@ -1,6 +1,5 @@
 #! @PYTHON3@
 
-from __future__ import print_function
 import getopt
 import os
 import re
@@ -279,13 +278,21 @@ const struct %(s)s *%(s)s_table_track_get_first(const struct %(s)s_table *);
              (ROW) = %(s)s_track_get_next(ROW))
 
 
-/* Returns true if 'row' was inserted since the last change tracking reset. */
+/* Returns true if 'row' was inserted since the last change tracking reset.
+ *
+ * Note: This can only be used to test rows of tracked changes. This cannot be
+ * used to test if an uncommitted row that has been added locally is new or it
+ * may given unexpected results. */
 static inline bool %(s)s_is_new(const struct %(s)s *row)
 {
-    return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_MODIFY) == 0;
+    return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_INSERT) > 0;
 }
 
-/* Returns true if 'row' was deleted since the last change tracking reset. */
+/* Returns true if 'row' was deleted since the last change tracking reset.
+ *
+ * Note: This can only be used to test rows of tracked changes. This cannot be
+ * used to test if an uncommitted row that has been added locally has been
+ * deleted or it may given unexpected results. */
 static inline bool %(s)s_is_deleted(const struct %(s)s *row)
 {
     return %(s)s_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0;
@@ -333,6 +340,14 @@ struct %(s)s *%(s)s_cursor_data(struct ovsdb_idl_cursor *);
 void %(s)s_init(struct %(s)s *);
 void %(s)s_delete(const struct %(s)s *);
 struct %(s)s *%(s)s_insert(struct ovsdb_idl_txn *);
+
+/* Returns true if the tracked column referenced by 'enum %(s)s_column_id' of
+ * the row referenced by 'struct %(s)s *' was updated since the last change
+ * tracking reset.
+ *
+ * Note: This can only be used to test rows of tracked changes. This cannot be
+ * used to test if an uncommitted row that has been added locally has been
+ * updated or it may given unexpected results. */
 bool %(s)s_is_updated(const struct %(s)s *, enum %(s)s_column_id);
 ''' % {'s': structName, 'S': structName.upper()})
 
diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in
index 338f3bc299..b8bd1c2d57 100644
--- a/ovsdb/ovsdb-server.1.in
+++ b/ovsdb/ovsdb-server.1.in
@@ -206,6 +206,10 @@ but not before 100 commits have been added or 10 minutes have elapsed
 since the last compaction. It will also be compacted automatically
 after 24 hours since the last compaction if 100 commits were added
 regardless of its size.
+.IP "\fBovsdb\-server/memory-trim-on-compaction\fR \fIon\fR|\fIoff\fR"
+If this option is \fIon\fR, ovsdb-server will try to reclaim all unused
+heap memory back to the system after each successful database compaction
+to reduce the memory consumption of the process.  \fIoff\fR by default.
 .
 .IP "\fBovsdb\-server/reconnect\fR"
 Makes \fBovsdb\-server\fR drop all of the JSON\-RPC
@@ -372,6 +376,11 @@ This command must be executed on the leader.  It initiates the change to the
 cluster.  To see if the change takes effect (committed), use
 \fBcluster/status\fR to show the current setting.  Once a change is committed,
 it persists at server restarts.
+.IP "\fBcluster/set\-backlog\-threshold \fIdb\fR \fIn_msgs\fR \fIn_bytes\fR"
+Sets the backlog limits for \fIdb\fR's RAFT connections to a maximum of
+\fIn_msgs\fR messages or \fIn_bytes\fR bytes.  If the backlog on one of the
+connections reaches the limit, it will be disconnected (and re-established).
+Values are checked only if the backlog contains more than 50 messages.
 .
 .so lib/vlog-unixctl.man
 .so lib/memory-unixctl.man
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
index b6957d7300..2bc0a69066 100644
--- a/ovsdb/ovsdb-server.c
+++ b/ovsdb/ovsdb-server.c
@@ -76,8 +76,12 @@ static char *ssl_protocols;
 static char *ssl_ciphers;
 static bool bootstrap_ca_cert;
 
+/* Try to reclaim heap memory back to system after DB compaction. */
+static bool trim_memory = false;
+
 static unixctl_cb_func ovsdb_server_exit;
 static unixctl_cb_func ovsdb_server_compact;
+static unixctl_cb_func ovsdb_server_memory_trim_on_compaction;
 static unixctl_cb_func ovsdb_server_reconnect;
 static unixctl_cb_func ovsdb_server_perf_counters_clear;
 static unixctl_cb_func ovsdb_server_perf_counters_show;
@@ -242,7 +246,7 @@ main_loop(struct server_config *config,
                           xasprintf("removing database %s because storage "
                                     "disconnected permanently", node->name));
             } else if (ovsdb_storage_should_snapshot(db->db->storage)) {
-                log_and_free_error(ovsdb_snapshot(db->db));
+                log_and_free_error(ovsdb_snapshot(db->db, trim_memory));
             }
         }
         if (run_process) {
@@ -409,6 +413,9 @@ main(int argc, char *argv[])
     unixctl_command_register("exit", "", 0, 0, ovsdb_server_exit, &exiting);
     unixctl_command_register("ovsdb-server/compact", "", 0, 1,
                              ovsdb_server_compact, &all_dbs);
+    unixctl_command_register("ovsdb-server/memory-trim-on-compaction",
+                             "on|off", 1, 1,
+                             ovsdb_server_memory_trim_on_compaction, NULL);
     unixctl_command_register("ovsdb-server/reconnect", "", 0, 0,
                              ovsdb_server_reconnect, jsonrpc);
 
@@ -540,7 +547,7 @@ close_db(struct server_config *config, struct db *db, char *comment)
 
 static struct ovsdb_error * OVS_WARN_UNUSED_RESULT
 parse_txn(struct server_config *config, struct db *db,
-          struct ovsdb_schema *schema, const struct json *txn_json,
+          const struct ovsdb_schema *schema, const struct json *txn_json,
           const struct uuid *txnid)
 {
     if (schema) {
@@ -548,7 +555,9 @@ parse_txn(struct server_config *config, struct db *db,
          * (first grabbing its storage), then replace it with the new schema.
          * The transaction must also include the replacement data.
          *
-         * Only clustered database schema changes go through this path. */
+         * Only clustered database schema changes and snapshot installs
+         * go through this path.
+         */
         ovs_assert(txn_json);
         ovs_assert(ovsdb_storage_is_clustered(db->db->storage));
 
@@ -558,13 +567,17 @@ parse_txn(struct server_config *config, struct db *db,
             return error;
         }
 
-        ovsdb_jsonrpc_server_reconnect(
-            config->jsonrpc, false,
-            (db->db->schema
-             ? xasprintf("database %s schema changed", db->db->name)
-             : xasprintf("database %s connected to storage", db->db->name)));
+        if (!db->db->schema ||
+            strcmp(schema->version, db->db->schema->version)) {
+            ovsdb_jsonrpc_server_reconnect(
+                config->jsonrpc, false,
+                (db->db->schema
+                ? xasprintf("database %s schema changed", db->db->name)
+                : xasprintf("database %s connected to storage",
+                            db->db->name)));
+        }
 
-        ovsdb_replace(db->db, ovsdb_create(schema, NULL));
+        ovsdb_replace(db->db, ovsdb_create(ovsdb_schema_clone(schema), NULL));
 
         /* Force update to schema in _Server database. */
         db->row_uuid = UUID_ZERO;
@@ -613,6 +626,7 @@ read_db(struct server_config *config, struct db *db)
         } else {
             error = parse_txn(config, db, schema, txn_json, &txnid);
             json_destroy(txn_json);
+            ovsdb_schema_destroy(schema);
             if (error) {
                 break;
             }
@@ -637,8 +651,6 @@ add_db(struct server_config *config, struct db *db)
 static struct ovsdb_error * OVS_WARN_UNUSED_RESULT
 open_db(struct server_config *config, const char *filename)
 {
-    struct db *db;
-
     /* If we know that the file is already open, return a good error message.
      * Otherwise, if the file is open, we'll fail later on with a harder to
      * interpret file locking error. */
@@ -653,9 +665,6 @@ open_db(struct server_config *config, const char *filename)
         return error;
     }
 
-    db = xzalloc(sizeof *db);
-    db->filename = xstrdup(filename);
-
     struct ovsdb_schema *schema;
     if (ovsdb_storage_is_clustered(storage)) {
         schema = NULL;
@@ -668,6 +677,9 @@ open_db(struct server_config *config, const char *filename)
         }
         ovs_assert(schema && !txn_json);
     }
+
+    struct db *db = xzalloc(sizeof *db);
+    db->filename = xstrdup(filename);
     db->db = ovsdb_create(schema, storage);
     ovsdb_jsonrpc_server_add_db(config->jsonrpc, db->db);
 
@@ -1481,7 +1493,8 @@ ovsdb_server_compact(struct unixctl_conn *conn, int argc,
                 VLOG_INFO("compacting %s database by user request",
                           node->name);
 
-                struct ovsdb_error *error = ovsdb_snapshot(db->db);
+                struct ovsdb_error *error = ovsdb_snapshot(db->db,
+                                                           trim_memory);
                 if (error) {
                     char *s = ovsdb_error_to_string(error);
                     ds_put_format(&reply, "%s\n", s);
@@ -1504,6 +1517,35 @@ ovsdb_server_compact(struct unixctl_conn *conn, int argc,
     ds_destroy(&reply);
 }
 
+/* "ovsdb-server/memory-trim-on-compaction": controls whether ovsdb-server
+ * tries to reclaim heap memory back to system using malloc_trim() after
+ * compaction.  */
+static void
+ovsdb_server_memory_trim_on_compaction(struct unixctl_conn *conn,
+                                       int argc OVS_UNUSED,
+                                       const char *argv[],
+                                       void *arg OVS_UNUSED)
+{
+    const char *command = argv[1];
+
+#if !HAVE_DECL_MALLOC_TRIM
+    unixctl_command_reply_error(conn, "memory trimming is not supported");
+    return;
+#endif
+
+    if (!strcmp(command, "on")) {
+        trim_memory = true;
+    } else if (!strcmp(command, "off")) {
+        trim_memory = false;
+    } else {
+        unixctl_command_reply_error(conn, "invalid argument");
+        return;
+    }
+    VLOG_INFO("memory trimming after compaction %s.",
+              trim_memory ? "enabled" : "disabled");
+    unixctl_command_reply(conn, NULL);
+}
+
 /* "ovsdb-server/reconnect": makes ovsdb-server drop all of its JSON-RPC
  * connections and reconnect. */
 static void
diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c
index 91662cab84..938a99d914 100644
--- a/ovsdb/ovsdb-tool.c
+++ b/ovsdb/ovsdb-tool.c
@@ -720,6 +720,7 @@ print_db_changes(struct shash *tables, struct smap *names,
                                 ds_init(&s);
                                 ovsdb_datum_to_string(&datum, type, &s);
                                 value_string = ds_steal_cstr(&s);
+                                ovsdb_datum_destroy(&datum, type);
                             } else {
                                 ovsdb_error_destroy(error);
                             }
diff --git a/ovsdb/ovsdb.c b/ovsdb/ovsdb.c
index cfc96b32f8..e019631e9a 100644
--- a/ovsdb/ovsdb.c
+++ b/ovsdb/ovsdb.c
@@ -17,6 +17,10 @@
 
 #include "ovsdb.h"
 
+#if HAVE_DECL_MALLOC_TRIM
+#include <malloc.h>
+#endif
+
 #include "column.h"
 #include "file.h"
 #include "monitor.h"
@@ -27,6 +31,7 @@
 #include "simap.h"
 #include "storage.h"
 #include "table.h"
+#include "timeval.h"
 #include "transaction.h"
 #include "trigger.h"
 
@@ -414,7 +419,7 @@ ovsdb_create(struct ovsdb_schema *schema, struct ovsdb_storage *storage)
     db->storage = storage;
     ovs_list_init(&db->monitors);
     ovs_list_init(&db->triggers);
-    db->run_triggers = false;
+    db->run_triggers_now = db->run_triggers = false;
 
     shash_init(&db->tables);
     if (schema) {
@@ -502,6 +507,10 @@ ovsdb_get_memory_usage(const struct ovsdb *db, struct simap *usage)
     }
 
     simap_increase(usage, "cells", cells);
+
+    if (db->storage) {
+        ovsdb_storage_get_memory_usage(db->storage, usage);
+    }
 }
 
 struct ovsdb_table *
@@ -511,18 +520,31 @@ ovsdb_get_table(const struct ovsdb *db, const char *name)
 }
 
 struct ovsdb_error * OVS_WARN_UNUSED_RESULT
-ovsdb_snapshot(struct ovsdb *db)
+ovsdb_snapshot(struct ovsdb *db, bool trim_memory OVS_UNUSED)
 {
     if (!db->storage) {
         return NULL;
     }
 
+    uint64_t elapsed, start_time = time_msec();
     struct json *schema = ovsdb_schema_to_json(db->schema);
     struct json *data = ovsdb_to_txn_json(db, "compacting database online");
     struct ovsdb_error *error = ovsdb_storage_store_snapshot(db->storage,
                                                              schema, data);
     json_destroy(schema);
     json_destroy(data);
+
+#if HAVE_DECL_MALLOC_TRIM
+    if (!error && trim_memory) {
+        malloc_trim(0);
+    }
+#endif
+
+    elapsed = time_msec() - start_time;
+    if (elapsed > 1000) {
+        VLOG_INFO("%s: Database compaction took %"PRIu64"ms",
+                  db->name, elapsed);
+    }
     return error;
 }
 
diff --git a/ovsdb/ovsdb.h b/ovsdb/ovsdb.h
index 32e5333163..72e127c847 100644
--- a/ovsdb/ovsdb.h
+++ b/ovsdb/ovsdb.h
@@ -83,6 +83,7 @@ struct ovsdb {
     /* Triggers. */
     struct ovs_list triggers;   /* Contains "struct ovsdb_trigger"s. */
     bool run_triggers;
+    bool run_triggers_now;
 
     struct ovsdb_table *rbac_role;
 
@@ -111,7 +112,8 @@ struct json *ovsdb_execute(struct ovsdb *, const struct ovsdb_session *,
                            long long int elapsed_msec,
                            long long int *timeout_msec);
 
-struct ovsdb_error *ovsdb_snapshot(struct ovsdb *) OVS_WARN_UNUSED_RESULT;
+struct ovsdb_error *ovsdb_snapshot(struct ovsdb *, bool trim_memory)
+    OVS_WARN_UNUSED_RESULT;
 
 void ovsdb_replace(struct ovsdb *dst, struct ovsdb *src);
 
diff --git a/ovsdb/raft-private.h b/ovsdb/raft-private.h
index ac8656d42f..76b097b891 100644
--- a/ovsdb/raft-private.h
+++ b/ovsdb/raft-private.h
@@ -27,6 +27,7 @@
 
 struct ds;
 struct ovsdb_parser;
+struct raft_install_snapshot_request;
 
 /* Formatting server IDs and cluster IDs for use in human-readable logs.  Do
  * not use these in cases where the whole server or cluster ID is needed; use
@@ -83,6 +84,9 @@ struct raft_server {
     bool replied;            /* Reply to append_request was received from this
                                 node during current election_timeout interval.
                                 */
+    /* install_snapshot_request has been sent, but there is no response yet. */
+    bool install_snapshot_request_in_progress;
+
     /* For use in adding and removing servers: */
     struct uuid requester_sid;  /* Nonzero if requested via RPC. */
     struct unixctl_conn *requester_conn; /* Only if requested via unixctl. */
diff --git a/ovsdb/raft-rpc.c b/ovsdb/raft-rpc.c
index 18c83fe9c2..dd14d81091 100644
--- a/ovsdb/raft-rpc.c
+++ b/ovsdb/raft-rpc.c
@@ -544,8 +544,8 @@ raft_format_install_snapshot_request(
     ds_put_format(s, " last_index=%"PRIu64, rq->last_index);
     ds_put_format(s, " last_term=%"PRIu64, rq->last_term);
     ds_put_format(s, " last_eid="UUID_FMT, UUID_ARGS(&rq->last_eid));
-    ds_put_cstr(s, " last_servers=");
     ds_put_format(s, " election_timer=%"PRIu64, rq->election_timer);
+    ds_put_cstr(s, " last_servers=");
 
     struct hmap servers;
     struct ovsdb_error *error =
diff --git a/ovsdb/raft.c b/ovsdb/raft.c
index 4789bc4f22..ec4c244762 100644
--- a/ovsdb/raft.c
+++ b/ovsdb/raft.c
@@ -36,6 +36,7 @@
 #include "ovsdb/log.h"
 #include "raft-rpc.h"
 #include "random.h"
+#include "simap.h"
 #include "socket-util.h"
 #include "stream.h"
 #include "timeval.h"
@@ -73,7 +74,8 @@ enum raft_failure_test {
     FT_CRASH_BEFORE_SEND_EXEC_REQ,
     FT_CRASH_AFTER_SEND_EXEC_REQ,
     FT_CRASH_AFTER_RECV_APPEND_REQ_UPDATE,
-    FT_DELAY_ELECTION
+    FT_DELAY_ELECTION,
+    FT_DONT_SEND_VOTE_REQUEST
 };
 static enum raft_failure_test failure_test;
 
@@ -298,6 +300,17 @@ struct raft {
     bool had_leader;            /* There has been leader elected since last
                                    election initiated. This is to help setting
                                    candidate_retrying. */
+
+    /* For all. */
+    bool ever_had_leader;       /* There has been leader elected since the raft
+                                   is initialized, meaning it is ever
+                                   connected. */
+
+    /* Connection backlog limits. */
+#define DEFAULT_MAX_BACKLOG_N_MSGS    500
+#define DEFAULT_MAX_BACKLOG_N_BYTES   UINT32_MAX
+    size_t conn_backlog_max_n_msgs;   /* Number of messages. */
+    size_t conn_backlog_max_n_bytes;  /* Number of bytes. */
 };
 
 /* All Raft structures. */
@@ -405,6 +418,9 @@ raft_alloc(void)
 
     raft->election_timer = ELECTION_BASE_MSEC;
 
+    raft->conn_backlog_max_n_msgs = DEFAULT_MAX_BACKLOG_N_MSGS;
+    raft->conn_backlog_max_n_bytes = DEFAULT_MAX_BACKLOG_N_BYTES;
+
     return raft;
 }
 
@@ -918,6 +934,34 @@ raft_reset_ping_timer(struct raft *raft)
     raft->ping_timeout = time_msec() + raft->election_timer / 3;
 }
 
+static void
+raft_conn_update_probe_interval(struct raft *raft, struct raft_conn *r_conn)
+{
+    /* Inactivity probe will be sent if connection will remain idle for the
+     * time of an election timeout.  Connection will be dropped if inactivity
+     * will last twice that time.
+     *
+     * It's not enough to just have heartbeats if connection is still
+     * established, but no packets received from the other side.  Without
+     * inactivity probe follower will just try to initiate election
+     * indefinitely staying in 'candidate' role.  And the leader will continue
+     * to send heartbeats to the dead connection thinking that remote server
+     * is still part of the cluster. */
+    int probe_interval = raft->election_timer + ELECTION_RANGE_MSEC;
+
+    jsonrpc_session_set_probe_interval(r_conn->js, probe_interval);
+}
+
+static void
+raft_update_probe_intervals(struct raft *raft)
+{
+    struct raft_conn *r_conn;
+
+    LIST_FOR_EACH (r_conn, list_node, &raft->conns) {
+        raft_conn_update_probe_interval(raft, r_conn);
+    }
+}
+
 static void
 raft_add_conn(struct raft *raft, struct jsonrpc_session *js,
               const struct uuid *sid, bool incoming)
@@ -932,6 +976,9 @@ raft_add_conn(struct raft *raft, struct jsonrpc_session *js,
                                               &conn->sid);
     conn->incoming = incoming;
     conn->js_seqno = jsonrpc_session_get_seqno(conn->js);
+    raft_conn_update_probe_interval(raft, conn);
+    jsonrpc_session_set_backlog_threshold(js, raft->conn_backlog_max_n_msgs,
+                                              raft->conn_backlog_max_n_bytes);
 }
 
 /* Starts the local server in an existing Raft cluster, using the local copy of
@@ -1007,6 +1054,23 @@ raft_get_sid(const struct raft *raft)
     return &raft->sid;
 }
 
+/* Adds memory consumption info to 'usage' for later use by memory_report(). */
+void
+raft_get_memory_usage(const struct raft *raft, struct simap *usage)
+{
+    struct raft_conn *conn;
+    uint64_t backlog = 0;
+    int cnt = 0;
+
+    LIST_FOR_EACH (conn, list_node, &raft->conns) {
+        backlog += jsonrpc_session_get_backlog(conn->js);
+        cnt++;
+    }
+    simap_increase(usage, "raft-backlog-kB", backlog / 1000);
+    simap_increase(usage, "raft-connections", cnt);
+    simap_increase(usage, "raft-log", raft->log_end - raft->log_start);
+}
+
 /* Returns true if 'raft' has completed joining its cluster, has not left or
  * initiated leaving the cluster, does not have failed disk storage, and is
  * apparently connected to the leader in a healthy way (or is itself the
@@ -1020,12 +1084,22 @@ raft_get_sid(const struct raft *raft)
 bool
 raft_is_connected(const struct raft *raft)
 {
+    static bool last_state = false;
     bool ret = (!raft->candidate_retrying
             && !raft->joining
             && !raft->leaving
             && !raft->left
-            && !raft->failed);
-    VLOG_DBG("raft_is_connected: %s\n", ret? "true": "false");
+            && !raft->failed
+            && raft->ever_had_leader);
+
+    if (!ret) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
+        VLOG_DBG_RL(&rl, "raft_is_connected: false");
+    } else if (!last_state) {
+        VLOG_DBG("raft_is_connected: true");
+    }
+    last_state = ret;
+
     return ret;
 }
 
@@ -1397,8 +1471,19 @@ raft_conn_run(struct raft *raft, struct raft_conn *conn)
     jsonrpc_session_run(conn->js);
 
     unsigned int new_seqno = jsonrpc_session_get_seqno(conn->js);
-    bool just_connected = (new_seqno != conn->js_seqno
+    bool reconnected = new_seqno != conn->js_seqno;
+    bool just_connected = (reconnected
                            && jsonrpc_session_is_connected(conn->js));
+
+    if (reconnected) {
+        /* Clear 'install_snapshot_request_in_progress' since it might not
+         * reach the destination or server was restarted. */
+        struct raft_server *server = raft_find_server(raft, &conn->sid);
+        if (server) {
+            server->install_snapshot_request_in_progress = false;
+        }
+    }
+
     conn->js_seqno = new_seqno;
     if (just_connected) {
         if (raft->joining) {
@@ -1641,6 +1726,7 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
     }
 
     ovs_assert(raft->role != RAFT_LEADER);
+
     raft->role = RAFT_CANDIDATE;
     /* If there was no leader elected since last election, we know we are
      * retrying now. */
@@ -1684,7 +1770,9 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
                 .leadership_transfer = leadership_transfer,
             },
         };
-        raft_send(raft, &rq);
+        if (failure_test != FT_DONT_SEND_VOTE_REQUEST) {
+            raft_send(raft, &rq);
+        }
     }
 
     /* Vote for ourselves. */
@@ -2513,13 +2601,14 @@ raft_server_init_leader(struct raft *raft, struct raft_server *s)
     s->match_index = 0;
     s->phase = RAFT_PHASE_STABLE;
     s->replied = false;
+    s->install_snapshot_request_in_progress = false;
 }
 
 static void
 raft_set_leader(struct raft *raft, const struct uuid *sid)
 {
     raft->leader_sid = *sid;
-    raft->had_leader = true;
+    raft->ever_had_leader = raft->had_leader = true;
     raft->candidate_retrying = false;
 }
 
@@ -2731,6 +2820,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index)
                           raft->election_timer, e->election_timer);
                 raft->election_timer = e->election_timer;
                 raft->election_timer_new = 0;
+                raft_update_probe_intervals(raft);
             }
             if (e->servers) {
                 /* raft_run_reconfigure() can write a new Raft entry, which can
@@ -2747,6 +2837,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index)
                 VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64,
                           raft->election_timer, e->election_timer);
                 raft->election_timer = e->election_timer;
+                raft_update_probe_intervals(raft);
             }
         }
         /* Check if any pending command can be completed, and complete it.
@@ -2960,6 +3051,15 @@ raft_update_leader(struct raft *raft, const struct uuid *sid)
         };
         ignore(ovsdb_log_write_and_free(raft->log, raft_record_to_json(&r)));
     }
+    if (raft->role == RAFT_CANDIDATE) {
+        /* Section 3.4: While waiting for votes, a candidate may
+         * receive an AppendEntries RPC from another server claiming to
+         * be leader. If the leader’s term (included in its RPC) is at
+         * least as large as the candidate’s current term, then the
+         * candidate recognizes the leader as legitimate and returns to
+         * follower state. */
+        raft->role = RAFT_FOLLOWER;
+    }
     return true;
 }
 
@@ -3260,7 +3360,20 @@ raft_send_install_snapshot_request(struct raft *raft,
             .election_timer = raft->election_timer, /* use latest value */
         }
     };
-    raft_send(raft, &rpc);
+
+    if (s->install_snapshot_request_in_progress) {
+        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
+
+        VLOG_INFO_RL(&rl, "not sending snapshot to server %s, "
+                          "already in progress", s->nickname);
+        return;
+    }
+
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
+    VLOG_INFO_RL(&rl, "sending snapshot to server %s, %"PRIu64":%"PRIu64".",
+                      s->nickname, raft->term, raft->log_start - 1);
+    CONST_CAST(struct raft_server *, s)->install_snapshot_request_in_progress
+        = raft_send(raft, &rpc);
 }
 
 static void
@@ -3913,7 +4026,7 @@ raft_handle_install_snapshot_request__(
     struct ovsdb_error *error = raft_save_snapshot(raft, new_log_start,
                                                    &new_snapshot);
     if (error) {
-        char *error_s = ovsdb_error_to_string(error);
+        char *error_s = ovsdb_error_to_string_free(error);
         VLOG_WARN("could not save snapshot: %s", error_s);
         free(error_s);
         return false;
@@ -3977,6 +4090,8 @@ raft_handle_install_snapshot_reply(
         }
     }
 
+    s->install_snapshot_request_in_progress = false;
+
     if (rpy->last_index != raft->log_start - 1 ||
         rpy->last_term != raft->snap.term) {
         static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
@@ -3992,8 +4107,9 @@ raft_handle_install_snapshot_reply(
     VLOG_INFO_RL(&rl, "cluster "CID_FMT": installed snapshot on server %s "
                  " up to %"PRIu64":%"PRIu64, CID_ARGS(&raft->cid),
                  s->nickname, rpy->last_term, rpy->last_index);
-    s->next_index = raft->log_end;
-    raft_send_append_request(raft, s, 0, "snapshot installed");
+    s->next_index = raft->log_start;
+    raft_send_append_request(raft, s, raft->log_end - s->next_index,
+                             "snapshot installed");
 }
 
 /* Returns true if 'raft' has grown enough since the last snapshot that
@@ -4023,9 +4139,24 @@ raft_may_snapshot(const struct raft *raft)
             && !raft->leaving
             && !raft->left
             && !raft->failed
+            && raft->role != RAFT_LEADER
             && raft->last_applied >= raft->log_start);
 }
 
+/* Prepares for soon snapshotting. */
+void
+raft_notify_snapshot_recommended(struct raft *raft)
+{
+    if (raft->role == RAFT_LEADER) {
+        /* Leader is about to write database snapshot to the disk and this
+         * might take significant amount of time.  Stepping back from the
+         * leadership to keep the cluster functional during this process.  */
+        VLOG_INFO("Transferring leadership to write a snapshot.");
+        raft_transfer_leadership(raft, "preparing to write snapshot");
+        raft_become_follower(raft);
+    }
+}
+
 /* Replaces the log for 'raft', up to the last log entry read, by
  * 'new_snapshot_data'.  Returns NULL if successful, otherwise an error that
  * the caller must eventually free.
@@ -4143,9 +4274,7 @@ raft_handle_execute_command_request__(
     cmd->sid = rq->common.sid;
 
     enum raft_command_status status = cmd->status;
-    if (status != RAFT_CMD_INCOMPLETE) {
-        raft_command_unref(cmd);
-    }
+    raft_command_unref(cmd);
     return status;
 }
 
@@ -4366,6 +4495,8 @@ raft_unixctl_status(struct unixctl_conn *conn,
                   : raft->leaving ? "leaving cluster"
                   : raft->left ? "left cluster"
                   : raft->failed ? "failed"
+                  : raft->candidate_retrying
+                      ? "disconnected from the cluster (election timeout)"
                   : "cluster member");
     if (raft->joining) {
         ds_put_format(&s, "Remotes for joining:");
@@ -4639,6 +4770,42 @@ raft_unixctl_change_election_timer(struct unixctl_conn *conn,
     unixctl_command_reply(conn, "change of election timer initiated.");
 }
 
+static void
+raft_unixctl_set_backlog_threshold(struct unixctl_conn *conn,
+                                   int argc OVS_UNUSED, const char *argv[],
+                                   void *aux OVS_UNUSED)
+{
+    const char *cluster_name = argv[1];
+    unsigned long long n_msgs, n_bytes;
+    struct raft_conn *r_conn;
+
+    struct raft *raft = raft_lookup_by_name(cluster_name);
+    if (!raft) {
+        unixctl_command_reply_error(conn, "unknown cluster");
+        return;
+    }
+
+    if (!str_to_ullong(argv[2], 10, &n_msgs)
+        || !str_to_ullong(argv[3], 10, &n_bytes)) {
+        unixctl_command_reply_error(conn, "invalid argument");
+        return;
+    }
+
+    if (n_msgs < 50 || n_msgs > SIZE_MAX || n_bytes > SIZE_MAX) {
+        unixctl_command_reply_error(conn, "values out of range");
+        return;
+    }
+
+    raft->conn_backlog_max_n_msgs = n_msgs;
+    raft->conn_backlog_max_n_bytes = n_bytes;
+
+    LIST_FOR_EACH (r_conn, list_node, &raft->conns) {
+        jsonrpc_session_set_backlog_threshold(r_conn->js, n_msgs, n_bytes);
+    }
+
+    unixctl_command_reply(conn, NULL);
+}
+
 static void
 raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED,
                           int argc OVS_UNUSED, const char *argv[],
@@ -4667,6 +4834,8 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED,
                 raft_reset_election_timer(raft);
             }
         }
+    } else if (!strcmp(test, "dont-send-vote-request")) {
+        failure_test = FT_DONT_SEND_VOTE_REQUEST;
     } else if (!strcmp(test, "clear")) {
         failure_test = FT_NO_TEST;
         unixctl_command_reply(conn, "test dismissed");
@@ -4697,6 +4866,9 @@ raft_init(void)
                              raft_unixctl_kick, NULL);
     unixctl_command_register("cluster/change-election-timer", "DB TIME", 2, 2,
                              raft_unixctl_change_election_timer, NULL);
+    unixctl_command_register("cluster/set-backlog-threshold",
+                             "DB N_MSGS N_BYTES", 3, 3,
+                             raft_unixctl_set_backlog_threshold, NULL);
     unixctl_command_register("cluster/failure-test", "FAILURE SCENARIO", 1, 1,
                              raft_unixctl_failure_test, NULL);
     ovsthread_once_done(&once);
diff --git a/ovsdb/raft.h b/ovsdb/raft.h
index 3d448995af..59902fe825 100644
--- a/ovsdb/raft.h
+++ b/ovsdb/raft.h
@@ -67,6 +67,7 @@
 struct json;
 struct ovsdb_log;
 struct raft;
+struct simap;
 struct sset;
 
 #define RAFT_MAGIC "CLUSTER"
@@ -113,6 +114,7 @@ const struct uuid *raft_get_cid(const struct raft *);
 const struct uuid *raft_get_sid(const struct raft *);
 bool raft_is_connected(const struct raft *);
 bool raft_is_leader(const struct raft *);
+void raft_get_memory_usage(const struct raft *, struct simap *usage);
 
 /* Joining a cluster. */
 bool raft_is_joining(const struct raft *);
@@ -172,6 +174,7 @@ void raft_command_wait(const struct raft_command *);
 bool raft_grew_lots(const struct raft *);
 uint64_t raft_get_log_length(const struct raft *);
 bool raft_may_snapshot(const struct raft *);
+void raft_notify_snapshot_recommended(struct raft *);
 struct ovsdb_error *raft_store_snapshot(struct raft *,
                                         const struct json *new_snapshot)
     OVS_WARN_UNUSED_RESULT;
diff --git a/ovsdb/storage.c b/ovsdb/storage.c
index e26252b066..bd1fe0a33a 100644
--- a/ovsdb/storage.c
+++ b/ovsdb/storage.c
@@ -26,6 +26,7 @@
 #include "ovsdb.h"
 #include "raft.h"
 #include "random.h"
+#include "simap.h"
 #include "timeval.h"
 #include "util.h"
 
@@ -188,6 +189,15 @@ ovsdb_storage_get_applied_index(const struct ovsdb_storage *storage)
     return storage->raft ? raft_get_applied_index(storage->raft) : 0;
 }
 
+void
+ovsdb_storage_get_memory_usage(const struct ovsdb_storage *storage,
+                               struct simap *usage)
+{
+    if (storage->raft) {
+        raft_get_memory_usage(storage->raft, usage);
+    }
+}
+
 void
 ovsdb_storage_run(struct ovsdb_storage *storage)
 {
@@ -499,14 +509,11 @@ ovsdb_storage_should_snapshot(const struct ovsdb_storage *storage)
             return false;
         }
 
-        /* If we can't snapshot right now, don't. */
-        if (storage->raft && !raft_may_snapshot(storage->raft)) {
-            return false;
-        }
-
         uint64_t log_len = (storage->raft
                             ? raft_get_log_length(storage->raft)
                             : storage->n_read + storage->n_written);
+        bool snapshot_recommended = false;
+
         if (now < storage->next_snapshot_max) {
             /* Maximum snapshot time not yet reached.  Take a snapshot if there
              * have been at least 100 log entries and the log file size has
@@ -514,12 +521,25 @@ ovsdb_storage_should_snapshot(const struct ovsdb_storage *storage)
             bool grew_lots = (storage->raft
                               ? raft_grew_lots(storage->raft)
                               : ovsdb_log_grew_lots(storage->log));
-            return log_len >= 100 && grew_lots;
+            snapshot_recommended = (log_len >= 100 && grew_lots);
         } else {
             /* We have reached the maximum snapshot time.  Take a snapshot if
              * there have been any log entries at all. */
-            return log_len > 0;
+            snapshot_recommended = (log_len > 0);
+        }
+
+        if (!snapshot_recommended) {
+            return false;
+        }
+
+        /* If we can't snapshot right now, don't. */
+        if (storage->raft && !raft_may_snapshot(storage->raft)) {
+            /* Notifying the storage that it needs to make a snapshot soon. */
+            raft_notify_snapshot_recommended(storage->raft);
+            return false;
         }
+
+        return true;
     }
 
     return false;
diff --git a/ovsdb/storage.h b/ovsdb/storage.h
index 8a9bbab709..a223968912 100644
--- a/ovsdb/storage.h
+++ b/ovsdb/storage.h
@@ -23,6 +23,7 @@
 struct json;
 struct ovsdb_schema;
 struct ovsdb_storage;
+struct simap;
 struct uuid;
 
 struct ovsdb_error *ovsdb_storage_open(const char *filename, bool rw,
@@ -39,6 +40,8 @@ bool ovsdb_storage_is_leader(const struct ovsdb_storage *);
 const struct uuid *ovsdb_storage_get_cid(const struct ovsdb_storage *);
 const struct uuid *ovsdb_storage_get_sid(const struct ovsdb_storage *);
 uint64_t ovsdb_storage_get_applied_index(const struct ovsdb_storage *);
+void ovsdb_storage_get_memory_usage(const struct ovsdb_storage *,
+                                    struct simap *usage);
 
 void ovsdb_storage_run(struct ovsdb_storage *);
 void ovsdb_storage_wait(struct ovsdb_storage *);
diff --git a/ovsdb/transaction.c b/ovsdb/transaction.c
index 369436bffb..8ffefcf7c9 100644
--- a/ovsdb/transaction.c
+++ b/ovsdb/transaction.c
@@ -967,7 +967,7 @@ ovsdb_txn_complete(struct ovsdb_txn *txn)
 {
     if (!ovsdb_txn_is_empty(txn)) {
 
-        txn->db->run_triggers = true;
+        txn->db->run_triggers_now = txn->db->run_triggers = true;
         ovsdb_monitors_commit(txn->db, txn);
         ovsdb_error_assert(for_each_txn_row(txn, ovsdb_txn_update_weak_refs));
         ovsdb_error_assert(for_each_txn_row(txn, ovsdb_txn_row_commit));
diff --git a/ovsdb/trigger.c b/ovsdb/trigger.c
index 7e62e90ae3..0372302af4 100644
--- a/ovsdb/trigger.c
+++ b/ovsdb/trigger.c
@@ -141,7 +141,7 @@ ovsdb_trigger_run(struct ovsdb *db, long long int now)
     struct ovsdb_trigger *t, *next;
 
     bool run_triggers = db->run_triggers;
-    db->run_triggers = false;
+    db->run_triggers_now = db->run_triggers = false;
 
     bool disconnect_all = false;
 
@@ -160,7 +160,7 @@ ovsdb_trigger_run(struct ovsdb *db, long long int now)
 void
 ovsdb_trigger_wait(struct ovsdb *db, long long int now)
 {
-    if (db->run_triggers) {
+    if (db->run_triggers_now) {
         poll_immediate_wake();
     } else {
         long long int deadline = LLONG_MAX;
@@ -319,9 +319,16 @@ ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now)
             if (!strcmp(ovsdb_error_get_tag(error), "cluster error")) {
                 /* Temporary error.  Transition back to "initialized" state to
                  * try again. */
+                char *err_s = ovsdb_error_to_string(error);
+                VLOG_DBG("cluster error %s", err_s);
+
                 jsonrpc_msg_destroy(t->reply);
                 t->reply = NULL;
                 t->db->run_triggers = true;
+                if (!strstr(err_s, "not leader")) {
+                    t->db->run_triggers_now = true;
+                }
+                free(err_s);
                 ovsdb_error_destroy(error);
             } else {
                 /* Permanent error.  Transition to "completed" state to report
diff --git a/python/automake.mk b/python/automake.mk
index 2f08c77014..767512f175 100644
--- a/python/automake.mk
+++ b/python/automake.mk
@@ -74,12 +74,12 @@ ovs-install-data-local:
 	$(MKDIR_P) python/ovs
 	sed \
 		-e '/^##/d' \
-                -e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \
-                -e 's,[@]RUNDIR[@],$(RUNDIR),g' \
-                -e 's,[@]LOGDIR[@],$(LOGDIR),g' \
-                -e 's,[@]bindir[@],$(bindir),g' \
-                -e 's,[@]sysconfdir[@],$(sysconfdir),g' \
-                -e 's,[@]DBDIR[@],$(DBDIR),g' \
+		-e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \
+		-e 's,[@]RUNDIR[@],$(RUNDIR),g' \
+		-e 's,[@]LOGDIR[@],$(LOGDIR),g' \
+		-e 's,[@]bindir[@],$(bindir),g' \
+		-e 's,[@]sysconfdir[@],$(sysconfdir),g' \
+		-e 's,[@]DBDIR[@],$(DBDIR),g' \
 		< $(srcdir)/python/ovs/dirs.py.template \
 		> python/ovs/dirs.py.tmp
 	$(MKDIR_P) $(DESTDIR)$(pkgdatadir)/python/ovs
@@ -107,12 +107,13 @@ ALL_LOCAL += $(srcdir)/python/ovs/dirs.py
 $(srcdir)/python/ovs/dirs.py: python/ovs/dirs.py.template
 	$(AM_V_GEN)sed \
 		-e '/^##/d' \
-                -e 's,[@]pkgdatadir[@],/usr/local/share/openvswitch,g' \
-                -e 's,[@]RUNDIR[@],/var/run,g' \
-                -e 's,[@]LOGDIR[@],/usr/local/var/log,g' \
-                -e 's,[@]bindir[@],/usr/local/bin,g' \
-                -e 's,[@]sysconfdir[@],/usr/local/etc,g' \
-                -e 's,[@]DBDIR[@],/usr/local/etc/openvswitch,g' \
+		-e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \
+		-e 's,[@]RUNDIR[@],$(RUNDIR),g' \
+		-e 's,[@]LOGDIR[@],$(LOGDIR),g' \
+		-e 's,[@]bindir[@],$(bindir),g' \
+		-e 's,[@]sysconfdir[@],$(sysconfdir),g' \
+		-e 's,[@]DBDIR[@],$(sysconfdir)/openvswitch,g' \
 		< $? > $@.tmp && \
 	mv $@.tmp $@
 EXTRA_DIST += python/ovs/dirs.py.template
+CLEANFILES += python/ovs/dirs.py
diff --git a/python/build/soutil.py b/python/build/soutil.py
index b8027af863..a658823028 100755
--- a/python/build/soutil.py
+++ b/python/build/soutil.py
@@ -1,6 +1,6 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
 
-# Copyright (c) 2008, 2017 Nicira, Inc.
+# Copyright (c) 2008, 2017, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/python/ovs/.gitignore b/python/ovs/.gitignore
index 9852786466..8bbcd824f4 100644
--- a/python/ovs/.gitignore
+++ b/python/ovs/.gitignore
@@ -1 +1,2 @@
 version.py
+dirs.py
diff --git a/python/ovs/compat/sortedcontainers/sortedlist.py b/python/ovs/compat/sortedcontainers/sortedlist.py
index 8aec6bbac1..ba55566926 100644
--- a/python/ovs/compat/sortedcontainers/sortedlist.py
+++ b/python/ovs/compat/sortedcontainers/sortedlist.py
@@ -3,8 +3,6 @@
 """
 # pylint: disable=redefined-builtin, ungrouped-imports
 
-from __future__ import print_function
-
 from bisect import bisect_left, bisect_right, insort
 from collections import Sequence, MutableSequence
 from functools import wraps
diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index 020291d486..4cf79cf94e 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import collections
 import functools
 import uuid
 
@@ -39,6 +40,10 @@ OVSDB_UPDATE2 = 1
 CLUSTERED = "clustered"
 
 
+Notice = collections.namedtuple('Notice', ('event', 'row', 'updates'))
+Notice.__new__.__defaults__ = (None,)  # default updates=None
+
+
 class Idl(object):
     """Open vSwitch Database Interface Definition Language (OVSDB IDL).
 
@@ -241,6 +246,7 @@ class Idl(object):
         i = 0
         while i < 50:
             i += 1
+            previous_change_seqno = self.change_seqno
             if not self._session.is_connected():
                 break
 
@@ -269,7 +275,7 @@ class Idl(object):
                 if msg.params[0] == str(self.server_monitor_uuid):
                     self.__parse_update(msg.params[1], OVSDB_UPDATE,
                                         tables=self.server_tables)
-                    self.change_seqno = initial_change_seqno
+                    self.change_seqno = previous_change_seqno
                     if not self.__check_server_db():
                         self.force_reconnect()
                         break
@@ -312,7 +318,7 @@ class Idl(object):
                         self.__error()
                         break
                     else:
-                        self.change_seqno = initial_change_seqno
+                        self.change_seqno = previous_change_seqno
                         self.__send_monitor_request()
             elif (msg.type == ovs.jsonrpc.Message.T_REPLY
                   and self._server_monitor_request_id is not None
@@ -322,7 +328,7 @@ class Idl(object):
                     self._server_monitor_request_id = None
                     self.__parse_update(msg.result, OVSDB_UPDATE,
                                         tables=self.server_tables)
-                    self.change_seqno = initial_change_seqno
+                    self.change_seqno = previous_change_seqno
                     if self.__check_server_db():
                         self.__send_monitor_request()
                         self.__send_db_change_aware()
@@ -336,7 +342,7 @@ class Idl(object):
                         self.__error()
                         break
                     else:
-                        self.change_seqno = initial_change_seqno
+                        self.change_seqno = previous_change_seqno
                         self.__send_monitor_request()
             elif (msg.type == ovs.jsonrpc.Message.T_REPLY
                   and self._db_change_aware_request_id is not None
@@ -372,7 +378,7 @@ class Idl(object):
                     self.force_reconnect()
                     break
                 else:
-                    self.change_seqno = initial_change_seqno
+                    self.change_seqno = previous_change_seqno
                     self.__send_monitor_request()
             elif (msg.type in (ovs.jsonrpc.Message.T_ERROR,
                                ovs.jsonrpc.Message.T_REPLY)
@@ -614,6 +620,7 @@ class Idl(object):
             raise error.Error("<table-updates> is not an object",
                               table_updates)
 
+        notices = []
         for table_name, table_update in table_updates.items():
             table = tables.get(table_name)
             if not table:
@@ -639,7 +646,9 @@ class Idl(object):
                                       % (table_name, uuid_string))
 
                 if version == OVSDB_UPDATE2:
-                    if self.__process_update2(table, uuid, row_update):
+                    changes = self.__process_update2(table, uuid, row_update)
+                    if changes:
+                        notices.append(changes)
                         self.change_seqno += 1
                     continue
 
@@ -652,17 +661,20 @@ class Idl(object):
                     raise error.Error('<row-update> missing "old" and '
                                       '"new" members', row_update)
 
-                if self.__process_update(table, uuid, old, new):
+                changes = self.__process_update(table, uuid, old, new)
+                if changes:
+                    notices.append(changes)
                     self.change_seqno += 1
+        for notice in notices:
+            self.notify(*notice)
 
     def __process_update2(self, table, uuid, row_update):
+        """Returns Notice if a column changed, False otherwise."""
         row = table.rows.get(uuid)
-        changed = False
         if "delete" in row_update:
             if row:
                 del table.rows[uuid]
-                self.notify(ROW_DELETE, row)
-                changed = True
+                return Notice(ROW_DELETE, row)
             else:
                 # XXX rate-limit
                 vlog.warn("cannot delete missing row %s from table"
@@ -681,29 +693,27 @@ class Idl(object):
             changed = self.__row_update(table, row, row_update)
             table.rows[uuid] = row
             if changed:
-                self.notify(ROW_CREATE, row)
+                return Notice(ROW_CREATE, row)
         elif "modify" in row_update:
             if not row:
                 raise error.Error('Modify non-existing row')
 
             old_row = self.__apply_diff(table, row, row_update['modify'])
-            self.notify(ROW_UPDATE, row, Row(self, table, uuid, old_row))
-            changed = True
+            return Notice(ROW_UPDATE, row, Row(self, table, uuid, old_row))
         else:
             raise error.Error('<row-update> unknown operation',
                               row_update)
-        return changed
+        return False
 
     def __process_update(self, table, uuid, old, new):
-        """Returns True if a column changed, False otherwise."""
+        """Returns Notice if a column changed, False otherwise."""
         row = table.rows.get(uuid)
         changed = False
         if not new:
             # Delete row.
             if row:
                 del table.rows[uuid]
-                changed = True
-                self.notify(ROW_DELETE, row)
+                return Notice(ROW_DELETE, row)
             else:
                 # XXX rate-limit
                 vlog.warn("cannot delete missing row %s from table %s"
@@ -723,7 +733,7 @@ class Idl(object):
             if op == ROW_CREATE:
                 table.rows[uuid] = row
             if changed:
-                self.notify(ROW_CREATE, row)
+                return Notice(ROW_CREATE, row)
         else:
             op = ROW_UPDATE
             if not row:
@@ -737,8 +747,8 @@ class Idl(object):
             if op == ROW_CREATE:
                 table.rows[uuid] = row
             if changed:
-                self.notify(op, row, Row.from_json(self, table, uuid, old))
-        return changed
+                return Notice(op, row, Row.from_json(self, table, uuid, old))
+        return False
 
     def __check_server_db(self):
         """Returns True if this is a valid server database, False otherwise."""
@@ -1567,10 +1577,9 @@ class Transaction(object):
                     for col, val in row._mutations['_inserts'].items():
                         column = row._table.columns[col]
                         if column.type.is_map():
-                            opdat = ["map"]
                             datum = data.Datum.from_python(column.type, val,
                                                            _row_to_uuid)
-                            opdat.append(datum.as_list())
+                            opdat = self._substitute_uuids(datum.to_json())
                         else:
                             opdat = ["set"]
                             inner_opdat = []
diff --git a/python/ovs/dirs.py b/python/ovs/dirs.py
deleted file mode 100644
index c67aecbb46..0000000000
--- a/python/ovs/dirs.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# 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.
-
-# The @variables@ in this file are replaced by default directories for
-# use in python/ovs/dirs.py in the source directory and replaced by the
-# configured directories for use in the installed python/ovs/dirs.py.
-#
-import os
-
-# Note that the use of """ is to aid in dealing with paths with quotes in them.
-PKGDATADIR = os.environ.get("OVS_PKGDATADIR", """/usr/local/share/openvswitch""")
-RUNDIR = os.environ.get("OVS_RUNDIR", """/var/run""")
-LOGDIR = os.environ.get("OVS_LOGDIR", """/usr/local/var/log""")
-BINDIR = os.environ.get("OVS_BINDIR", """/usr/local/bin""")
-
-DBDIR = os.environ.get("OVS_DBDIR")
-if not DBDIR:
-    sysconfdir = os.environ.get("OVS_SYSCONFDIR")
-    if sysconfdir:
-        DBDIR = "%s/openvswitch" % sysconfdir
-    else:
-        DBDIR = """/usr/local/etc/openvswitch"""
diff --git a/python/ovs/stream.py b/python/ovs/stream.py
index e9bb0c8548..f5a520862c 100644
--- a/python/ovs/stream.py
+++ b/python/ovs/stream.py
@@ -132,6 +132,10 @@ class Stream(object):
     IPTOS_PREC_INTERNETCONTROL = 0xc0
     DSCP_DEFAULT = IPTOS_PREC_INTERNETCONTROL >> 2
 
+    @staticmethod
+    def check_connection_completion(sock):
+        return ovs.socket_util.check_connection_completion(sock)
+
     @staticmethod
     def open(name, dscp=DSCP_DEFAULT):
         """Attempts to connect a stream to a remote peer.  'name' is a
@@ -189,7 +193,7 @@ class Stream(object):
         if error:
             return error, None
         else:
-            err = ovs.socket_util.check_connection_completion(sock)
+            err = cls.check_connection_completion(sock)
             if err == errno.EAGAIN or err == errno.EINPROGRESS:
                 status = errno.EAGAIN
                 err = 0
@@ -261,7 +265,7 @@ class Stream(object):
 
     def __scs_connecting(self):
         if self.socket is not None:
-            retval = ovs.socket_util.check_connection_completion(self.socket)
+            retval = self.check_connection_completion(self.socket)
             assert retval != errno.EINPROGRESS
         elif sys.platform == 'win32':
             if self.retry_connect:
@@ -761,6 +765,13 @@ Stream.register_method("tcp", TCPStream)
 
 
 class SSLStream(Stream):
+    @staticmethod
+    def check_connection_completion(sock):
+        try:
+            return Stream.check_connection_completion(sock)
+        except SSL.SysCallError as e:
+            return ovs.socket_util.get_exception_errno(e)
+
     @staticmethod
     def needs_probes():
         return True
diff --git a/python/ovstest/rpcserver.py b/python/ovstest/rpcserver.py
index c4aab70207..05b6b1be20 100644
--- a/python/ovstest/rpcserver.py
+++ b/python/ovstest/rpcserver.py
@@ -18,22 +18,14 @@ rpcserver is an XML RPC server that allows RPC client to initiate tests
 
 import sys
 
-import exceptions
-
 import xmlrpc.client
 
-import tcp
-
 from twisted.internet import reactor
 from twisted.internet.error import CannotListenError
 from twisted.web import server
 from twisted.web import xmlrpc
 
-import udp
-
-import util
-
-import vswitch
+from . import tcp, udp, util, vswitch
 
 
 class TestArena(xmlrpc.XMLRPC):
@@ -210,7 +202,7 @@ class TestArena(xmlrpc.XMLRPC):
             (_, port) = self.__get_handle_resources(handle)
             port.loseConnection()
             self.__delete_handle(handle)
-        except exceptions.KeyError:
+        except KeyError:
             return -1
         return 0
 
@@ -222,7 +214,7 @@ class TestArena(xmlrpc.XMLRPC):
             (_, connector) = self.__get_handle_resources(handle)
             connector.disconnect()
             self.__delete_handle(handle)
-        except exceptions.KeyError:
+        except KeyError:
             return -1
         return 0
 
diff --git a/python/ovstest/tcp.py b/python/ovstest/tcp.py
index c495717f2f..098c6cba3e 100644
--- a/python/ovstest/tcp.py
+++ b/python/ovstest/tcp.py
@@ -21,7 +21,7 @@ import time
 from twisted.internet import interfaces
 from twisted.internet.protocol import ClientFactory, Factory, Protocol
 
-from zope.interface import implements
+from zope.interface.declarations import implementer
 
 
 class TcpListenerConnection(Protocol):
@@ -55,8 +55,8 @@ class TcpListenerFactory(Factory):
         return str(self.stats)
 
 
+@implementer(interfaces.IPushProducer)
 class Producer(object):
-    implements(interfaces.IPushProducer)
     """
     This producer class generates infinite byte stream for a specified time
     duration
diff --git a/python/ovstest/tests.py b/python/ovstest/tests.py
index 6de3cc3af4..f959f945ef 100644
--- a/python/ovstest/tests.py
+++ b/python/ovstest/tests.py
@@ -10,8 +10,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import math
 import time
 
diff --git a/python/ovstest/util.py b/python/ovstest/util.py
index 72457158f2..270d6a0376 100644
--- a/python/ovstest/util.py
+++ b/python/ovstest/util.py
@@ -26,8 +26,6 @@ import socket
 import struct
 import subprocess
 
-import exceptions
-
 import xmlrpc.client
 
 
@@ -88,7 +86,7 @@ def start_process(args):
                              stderr=subprocess.PIPE)
         out, err = p.communicate()
         return (p.returncode, out, err)
-    except exceptions.OSError:
+    except OSError:
         return (-1, None, None)
 
 
diff --git a/python/ovstest/vswitch.py b/python/ovstest/vswitch.py
index 9d5b5cffd0..45c9587eeb 100644
--- a/python/ovstest/vswitch.py
+++ b/python/ovstest/vswitch.py
@@ -15,7 +15,7 @@
 """
 vswitch module allows its callers to interact with OVS DB.
 """
-import util
+from . import util
 
 
 def ovs_vsctl_add_bridge(bridge):
diff --git a/python/setup.py b/python/setup.py
index b7252800c1..cfe01763f3 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -10,8 +10,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import sys
 
 from distutils.command.build_ext import build_ext
@@ -30,6 +28,15 @@ except IOError:
           file=sys.stderr)
     sys.exit(-1)
 
+try:
+    # Try to open generated ovs/dirs.py. However, in this case we
+    # don't need to exec()
+    open("ovs/dirs.py")
+except IOError:
+    print("Ensure dirs.py is created by running make python/ovs/dirs.py",
+          file=sys.stderr)
+    sys.exit(-1)
+
 ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
 if sys.platform == 'win32':
     ext_errors += (IOError, ValueError)
@@ -73,8 +80,6 @@ setup_args = dict(
         'Topic :: Software Development :: Libraries :: Python Modules',
         'Topic :: System :: Networking',
         'License :: OSI Approved :: Apache Software License',
-        'Programming Language :: Python :: 2',
-        'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
index 7bc8c34b80..f6ec347c15 100644
--- a/rhel/openvswitch-fedora.spec.in
+++ b/rhel/openvswitch-fedora.spec.in
@@ -318,18 +318,19 @@ exit 0
 %post
 %if %{with libcapng}
 if [ $1 -eq 1 ]; then
-    sed -i 's:^#OVS_USER_ID=:OVS_USER_ID=:' /etc/sysconfig/openvswitch
-    sed -i 's:\(.*su\).*:\1 openvswitch openvswitch:' %{_sysconfdir}/logrotate.d/openvswitch
-
 %if %{with dpdk}
-    sed -i \
-        's@OVS_USER_ID="openvswitch:openvswitch"@OVS_USER_ID="openvswitch:hugetlbfs"@'\
-        /etc/sysconfig/openvswitch
+    %define gname hugetlbfs
+%else
+    %define gname openvswitch
 %endif
+    sed -i \
+        's@^#OVS_USER_ID="openvswitch:openvswitch"@OVS_USER_ID="openvswitch:%{gname}"@'\
+        %{_sysconfdir}/sysconfig/openvswitch
+    sed -i 's:\(.*su\).*:\1 openvswitch %{gname}:' %{_sysconfdir}/logrotate.d/openvswitch
 
-    # In the case of upgrade, this is not needed.
-    chown -R openvswitch:openvswitch /etc/openvswitch
-    chown -R openvswitch:openvswitch /var/log/openvswitch
+    # In the case of upgrade, this is not needed
+    chown -R openvswitch:openvswitch %{_sysconfdir}/openvswitch
+    chown -R openvswitch:%{gname} %{_localstatedir}/log/openvswitch
 fi
 %endif
 
diff --git a/rhel/openvswitch-kmod-fedora.spec.in b/rhel/openvswitch-kmod-fedora.spec.in
index c94f2f5358..15eec6d4c0 100644
--- a/rhel/openvswitch-kmod-fedora.spec.in
+++ b/rhel/openvswitch-kmod-fedora.spec.in
@@ -17,7 +17,8 @@
 #   - 3.10.0 major revision 693  (RHEL 7.4)
 #   - 3.10.0 major revision 957  (RHEL 7.6)
 #   - 3.10.0 major revision 1062 (RHEL 7.7)
-#   - 3.10.0 major revision 1101 (RHEL 7.8)
+#   - 3.10.0 major revision 1101 (RHEL 7.8 Beta)
+#   - 3.10.0 major revision 1127 (RHEL 7.8 GA)
 # By default, build against the current running kernel version
 #%define kernel 3.1.5-1.fc16.x86_64
 #define kernel %{kernel_source}
@@ -97,7 +98,7 @@ if grep -qs "suse" /etc/os-release; then
 elif [ "$mainline_major" = "3" ] && [ "$mainline_minor" = "10" ] &&
      { [ "$major_rev" = "327" ] || [ "$major_rev" = "693" ] || \
        [ "$major_rev" = "957" ] || [ "$major_rev" == "1062" ] || \
-       [ "$major_rev" = "1101" ]; }; then
+       [ "$major_rev" = "1101" ] || [ "$major_rev" = "1127" ] ; }; then
     # For RHEL 7.2, 7.4, 7.6, 7.7, and 7.8
     if [ -x "%{_datadir}/openvswitch/scripts/ovs-kmod-manage.sh" ]; then
         %{_datadir}/openvswitch/scripts/ovs-kmod-manage.sh
diff --git a/rhel/openvswitch.spec.in b/rhel/openvswitch.spec.in
index b0383ed75e..ee8b3c9eac 100644
--- a/rhel/openvswitch.spec.in
+++ b/rhel/openvswitch.spec.in
@@ -39,7 +39,7 @@ BuildRequires: checkpolicy, selinux-policy-devel
 BuildRequires: autoconf, automake, libtool
 BuildRequires: python3-sphinx
 BuildRequires: unbound-devel
-BuildRequires: unwind-devel
+BuildRequires: libunwind-devel
 
 %bcond_without check
 %bcond_with check_datapath_kernel
diff --git a/rhel/usr_lib_systemd_system_ovsdb-server.service b/rhel/usr_lib_systemd_system_ovsdb-server.service
index 4c170c09b4..98338b9dfb 100644
--- a/rhel/usr_lib_systemd_system_ovsdb-server.service
+++ b/rhel/usr_lib_systemd_system_ovsdb-server.service
@@ -11,10 +11,16 @@ PIDFile=/var/run/openvswitch/ovsdb-server.pid
 Restart=on-failure
 EnvironmentFile=/etc/openvswitch/default.conf
 EnvironmentFile=-/etc/sysconfig/openvswitch
+EnvironmentFile=-/run/openvswitch.useropts
+
+# Environment is reloaded for each Exec*, make sure to
+# remove openvswitch.useropts first to reload a fresh
+# OVS_USER_ID from default.conf or sysconfig.
+ExecStartPre=/usr/bin/rm -f /run/openvswitch.useropts
+
 ExecStartPre=-/usr/bin/chown ${OVS_USER_ID} /var/run/openvswitch /var/log/openvswitch
-ExecStartPre=/bin/sh -c 'rm -f /run/openvswitch.useropts; /usr/bin/echo "OVS_USER_ID=${OVS_USER_ID}" > /run/openvswitch.useropts'
+ExecStartPre=/bin/sh -c '/usr/bin/echo "OVS_USER_ID=${OVS_USER_ID}" > /run/openvswitch.useropts'
 ExecStartPre=/bin/sh -c 'if [ "$${OVS_USER_ID/:*/}" != "root" ]; then /usr/bin/echo "OVS_USER_OPT=--ovs-user=${OVS_USER_ID}" >> /run/openvswitch.useropts; fi'
-EnvironmentFile=-/run/openvswitch.useropts
 ExecStart=/usr/share/openvswitch/scripts/ovs-ctl \
           --no-ovs-vswitchd --no-monitor --system-id=random \
           ${OVS_USER_OPT} \
diff --git a/rhel/usr_share_openvswitch_scripts_ovs-kmod-manage.sh b/rhel/usr_share_openvswitch_scripts_ovs-kmod-manage.sh
index a9b5cdd817..c70e135cd5 100644
--- a/rhel/usr_share_openvswitch_scripts_ovs-kmod-manage.sh
+++ b/rhel/usr_share_openvswitch_scripts_ovs-kmod-manage.sh
@@ -19,7 +19,8 @@
 #   - 3.10.0 major revision 693  (RHEL 7.4)
 #   - 3.10.0 major revision 957  (RHEL 7.6)
 #   - 3.10.0 major revision 1062 (RHEL 7.7)
-#   - 3.10.0 major revision 1101 (RHEL 7.8)
+#   - 3.10.0 major revision 1101 (RHEL 7.8 Beta)
+#   - 3.10.0 major revision 1127 (RHEL 7.8 GA)
 #   - 4.4.x,  x >= 73           (SLES 12 SP3)
 #   - 4.12.x, x >= 14           (SLES 12 SP4).
 # It is packaged in the openvswitch kmod RPM and run in the post-install
@@ -108,6 +109,11 @@ if [ "$mainline_major" = "3" ] && [ "$mainline_minor" = "10" ]; then
         ver_offset=4
         installed_ver="$minor_rev"
     elif [ "$major_rev" = "1101" ]; then
+#        echo "rhel78"
+        comp_ver=10
+        ver_offset=4
+        installed_ver="$minor_rev"
+    elif [ "$major_rev" = "1127" ]; then
 #        echo "rhel78"
         comp_ver=10
         ver_offset=4
diff --git a/selinux/openvswitch-custom.te.in b/selinux/openvswitch-custom.te.in
index 2adaf231fe..beb0ab0d66 100644
--- a/selinux/openvswitch-custom.te.in
+++ b/selinux/openvswitch-custom.te.in
@@ -19,6 +19,7 @@ require {
         type kernel_t;
         type hostname_exec_t;
         type modules_conf_t;
+        type modules_dep_t;
         type modules_object_t;
         type passwd_file_t;
         type plymouth_exec_t;
@@ -121,6 +122,7 @@ allow openvswitch_load_module_t insmod_exec_t:file { execute execute_no_trans ge
 allow openvswitch_load_module_t kernel_t:system module_request;
 allow openvswitch_load_module_t modules_conf_t:dir { getattr open read search };
 allow openvswitch_load_module_t modules_conf_t:file { getattr open read };
+allow openvswitch_load_module_t modules_dep_t:file { getattr map open read };
 allow openvswitch_load_module_t modules_object_t:file { map getattr open read };
 allow openvswitch_load_module_t modules_object_t:dir { getattr open read search };
 allow openvswitch_load_module_t openvswitch_load_module_exec_t:file { entrypoint };
diff --git a/tests/atlocal.in b/tests/atlocal.in
index 1dc7cd5d08..7e0b91a800 100644
--- a/tests/atlocal.in
+++ b/tests/atlocal.in
@@ -165,6 +165,9 @@ find_command()
 # Set HAVE_NC
 find_command nc
 
+# Set HAVE_TC
+find_command tc
+
 # Determine correct netcat option to quit on stdin EOF
 if nc --version 2>&1 | grep -q nmap.org; then
     # Nmap netcat
diff --git a/tests/automake.mk b/tests/automake.mk
index 9c7ebdce9b..d51d175f40 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -132,7 +132,8 @@ FUZZ_REGRESSION_TESTS = \
 	tests/fuzz-regression/ofp_print_fuzzer-5722747668791296 \
 	tests/fuzz-regression/ofp_print_fuzzer-6285128790704128 \
 	tests/fuzz-regression/ofp_print_fuzzer-6470117922701312 \
-	tests/fuzz-regression/ofp_print_fuzzer-6502620041576448
+	tests/fuzz-regression/ofp_print_fuzzer-6502620041576448 \
+	tests/fuzz-regression/ofp_print_fuzzer-6540965472632832
 $(srcdir)/tests/fuzz-regression-list.at: tests/automake.mk
 	$(AM_V_GEN)for name in $(FUZZ_REGRESSION_TESTS); do \
             basename=`echo $$name | sed 's,^.*/,,'`; \
@@ -152,7 +153,8 @@ SYSTEM_KMOD_TESTSUITE_AT = \
 SYSTEM_USERSPACE_TESTSUITE_AT = \
 	tests/system-userspace-testsuite.at \
 	tests/system-userspace-macros.at \
-	tests/system-userspace-packet-type-aware.at
+	tests/system-userspace-packet-type-aware.at \
+	tests/system-route.at
 
 SYSTEM_AFXDP_TESTSUITE_AT = \
 	tests/system-userspace-macros.at \
diff --git a/tests/bridge.at b/tests/bridge.at
index d48463e263..904f1381c7 100644
--- a/tests/bridge.at
+++ b/tests/bridge.at
@@ -103,3 +103,20 @@ AT_CHECK([ovs-appctl -t ovs-vswitchd version], [0], [ignore])
 OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
 AT_CLEANUP
+
+AT_SETUP([bridge - change ofproto versions])
+dnl Start vswitch and add a version test bridge
+OVS_VSWITCHD_START(
+    [add-br vr_test0 -- \
+     set bridge vr_test0 datapath-type=dummy \
+                         protocols=OpenFlow10])
+
+dnl set the version to include, say, OpenFlow14
+AT_CHECK([ovs-vsctl set bridge vr_test0 protocols=OpenFlow10,OpenFlow14])
+
+dnl now try to use bundle action on a flow
+AT_CHECK([ovs-ofctl add-flow vr_test0 --bundle actions=normal])
+
+OVS_APP_EXIT_AND_WAIT([ovs-vswitchd])
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+AT_CLEANUP
diff --git a/tests/classifier.at b/tests/classifier.at
index 88818618be..cdcd72c156 100644
--- a/tests/classifier.at
+++ b/tests/classifier.at
@@ -304,3 +304,39 @@ ovs-ofctl: "conjunction" actions may be used along with "note" but not any other
 ])
 OVS_VSWITCHD_STOP
 AT_CLEANUP
+
+# Flow classifier a packet with excess of padding.
+AT_SETUP([flow classifier - packet with extra padding])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+AT_DATA([flows.txt], [dnl
+priority=5,ip,ip_dst=1.1.1.1,actions=1
+priority=5,ip,ip_dst=1.1.1.2,actions=2
+priority=0,actions=drop
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+packet=00020202020000010101010008004500001c00010000401176cc01010101010101020d6a00350008ee3a
+AT_CHECK([ovs-appctl ofproto/trace br0 in_port=1 $packet] , [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_dst=1.1.1.2,nw_frag=no
+Datapath actions: 2
+])
+# normal packet plus 255 bytes of padding (8bit padding).
+# 255 * 2 = 510
+padding=$(printf '%*s' 510 | tr ' ' '0')
+AT_CHECK([ovs-appctl ofproto/trace br0 in_port=1 ${packet}${padding}] , [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_dst=1.1.1.2,nw_frag=no
+Datapath actions: 2
+])
+# normal packet plus padding up to 65535 bytes of length (16bit limit).
+# 65535 - 43 = 65492
+# 65492 * 2 = 130984
+padding=$(printf '%*s' 130984 | tr ' ' '0')
+AT_CHECK([ovs-appctl ofproto/trace br0 in_port=1 ${packet}${padding}], [0], [stdout])
+AT_CHECK([tail -2 stdout], [0],
+  [Megaflow: recirc_id=0,eth,ip,in_port=1,nw_dst=1.1.1.2,nw_frag=no
+Datapath actions: 2
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/daemon.at b/tests/daemon.at
index a7982de381..39d9aa391e 100644
--- a/tests/daemon.at
+++ b/tests/daemon.at
@@ -218,11 +218,11 @@ OVS_WAIT_UNTIL([test -s ovsdb-server.pid])
 OVS_WAIT_UNTIL([sc query ovsdb-server | grep STATE | grep RUNNING > /dev/null 2>&1])
 AT_CHECK([kill -0 `cat ovsdb-server.pid`], [0], [ignore])
 AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], [0],
-[Open_vSwitch
+[_Server
 ])
 AT_CHECK([sc stop ovsdb-server], [0], [ignore])
 OVS_WAIT_UNTIL([test ! -s ovsdb-server.pid])
-AT_CHECK([sc query ovsdb-server | grep STATE | grep STOPPED], [0], [ignore])
+OVS_WAIT_UNTIL([sc query ovsdb-server | grep STATE | grep STOPPED > /dev/null 2>&1])
 AT_CHECK([sc delete ovsdb-server], [0], [[[SC]] DeleteService SUCCESS
 ])
 AT_CLEANUP
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
index 0aeb4e788f..1ec0054c5b 100644
--- a/tests/dpif-netdev.at
+++ b/tests/dpif-netdev.at
@@ -293,60 +293,87 @@ type=drop rate=1 burst_size=2
 ])
 
 ovs-appctl time/warp 5000
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
+for i in `seq 1 7`; do
+  AT_CHECK(
+    [ovs-appctl netdev-dummy/receive p7 \
+       'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
+done
+
+for i in `seq 1 5`; do
+  AT_CHECK(
+    [ovs-appctl netdev-dummy/receive p8 \
+       'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
+done
+
 sleep 1  # wait for forwarders process packets
 
 # Meter 1 is measuring packets, allowing one packet per second with
-# bursts of one packet, so 4 out of 5 packets should hit the drop
-# band.
+# bursts of one packet, so 4 out of 5 packets should hit the drop band.
 # Meter 2 is measuring kbps, with burst size 2 (== 2000 bits). 4 packets
-# (240 bytes == 1920 bits) pass, but the last packet should hit the drop band.
+# (240 bytes == 1920 bits) pass, but the last three packets should hit the
+# drop band.  There should be 80 bits remaining for the next packets.
 AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | strip_timers], [0], [dnl
 OFPST_METER reply (OF1.3) (xid=0x2):
 meter:1 flow_count:1 packet_in_count:5 byte_in_count:300 duration:0.0s bands:
 0: packet_count:4 byte_count:240
 
-meter:2 flow_count:1 packet_in_count:5 byte_in_count:300 duration:0.0s bands:
-0: packet_count:1 byte_count:60
+meter:2 flow_count:1 packet_in_count:7 byte_in_count:420 duration:0.0s bands:
+0: packet_count:3 byte_count:180
 ])
 
-# Advance time by 1/2 second
-ovs-appctl time/warp 500
+# Advance time by 870 ms
+ovs-appctl time/warp 870
+
+for i in `seq 1 5`; do
+  AT_CHECK(
+    [ovs-appctl netdev-dummy/receive p7 \
+       'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
+
+  AT_CHECK(
+    [ovs-appctl netdev-dummy/receive p8 \
+       'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
+done
 
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p7 'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
-AT_CHECK([ovs-appctl netdev-dummy/receive p8 'in_port(8),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.3,dst=10.0.0.4,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
 sleep 1  # wait for forwarders process packets
 
 # Meter 1 is measuring packets, allowing one packet per second with
 # bursts of one packet, so all 5 of the new packets should hit the drop
 # band.
-# Meter 2 is measuring kbps, with burst size 2 (== 2000 bits). After 500ms
-# there should be space for 80 + 500 bits, so one new 60 byte (480 bit) packet
-# should pass, remaining 4 should hit the drop band.
+# Meter 2 is measuring kbps, with burst size 2 (== 2000 bits). After 870ms
+# there should be space for 80 + 870 = 950 bits, so one new 60 byte (480 bit)
+# packet should pass, remaining 4 should hit the drop band.  There should be
+# 470 bits left.
 AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | strip_timers], [0], [dnl
 OFPST_METER reply (OF1.3) (xid=0x2):
 meter:1 flow_count:1 packet_in_count:10 byte_in_count:600 duration:0.0s bands:
 0: packet_count:9 byte_count:540
 
-meter:2 flow_count:1 packet_in_count:10 byte_in_count:600 duration:0.0s bands:
-0: packet_count:5 byte_count:300
+meter:2 flow_count:1 packet_in_count:12 byte_in_count:720 duration:0.0s bands:
+0: packet_count:7 byte_count:420
+])
+
+# Advance time by 10 ms
+ovs-appctl time/warp 10
+
+for i in `seq 1 5`; do
+  AT_CHECK(
+    [ovs-appctl netdev-dummy/receive p7 \
+       'in_port(7),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' --len 60])
+done
+
+sleep 1  # wait for forwarders process packets
+
+# Meter 1 should remain the same as we didn't send anything that should hit it.
+# Meter 2 is measuring kbps, with burst size 2 (== 2000 bits). After 10ms
+# there should be space for 470 + 10 = 480 bits, so one new 60 byte (480 bit)
+# packet should pass, remaining 4 should hit the drop band.
+AT_CHECK([ovs-ofctl -O OpenFlow13 meter-stats br0 | strip_timers], [0], [dnl
+OFPST_METER reply (OF1.3) (xid=0x2):
+meter:1 flow_count:1 packet_in_count:10 byte_in_count:600 duration:0.0s bands:
+0: packet_count:9 byte_count:540
+
+meter:2 flow_count:1 packet_in_count:17 byte_in_count:1020 duration:0.0s bands:
+0: packet_count:11 byte_count:660
 ])
 
 ovs-appctl time/warp 5000
@@ -354,7 +381,7 @@ ovs-appctl time/warp 5000
 AT_CHECK([
 ovs-appctl coverage/read-counter datapath_drop_meter
 ], [0], [dnl
-14
+20
 ])
 
 AT_CHECK([cat ovs-vswitchd.log | filter_flow_install | strip_xout_keep_actions], [0], [dnl
@@ -364,6 +391,8 @@ recirc_id(0),in_port(7),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), a
 recirc_id(0),in_port(8),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), actions:2
 ])
 
+AT_CHECK([ovs-ofctl -O OpenFlow13 del-meters br0])
+
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
@@ -371,7 +400,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD],
   [AT_SETUP([dpif-netdev - partial hw offload - $1])
    OVS_VSWITCHD_START(
      [add-port br0 p1 -- \
-      set interface p1 type=$1 ofport_request=1 options:pstream=punix:$OVS_RUNDIR/p1.sock options:ifindex=1 -- \
+      set interface p1 type=$1 ofport_request=1 options:pstream=punix:$OVS_RUNDIR/p1.sock options:ifindex=1100 -- \
       set bridge br0 datapath-type=dummy \
                      other-config:datapath-id=1234 fail-mode=secure], [], [],
       [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
@@ -393,7 +422,7 @@ skb_priority(0),skb_mark(0),ct_state(0),ct_zone(0),ct_mark(0),ct_label(0),recirc
    # Check that flow successfully offloaded.
    OVS_WAIT_UNTIL([grep "succeed to add netdev flow" ovs-vswitchd.log])
    AT_CHECK([filter_hw_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
-p1: flow put[[create]]: flow match: recirc_id=0,eth,ip,in_port=1,vlan_tci=0x0000,nw_frag=no, mark: 0
+p1: flow put[[create]]: flow match: recirc_id=0,eth,ip,in_port=1,vlan_tci=0x0000,nw_frag=no, mark: 1
 ])
    # Check that datapath flow installed successfully.
    AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
@@ -404,7 +433,7 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), a
 
    # Check for succesfull packet matching with installed offloaded flow.
    AT_CHECK([filter_hw_packet_netdev_dummy < ovs-vswitchd.log | strip_xout], [0], [dnl
-p1: packet: ip,vlan_tci=0x0000,dl_src=00:06:07:08:09:0a,dl_dst=00:01:02:03:04:05,nw_src=127.0.0.1,nw_dst=127.0.0.1,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=64 matches with flow: recirc_id=0,eth,ip,vlan_tci=0x0000,nw_frag=no with mark: 0
+p1: packet: ip,vlan_tci=0x0000,dl_src=00:06:07:08:09:0a,dl_dst=00:01:02:03:04:05,nw_src=127.0.0.1,nw_dst=127.0.0.1,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=64 matches with flow: recirc_id=0,eth,ip,vlan_tci=0x0000,nw_frag=no with mark: 1
 ])
 
    ovs-appctl revalidator/wait
@@ -421,7 +450,7 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), p
    # Check that flow successfully deleted from HW.
    OVS_WAIT_UNTIL([grep "succeed to delete netdev flow" ovs-vswitchd.log])
    AT_CHECK([filter_hw_flow_del < ovs-vswitchd.log | strip_xout], [0], [dnl
-p1: flow del: mark: 0
+p1: flow del: mark: 1
 ])
    OVS_VSWITCHD_STOP
    AT_CLEANUP])
@@ -434,7 +463,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS],
   [AT_SETUP([dpif-netdev - partial hw offload with packet modifications - $1])
    OVS_VSWITCHD_START(
      [add-port br0 p1 -- \
-      set interface p1 type=$1 ofport_request=1 options:pcap=p1.pcap options:ifindex=1 -- \
+      set interface p1 type=$1 ofport_request=1 options:pcap=p1.pcap options:ifindex=1101 -- \
       set bridge br0 datapath-type=dummy \
                      other-config:datapath-id=1234 fail-mode=secure], [], [],
       [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
@@ -460,7 +489,7 @@ packet_type(ns=0,id=0),eth(src=00:06:07:08:09:0a,dst=00:01:02:03:04:05),eth_type
    # Check that flow successfully offloaded.
    OVS_WAIT_UNTIL([grep "succeed to add netdev flow" ovs-vswitchd.log])
    AT_CHECK([filter_hw_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
-p1: flow put[[create]]: flow match: recirc_id=0,eth,udp,in_port=1,dl_vlan=99,dl_vlan_pcp=7,nw_src=127.0.0.1,nw_frag=no,tp_dst=82, mark: 0
+p1: flow put[[create]]: flow match: recirc_id=0,eth,udp,in_port=1,dl_vlan=99,dl_vlan_pcp=7,nw_src=127.0.0.1,nw_frag=no,tp_dst=82, mark: 1
 ])
    # Check that datapath flow installed successfully.
    AT_CHECK([filter_flow_install < ovs-vswitchd.log | strip_xout], [0], [dnl
@@ -472,7 +501,7 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x8100),vlan(vid=99,pcp=
    # Check for succesfull packet matching with installed offloaded flow.
    AT_CHECK([filter_hw_packet_netdev_dummy < ovs-vswitchd.log | strip_xout], [0], [dnl
 p1: packet: udp,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09:0a,dl_dst=00:01:02:03:04:05,nw_src=127.0.0.1,nw_dst=127.0.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=81,tp_dst=82 dnl
-matches with flow: recirc_id=0,eth,udp,dl_vlan=99,dl_vlan_pcp=7,nw_src=127.0.0.1,nw_frag=no,tp_dst=82 with mark: 0
+matches with flow: recirc_id=0,eth,udp,dl_vlan=99,dl_vlan_pcp=7,nw_src=127.0.0.1,nw_frag=no,tp_dst=82 with mark: 1
 ])
 
    ovs-appctl revalidator/wait
@@ -490,7 +519,7 @@ packets:1, bytes:64, used:0.0s, actions:set(ipv4(src=192.168.0.7)),set(udp(dst=3
    # Check that flow successfully deleted from HW.
    OVS_WAIT_UNTIL([grep "succeed to delete netdev flow" ovs-vswitchd.log])
    AT_CHECK([filter_hw_flow_del < ovs-vswitchd.log | strip_xout], [0], [dnl
-p1: flow del: mark: 0
+p1: flow del: mark: 1
 ])
 
    # Check that ip address and udp port were correctly modified in output packets.
@@ -506,3 +535,20 @@ udp,in_port=ANY,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09:
 
 DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy])
 DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy-pmd])
+
+AT_SETUP([dpif-netdev - check dpctl/add-flow in_port exact match])
+OVS_VSWITCHD_START(
+  [add-port br0 p1 \
+   -- set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p0.sock \
+   -- set bridge br0 datapath-type=dummy \
+                     other-config:datapath-id=1234 fail-mode=secure])
+
+AT_CHECK([ovs-appctl dpctl/add-flow "eth(),eth_type(0x0800),ipv4()" "3"], [2],
+[], [dnl
+ovs-vswitchd: updating flow table (Invalid argument)
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+OVS_WAIT_UNTIL([grep "flow: in_port is not an exact match" ovs-vswitchd.log])
+OVS_VSWITCHD_STOP(["/flow: in_port is not an exact match/d
+/failed to put/d"])
+AT_CLEANUP
diff --git a/tests/fuzz-regression-list.at b/tests/fuzz-regression-list.at
index e3173fb88f..2347c690ef 100644
--- a/tests/fuzz-regression-list.at
+++ b/tests/fuzz-regression-list.at
@@ -21,3 +21,4 @@ TEST_FUZZ_REGRESSION([ofp_print_fuzzer-5722747668791296])
 TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6285128790704128])
 TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6470117922701312])
 TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6502620041576448])
+TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6540965472632832])
diff --git a/tests/fuzz-regression/ofp_print_fuzzer-6540965472632832 b/tests/fuzz-regression/ofp_print_fuzzer-6540965472632832
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/idltest.ovsschema b/tests/idltest.ovsschema
index bee79fc50f..3ddb612b0c 100644
--- a/tests/idltest.ovsschema
+++ b/tests/idltest.ovsschema
@@ -54,6 +54,15 @@
       },
       "isRoot" : true
     },
+    "indexed": {
+      "columns": {
+        "i": {
+          "type": "integer"
+        }
+      },
+      "indexes": [["i"]],
+      "isRoot" : true
+    },
     "simple": {
       "columns": {
         "b": {
@@ -171,6 +180,36 @@
       },
       "isRoot" : false
     },
+    "simple5": {
+      "columns" : {
+        "name": {"type": "string"},
+        "irefmap": {
+          "type": {
+            "key": {"type": "integer"},
+            "value": {"type": "uuid",
+                      "refTable": "simple3"},
+            "min": 0,
+            "max": "unlimited"
+          }
+        }
+      },
+      "isRoot": true
+    },
+    "simple6": {
+      "columns" : {
+        "name": {"type": "string"},
+        "weak_ref": {
+          "type": {
+            "key": {"type": "uuid",
+                    "refTable": "simple",
+                    "refType": "weak"},
+            "min": 0,
+            "max": "unlimited"
+          }
+        }
+      },
+      "isRoot": true
+    },
     "singleton" : {
       "columns" : {
         "name" : {
diff --git a/tests/library.at b/tests/library.at
index ac4ea4abf2..1702b7556b 100644
--- a/tests/library.at
+++ b/tests/library.at
@@ -53,7 +53,8 @@ AT_CHECK([ovstest test-packets])
 AT_CLEANUP
 
 AT_SETUP([SHA-1])
-AT_CHECK([ovstest test-sha1], [0], [.........
+AT_KEYWORDS([sha1])
+AT_CHECK([ovstest test-sha1], [0], [..........
 ])
 AT_CLEANUP
 
diff --git a/tests/odp.at b/tests/odp.at
index 3ab9ad62dd..516527f9cc 100644
--- a/tests/odp.at
+++ b/tests/odp.at
@@ -397,6 +397,43 @@ odp_actions_from_string: error
 ])
 AT_CLEANUP
 
+AT_SETUP([OVS datapath actions parsing and formatting - userdata overflow])
+dnl Userdata should fit in a single netlink message, i.e. should be less than
+dnl UINT16_MAX - NLA_HDRLEN = 65535 - 4 = 65531 bytes.  OVS should not accept
+dnl larger userdata.  OTOH, userdata is part of a nested netlink message, that
+dnl should not be oversized too.  'pid' takes NLA_HDRLEN + 4 = 8 bytes.
+dnl Plus NLA_HDRLEN for the nested header.  'actions' flag takes NLA_HDRLEN = 4
+dnl and 'tunnel_out_port' takes NLA_HDRLEN + 4 = 8 bytes.
+dnl So, for the variant with 'actions' maximum length of userdata should be:
+dnl UINT16_MAX -  NLA_HDRLEN   - (NLA_HDRLEN + 4) - NLA_HDRLEN - NLA_HDRLEN
+dnl  total max   nested header        pid             actions     userdata
+dnl Result: 65515 bytes for the actual userdata.
+dnl For the case with 'tunnel_out_port': 65511
+dnl Size of userdata will be rounded up to be multiple of 4, so highest
+dnl acceptable sizes are 65512 and 65508.
+
+dnl String with length 65512 * 2 = 131024 is valid, while 131026 is not.
+data_valid=$(  printf '%*s' 131024 | tr ' ' "a")
+data_invalid=$(printf '%*s' 131026 | tr ' ' "a")
+
+echo "userspace(pid=1234567,userdata(${data_valid}),actions)" > actions.txt
+echo "userspace(pid=1234567,userdata(${data_invalid}),actions)" >> actions.txt
+
+dnl String with length 65508 * 2 = 131016 is valid, while 131018 is not.
+data_valid=$(  printf '%*s' 131016 | tr ' ' "a")
+data_invalid=$(printf '%*s' 131018 | tr ' ' "a")
+
+echo "userspace(pid=1234567,userdata(${data_valid}),tunnel_out_port=10)" >> actions.txt
+echo "userspace(pid=1234567,userdata(${data_invalid}),tunnel_out_port=10)" >> actions.txt
+
+AT_CHECK_UNQUOTED([ovstest test-odp parse-actions < actions.txt], [0], [dnl
+`cat actions.txt | head -1`
+odp_actions_from_string: error
+`cat actions.txt | head -3 | tail -1`
+odp_actions_from_string: error
+])
+AT_CLEANUP
+
 AT_SETUP([OVS datapath keys parsing and formatting - 33 nested encap ])
 AT_DATA([odp-in.txt], [dnl
 encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap(encap()))))))))))))))))))))))))))))))))
diff --git a/tests/ofp-actions.at b/tests/ofp-actions.at
index 4893280a99..a0487341c9 100644
--- a/tests/ofp-actions.at
+++ b/tests/ofp-actions.at
@@ -766,6 +766,17 @@ dnl Check OpenFlow v1.3.4 Conformance Test: 430.510.
 & 00000010  00 00 00 10 00 00 00 01-
 0019 0010 80000807 000102030405 000000000010 00000001
 
+dnl Check NSH encap (experimenter extension).
+# actions=encap(nsh(md_type=1))
+ffff 0018 00002320 002e 0000 0001894f 0004 01 05 01 000000
+
+dnl NSH encap with non-zero padding.
+# actions=encap(nsh(md_type=1))
+# 21: 12 -> 00
+# 22: 34 -> 00
+# 23: 56 -> 00
+ffff 0018 00002320 002e 0000 0001894f 0004 01 05 01 123456
+
 ])
 sed '/^[[#&]]/d' < test-data > input.txt
 sed -n 's/^# //p; /^$/p' < test-data > expout
@@ -993,12 +1004,21 @@ bad_action 'dec_ttl(,)' 'dec_ttl_cnt_ids: expected at least one controller id.'
 # set_mpls_label
 bad_action 'set_mpls_label' 'set_mpls_label: expected label.'
 
+# set_mpls_label oversized
+bad_action 'set_mpls_label(0x100000)' '0x100000: not a valid MPLS label'
+
 # set_mpls_tc
 bad_action 'set_mpls_tc' 'set_mpls_tc: expected tc.'
 
+# set_mpls_tc oversized
+bad_action 'set_mpls_tc(8)' '8: not a valid MPLS TC'
+
 # set_mpls_ttl
 bad_action 'set_mpls_ttl' 'set_mpls_ttl: expected ttl.'
 
+# set_mpls_ttl oversized
+bad_action 'set_mpls_ttl(256)' 'invalid MPLS TTL "256"'
+
 # fin_timeout
 bad_action 'fin_timeout(foo=bar)' "invalid key 'foo' in 'fin_timeout' argument"
 
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index ff1cc93707..7b5b2183bf 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -5171,6 +5171,36 @@ AT_CHECK_UNQUOTED([tail -1 stdout], [0], [Datapath actions: 2
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+# Checks for regression against a bug in which OVS dropped packets
+# with in_port=CONTROLLER when they were recirculated (because
+# CONTROLLER isn't a real port and could not be looked up).
+AT_SETUP([ofproto-dpif - packet-out recirculation])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+
+AT_DATA([flows.txt], [dnl
+table=0 ip actions=mod_dl_dst:83:83:83:83:83:83,ct(table=1)
+table=1 ip actions=ct(commit),output:2
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+packet=ffffffffffff00102030405008004500001c00000000401100000a000002ffffffff0035111100080000
+AT_CHECK([ovs-ofctl packet-out br0 "in_port=controller packet=$packet actions=table"])
+
+# Dumps out the flow table, extracts the number of packets that have gone
+# through the (single) flow in table 1, and returns success if it's exactly 1.
+#
+# If this remains 0, then the recirculation isn't working properly since the
+# packet never goes through flow in table 1.
+check_flows () {
+    n=$(ovs-ofctl dump-flows br0 table=1 | sed -n 's/.*n_packets=\([[0-9]]\{1,\}\).*/\1/p')
+    echo "n_packets=$n"
+    test "$n" = 1
+}
+OVS_WAIT_UNTIL([check_flows], [ovs dump-flows br0])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
 
 AT_SETUP([ofproto-dpif - debug_slow action])
 OVS_VSWITCHD_START
@@ -8632,6 +8662,29 @@ recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(dst=50:54:00:00:00:0c),eth_ty
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif megaflow - set dl_dst with match on dl_src])
+OVS_VSWITCHD_START
+AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg])
+add_of_ports br0 1 2
+AT_DATA([flows.txt], [dnl
+table=0 in_port=1,dl_src=50:54:00:00:00:09 actions=mod_dl_dst(50:54:00:00:00:0a),output(2)
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.0.0.2,dst=10.0.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.4,dst=10.0.0.3,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:0b,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(src=10.0.0.6,dst=10.0.0.5,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)'])
+sleep 1
+dnl The first packet is essentially a no-op, as the new destination MAC is the
+dnl same as the original.  The second entry actually updates the destination
+dnl MAC.  The last one must be dropped as it doesn't match with dl_src.
+AT_CHECK([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(frag=no), actions:2
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0c),eth_type(0x0800),ipv4(frag=no), actions:set(eth(dst=50:54:00:00:00:0a)),2
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=50:54:00:00:00:0b),eth_type(0x0800),ipv4(frag=no), actions:drop
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 m4_define([OFPROTO_DPIF_MEGAFLOW_DISABLED],
   [AT_SETUP([ofproto-dpif megaflow - disabled$1])
    OVS_VSWITCHD_START([], [], [], [m4_if([$1], [], [], [--dummy-numa="0,0,0,0,1,1,1,1"])])
@@ -9215,6 +9268,26 @@ OFPST_TABLE reply (OF1.3) (xid=0x2):
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif packet-out table meter drop])
+OVS_VSWITCHD_START
+add_of_ports br0 1 2
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-meter br0 'meter=1 pktps bands=type=drop rate=1'])
+AT_CHECK([ovs-ofctl -O OpenFlow13 add-flow br0 'in_port=1 action=meter:1,output:2'])
+
+ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000400080000 actions=resubmit(,0)"
+ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=50540000000a50540000000908004500001c000000000011a4cd0a0101010a0101020001000400080000 actions=resubmit(,0)"
+
+# Check that vswitchd hasn't crashed by dumping the meter added above
+AT_CHECK([ovs-ofctl -O OpenFlow13 dump-meters br0 | ofctl_strip], [0], [dnl
+OFPST_METER_CONFIG reply (OF1.3):
+meter=1 pktps bands=
+type=drop rate=1
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - ICMPv6])
 OVS_VSWITCHD_START
 add_of_ports br0 1
@@ -10540,6 +10613,62 @@ udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([ofproto-dpif - conntrack - match masked ct fields])
+OVS_VSWITCHD_START
+
+add_of_ports br0 1 2
+
+AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg vconn:info ofproto_dpif:info])
+
+dnl Allow new connections on p1->p2. Allow only established connections p2->p1
+AT_DATA([flows.txt], [dnl
+table=0,arp,action=normal
+table=0,ip,in_port=1,udp,nw_src=10.1.2.1/24,action=ct(commit)
+table=0,ip,in_port=1,udp6,ipv6_dst=2001:db8::1/64,action=ct(commit)
+table=0,ip,in_port=1,udp,tp_src=3/0x1,action=ct(commit)
+table=0,ip,in_port=2,actions=ct(table=1)
+table=0,ip6,in_port=2,actions=ct(table=1)
+table=1,priority=10,udp,ct_state=+trk+rpl,ct_nw_src=10.1.2.1/24,actions=controller
+table=1,priority=10,udp6,ct_state=+trk+rpl,ct_ipv6_dst=2001:db8::1/64,actions=controller
+table=1,priority=10,udp,ct_state=+trk+rpl,ct_tp_src=3/0x1,actions=controller
+table=1,priority=1,action=drop
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+AT_CAPTURE_FILE([ofctl_monitor.log])
+AT_CHECK([ovs-ofctl monitor br0 65534 invalid_ttl -P nxt_packet_in --detach --no-chdir --pidfile 2> ofctl_monitor.log])
+
+dnl Match ct_nw_src=10.1.2.1/24
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.2.100,dst=10.1.2.200,proto=17,tos=0,ttl=64,frag=no),udp(src=6,dst=6)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.2.200,dst=10.1.2.100,proto=17,tos=0,ttl=64,frag=no),udp(src=6,dst=6)'])
+
+dnl Match ct_ipv6_dst=2001:db8::1/64
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x86dd),ipv6(src=2001:db8::1,dst=2001:db8::2,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=1,dst=2)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x86dd),ipv6(src=2001:db8::2,dst=2001:db8::1,label=0,proto=17,tclass=0x70,hlimit=128,frag=no),udp(src=2,dst=1)'])
+
+dnl Match ct_tp_src=3/0x1
+AT_CHECK([ovs-appctl netdev-dummy/receive p1 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.1.1.1,dst=10.1.1.2,proto=17,tos=0,ttl=64,frag=no),udp(src=1,dst=2)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p2 'in_port(2),eth(src=50:54:00:00:00:0a,dst=50:54:00:00:00:09),eth_type(0x0800),ipv4(src=10.1.1.2,dst=10.1.1.1,proto=17,tos=0,ttl=64,frag=no),udp(src=2,dst=1)'])
+
+OVS_WAIT_UNTIL([test `wc -l < ofctl_monitor.log` -ge 6])
+OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+
+dnl Check this output.
+AT_CHECK([cat ofctl_monitor.log], [0], [dnl
+NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.2.100,ct_nw_dst=10.1.2.200,ct_nw_proto=17,ct_tp_src=6,ct_tp_dst=6,ip,in_port=2 (via action) data_len=106 (unbuffered)
+udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.2.200,nw_dst=10.1.2.100,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=6,tp_dst=6 udp_csum:221
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=126 ct_state=est|rpl|trk,ct_ipv6_src=2001:db8::1,ct_ipv6_dst=2001:db8::2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ipv6,in_port=2 (via action) data_len=126 (unbuffered)
+udp6,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,ipv6_src=2001:db8::2,ipv6_dst=2001:db8::1,ipv6_label=0x00000,nw_tos=112,nw_ecn=0,nw_ttl=128,tp_src=2,tp_dst=1 udp_csum:bfe2
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x0 total_len=106 ct_state=est|rpl|trk,ct_nw_src=10.1.1.1,ct_nw_dst=10.1.1.2,ct_nw_proto=17,ct_tp_src=1,ct_tp_dst=2,ip,in_port=2 (via action) data_len=106 (unbuffered)
+udp,vlan_tci=0x0000,dl_src=50:54:00:00:00:0a,dl_dst=50:54:00:00:00:09,nw_src=10.1.1.2,nw_dst=10.1.1.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=2,tp_dst=1 udp_csum:553
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([ofproto-dpif - conntrack - ofproto/trace])
 OVS_VSWITCHD_START
 
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index c8062c8acc..ebf0dc41c0 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -101,6 +101,7 @@ for test_case in \
     'mpls,mpls_label=5                           NXM,OXM,OpenFlow11' \
     'mpls,mpls_tc=1                              NXM,OXM,OpenFlow11' \
     'mpls,mpls_bos=0                             NXM,OXM' \
+    'mpls,mpls_ttl=5                             NXM,OXM' \
     'ip,ip_src=1.2.3.4                           any' \
     'ip,ip_src=192.168.0.0/24                    any' \
     'ip,ip_src=192.0.168.0/255.0.255.0           NXM,OXM,OpenFlow11' \
@@ -434,6 +435,7 @@ tcp,actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 actions=controller(max_len=123,reason=invalid_ttl,id=555)
 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+mpls,mpls_label=5,mpls_tc=1,mpls_ttl=1,mpls_bos=0,actions=drop
 ip,actions=ct(commit,zone=5)
 ip,actions=ct(commit,exec(load(1->NXM_NX_CT_MARK[])))
 ip,actions=ct(commit,exec(load(0x1->NXM_NX_CT_LABEL[])))
@@ -447,6 +449,16 @@ actions=output(max_len=100,port=123)
 actions=output(port=100,max_len=123)
 actions=output(port=LOCAL,max_len=123)
 actions=output(port=IN_PORT,max_len=123)
+mpls,mpls_label=1,actions=set_mpls_label(0)
+mpls,mpls_label=1,actions=set_mpls_label(10)
+mpls,mpls_label=1,actions=set_mpls_label(0x10)
+mpls,mpls_label=1,actions=set_mpls_label(0xfffff)
+mpls,mpls_tc=1,actions=set_mpls_tc(0)
+mpls,mpls_tc=1,actions=set_mpls_tc(3)
+mpls,mpls_tc=1,actions=set_mpls_tc(7)
+mpls,mpls_ttl=1,actions=set_mpls_ttl(0)
+mpls,mpls_ttl=1,actions=set_mpls_ttl(200)
+mpls,mpls_ttl=1,actions=set_mpls_ttl(255)
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -490,6 +502,7 @@ NXT_FLOW_MOD: ADD table:255 tcp actions=fin_timeout(idle_timeout=5,hard_timeout=
 NXT_FLOW_MOD: ADD table:255 actions=controller(reason=invalid_ttl,max_len=123,id=555)
 NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 NXT_FLOW_MOD: ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678,sampling_port=56789)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_label=5,mpls_tc=1,mpls_ttl=1,mpls_bos=0 actions=drop
 NXT_FLOW_MOD: ADD table:255 ip actions=ct(commit,zone=5)
 NXT_FLOW_MOD: ADD table:255 ip actions=ct(commit,exec(load:0x1->NXM_NX_CT_MARK[]))
 NXT_FLOW_MOD: ADD table:255 ip actions=ct(commit,exec(load:0x1->NXM_NX_CT_LABEL[0..63],load:0->NXM_NX_CT_LABEL[64..127]))
@@ -503,6 +516,16 @@ NXT_FLOW_MOD: ADD table:255 actions=output(port=123,max_len=100)
 NXT_FLOW_MOD: ADD table:255 actions=output(port=100,max_len=123)
 NXT_FLOW_MOD: ADD table:255 actions=output(port=LOCAL,max_len=123)
 NXT_FLOW_MOD: ADD table:255 actions=output(port=IN_PORT,max_len=123)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_label=1 actions=set_mpls_label(0)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_label=1 actions=set_mpls_label(10)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_label=1 actions=set_mpls_label(16)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_label=1 actions=set_mpls_label(1048575)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_tc=1 actions=set_mpls_tc(0)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_tc=1 actions=set_mpls_tc(3)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_tc=1 actions=set_mpls_tc(7)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_ttl=1 actions=set_mpls_ttl(0)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_ttl=1 actions=set_mpls_ttl(200)
+NXT_FLOW_MOD: ADD table:255 mpls,mpls_ttl=1 actions=set_mpls_ttl(255)
 ]])
 AT_CLEANUP
 
diff --git a/tests/ovs-vsctl.at b/tests/ovs-vsctl.at
index 55c7a6e179..1f1fc3c79a 100644
--- a/tests/ovs-vsctl.at
+++ b/tests/ovs-vsctl.at
@@ -966,6 +966,14 @@ AT_CHECK([RUN_OVS_VSCTL([--if-exists del-zone-tp netdev zone=1])])
 AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:2, Timeout Policies: icmp_first=2 icmp_reply=3
 ])
 
+AT_CHECK(
+  [RUN_OVS_VSCTL_TOGETHER([--id=@n create CT_Zone external_ids:"test"="123"],
+                          [--id=@m create Datapath datapath_version=0 ct_zones:"10"=@n],
+                          [set Open_vSwitch . datapaths:"netdev"=@m])],
+  [0], [stdout])
+AT_CHECK([RUN_OVS_VSCTL([list-zone-tp netdev])], [0], [Zone:10, Timeout Policies: system default
+])
+
 AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 'capabilities={recirc=true}' -- set Open_vSwitch . datapaths:"system"=@m])], [0], [stdout])
 AT_CHECK([RUN_OVS_VSCTL([list-dp-cap system])], [0], [recirc=true
 ])
@@ -1631,3 +1639,26 @@ AT_CHECK([grep "server name" ovsdb-server.log], [0],
 
 OVS_VSCTL_CLEANUP
 AT_CLEANUP
+
+dnl ----------------------------------------------------------------------
+AT_BANNER([set ingress policing test])
+
+AT_SETUP([set ingress_policing_rate and ingress_policing_burst])
+AT_KEYWORDS([ingress_policing])
+OVS_VSCTL_SETUP
+AT_CHECK([RUN_OVS_VSCTL_TOGETHER(
+   [add-br a],
+   [add-port a a1],
+   [set interface a1 ingress_policing_rate=100],
+   [set interface a1 ingress_policing_burst=10],
+   [--columns=ingress_policing_burst,ingress_policing_rate list interface a1])],
+   [0],
+   [
+
+
+
+ingress_policing_burst: 10
+ingress_policing_rate: 100
+])
+OVS_VSCTL_CLEANUP
+AT_CLEANUP
diff --git a/tests/ovsdb-client.at b/tests/ovsdb-client.at
index 8d777a0275..5e3b26aea8 100644
--- a/tests/ovsdb-client.at
+++ b/tests/ovsdb-client.at
@@ -12,6 +12,30 @@ AT_CHECK([ovsdb-client get-schema-cksum unix:socket ordinals], [0], [12345678 9
 OVSDB_SERVER_SHUTDOWN
 AT_CLEANUP
 
+AT_SETUP([ovsdb-client needs-conversion (no conversion needed)])
+AT_KEYWORDS([ovsdb client file positive])
+ordinal_schema > schema
+touch .db.~lock~
+AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0], [ignore], [ignore])
+AT_CHECK([ovsdb-client needs-conversion unix:socket schema], [0], [no
+])
+OVSDB_SERVER_SHUTDOWN
+AT_CLEANUP
+
+AT_SETUP([ovsdb-client needs-conversion (conversion needed)])
+AT_KEYWORDS([ovsdb client file positive])
+ordinal_schema > schema
+touch .db.~lock~
+AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore])
+AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0], [ignore], [ignore])
+sed 's/5\.1\.3/5.1.4/' < schema > schema2
+AT_CHECK([diff schema schema2], [1], [ignore])
+AT_CHECK([ovsdb-client needs-conversion unix:socket schema2], [0], [yes
+])
+OVSDB_SERVER_SHUTDOWN
+AT_CLEANUP
+
 AT_SETUP([ovsdb-client backup and restore])
 AT_KEYWORDS([ovsdb client positive])
 
diff --git a/tests/ovsdb-cluster.at b/tests/ovsdb-cluster.at
index 3a0bd4579e..cf43e9cf86 100644
--- a/tests/ovsdb-cluster.at
+++ b/tests/ovsdb-cluster.at
@@ -128,7 +128,7 @@ ovsdb_test_cluster_disconnect () {
            "rows": [{"i": 1}]}]]' > test-ovsdb.log 2>&1 &
     echo $! > test-ovsdb.pid
 
-    OVS_WAIT_UNTIL([grep "000: i=1" test-ovsdb.log])
+    OVS_WAIT_UNTIL([grep "000: table simple: i=1" test-ovsdb.log])
 
     # Start collecting raft_is_connected logs for $target before shutting down
     # any servers.
@@ -179,6 +179,41 @@ AT_KEYWORDS([ovsdb server negative unix cluster disconnect])
 ovsdb_test_cluster_disconnect 5 leader yes
 AT_CLEANUP
 
+AT_SETUP([OVSDB cluster - initial status should be disconnected])
+AT_KEYWORDS([ovsdb server negative unix cluster disconnect])
+
+n=3
+schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool '-vPATTERN:console:%c|%p|%m' create-cluster s1.db $abs_srcdir/idltest.ovsschema unix:s1.raft], [0], [], [stderr])
+cid=`ovsdb-tool db-cid s1.db`
+schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
+for i in `seq 2 $n`; do
+    AT_CHECK([ovsdb-tool join-cluster s$i.db $schema_name unix:s$i.raft unix:s1.raft])
+done
+
+on_exit 'kill `cat *.pid`'
+for i in `seq $n`; do
+    AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db])
+done
+for i in `seq $n`; do
+    AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+
+# Stop all servers, and start the s1 only, to test initial connection status
+# when there is no leader yet.
+for i in `seq 1 $n`; do
+    OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s$i], [s$i.pid])
+done
+i=1
+AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db])
+
+# The initial status should be disconnected. So wait should fail.
+AT_CHECK([ovsdb_client_wait --timeout=1 unix:s$i.ovsdb $schema_name connected], [142], [ignore], [ignore])
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s$i], [s$i.pid])
+
+AT_CLEANUP
+
 
 
 AT_BANNER([OVSDB cluster election timer change])
@@ -273,6 +308,88 @@ OVS_WAIT_UNTIL([ovs-appctl -t "`pwd`"/s4 cluster/status $schema_name | grep "Ele
 
 AT_CLEANUP
 
+
+AT_BANNER([OVSDB cluster install snapshot RPC])
+
+AT_SETUP([OVSDB cluster - install snapshot RPC])
+AT_KEYWORDS([ovsdb server positive unix cluster snapshot])
+
+n=3
+schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool '-vPATTERN:console:%c|%p|%m' create-cluster s1.db $abs_srcdir/idltest.ovsschema unix:s1.raft], [0], [], [stderr])
+cid=`ovsdb-tool db-cid s1.db`
+schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
+for i in `seq 2 $n`; do
+    AT_CHECK([ovsdb-tool join-cluster s$i.db $schema_name unix:s$i.raft unix:s1.raft])
+done
+
+on_exit 'kill `cat *.pid`'
+for i in `seq $n`; do
+    AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db])
+done
+for i in `seq $n`; do
+    AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+
+AT_CHECK([ovsdb-client transact unix:s1.ovsdb '[["idltest",
+      {"op": "insert",
+       "table": "indexed",
+       "row": {"i": 0}}]]'], [0], [ignore], [ignore])
+
+# Kill one follower (s2) and write some data to cluster, so that the follower is falling behind
+printf "\ns2: stopping\n"
+OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s2], [s2.pid])
+
+# Delete "i":0 and readd it to get a different UUID for it.
+AT_CHECK([ovsdb-client transact unix:s1.ovsdb '[["idltest",
+      {"op": "delete",
+       "table": "indexed",
+       "where": [["i", "==", 0]]}]]'], [0], [ignore], [ignore])
+
+AT_CHECK([ovsdb-client transact unix:s1.ovsdb '[["idltest",
+      {"op": "insert",
+       "table": "indexed",
+       "row": {"i": 0}}]]'], [0], [ignore], [ignore])
+
+AT_CHECK([ovsdb-client transact unix:s1.ovsdb '[["idltest",
+      {"op": "insert",
+       "table": "indexed",
+       "row": {"i": 1}}]]'], [0], [ignore], [ignore])
+
+# Compact leader online to generate snapshot
+AT_CHECK([ovs-appctl -t "`pwd`"/s1 ovsdb-server/compact])
+
+# Start the follower s2 again.
+AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s2.log --pidfile=s2.pid --unixctl=s2 --remote=punix:s2.ovsdb s2.db])
+AT_CHECK([ovsdb_client_wait unix:s2.ovsdb $schema_name connected])
+
+# A client transaction through s2. During this transaction, there will be a
+# install_snapshot RPC because s2 detects it is behind and s1 doesn't have the
+# pre_log_index requested by s2 because it is already compacted.
+# After the install_snapshot RPC process, the transaction through s2 should
+# succeed.
+AT_CHECK([ovsdb-client transact unix:s2.ovsdb '[["idltest",
+      {"op": "insert",
+       "table": "indexed",
+       "row": {"i": 2}}]]'], [0], [ignore], [ignore])
+
+# The snapshot should overwrite the in-memory contents of the DB on S2
+# without generating any constraint violations. All tree records (0, 1, 2)
+# should be in the DB at this point.
+AT_CHECK([ovsdb-client --no-headings dump unix:s2.ovsdb idltest indexed | uuidfilt | sort -k 2], [0], [dnl
+<0> 0
+<1> 1
+<2> 2
+indexed table
+])
+
+for i in `seq $n`; do
+    OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s$i], [s$i.pid])
+done
+
+AT_CLEANUP
+
 
 
 OVS_START_SHELL_HELPERS
@@ -436,6 +553,61 @@ AT_KEYWORDS([ovsdb server negative unix cluster pending-txn])
 ovsdb_cluster_failure_test 2 2 3 crash-after-receiving-append-request-update
 AT_CLEANUP
 
+
+AT_SETUP([OVSDB cluster - competing candidates])
+AT_KEYWORDS([ovsdb server negative unix cluster competing-candidates])
+
+n=3
+schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
+ordinal_schema > schema
+AT_CHECK([ovsdb-tool '-vPATTERN:console:%c|%p|%m' create-cluster s1.db $abs_srcdir/idltest.ovsschema unix:s1.raft], [0], [], [stderr])
+cid=`ovsdb-tool db-cid s1.db`
+schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
+for i in `seq 2 $n`; do
+    AT_CHECK([ovsdb-tool join-cluster s$i.db $schema_name unix:s$i.raft unix:s1.raft])
+done
+
+on_exit 'kill `cat *.pid`'
+for i in `seq $n`; do
+    AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb s$i.db])
+done
+for i in `seq $n`; do
+    AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+
+# We need to simulate the situation when 2 candidates starts election with same
+# term.
+#
+# Before triggering leader election, tell follower s2 don't send vote request (simulating
+# vote-request lost or not handled in time), and tell follower s3 to delay
+# election timer to make sure s3 doesn't send vote-request before s2 enters
+# term 2.
+AT_CHECK([ovs-appctl -t "`pwd`"/s2 cluster/failure-test dont-send-vote-request], [0], [ignore])
+AT_CHECK([ovs-appctl -t "`pwd`"/s3 cluster/failure-test delay-election], [0], [ignore])
+
+# Restart leader, which will become follower, and both old followers will start
+# election as candidate. The new follower (old leader) will vote one of them,
+# and the other candidate should step back as follower as again.
+kill -9 `cat s1.pid`
+AT_CHECK([ovsdb-server -v -vconsole:off -vsyslog:off --detach --no-chdir --log-file=s1.log --pidfile=s1.pid --unixctl=s1 --remote=punix:s1.ovsdb s1.db])
+
+# Tell s1 to delay election timer so that it won't start election before s3
+# becomes candidate.
+AT_CHECK([ovs-appctl -t "`pwd`"/s1 cluster/failure-test delay-election], [0], [ignore])
+
+OVS_WAIT_UNTIL([ovs-appctl -t "`pwd`"/s1 cluster/status $schema_name | grep "Term: 2"])
+
+for i in `seq $n`; do
+    OVS_WAIT_WHILE([ovs-appctl -t "`pwd`"/s$i cluster/status $schema_name | grep "candidate"])
+    AT_CHECK([ovsdb_client_wait unix:s$i.ovsdb $schema_name connected])
+done
+
+for i in `seq $n`; do
+    OVS_APP_EXIT_AND_WAIT_BY_TARGET([`pwd`/s$i], [s$i.pid])
+done
+
+AT_CLEANUP
+
 
 AT_BANNER([OVSDB - cluster tests])
 
@@ -529,7 +701,7 @@ ovsdb|WARN|schema: changed 30 columns in 'Open_vSwitch' database from ephemeral
     # Use file instead of var because code inside "while" runs in a subshell.
     echo 0 > phase
     i=0
-    (while :; do echo; sleep 0.1; done) | while read REPLY; do
+    (while :; do echo || exit 0; sleep 0.1; done) | while read REPLY; do
         printf "t=%2d s:" $i
         done=0
         for j in $(seq 0 $(expr $n1 - 1)); do
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index cc38d69c10..a1daf9a137 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -12,25 +12,6 @@ ovsdb_start_idltest () {
     on_exit 'kill `cat ovsdb-server.pid`'
 }
 
-# ovsdb_cluster_start_idltest [REMOTE] [SCHEMA]
-#
-# Creates a database using SCHEMA (default: idltest.ovsschema) and
-# starts a database cluster listening on punix:socket and REMOTE (if
-# specified).
-ovsdb_cluster_start_idltest () {
-   local n=$1
-   ovsdb-tool create-cluster s1.db $abs_srcdir/idltest.ovsschema unix:s1.raft || return $?
-   cid=`ovsdb-tool db-cid s1.db`
-   schema_name=`ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema`
-   for i in `seq 2 $n`; do
-     ovsdb-tool join-cluster s$i.db $schema_name unix:s$i.raft unix:s1.raft || return $?
-   done
-   for i in `seq $n`; do
-     ovsdb-server -vraft -vconsole:warn --detach --no-chdir --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i --remote=punix:s$i.ovsdb ${2:+--remote=$2} s$i.db || return $?
-   done
-   on_exit 'kill `cat s*.pid`'
-}
-
 # ovsdb_cluster_leader [REMOTES] [DATABASE]
 #
 # Returns the leader of the DATABASE cluster.
@@ -48,6 +29,35 @@ ovsdb_cluster_leader () {
    done
 }])
 
+# OVSDB_CLUSTER_START_IDLTEST([N], [REMOTE])
+#
+# Creates a clustered database using idltest.ovsschema and starts a database
+# cluster of N servers listening on punix:socket and REMOTE (if specified).
+m4_define([OVSDB_CLUSTER_START_IDLTEST],
+  [n=$1
+   AT_CHECK([ovsdb-tool create-cluster s1.db \
+                        $abs_srcdir/idltest.ovsschema unix:s1.raft])
+   cid=$(ovsdb-tool db-cid s1.db)
+   schema_name=$(ovsdb-tool schema-name $abs_srcdir/idltest.ovsschema)
+   for i in $(seq 2 $n); do
+     AT_CHECK([ovsdb-tool join-cluster s$i.db \
+                          $schema_name unix:s$i.raft unix:s1.raft])
+   done
+   on_exit 'kill $(cat s*.pid)'
+   for i in $(seq $n); do
+     AT_CHECK([ovsdb-server -vraft -vconsole:warn --detach --no-chdir \
+                   --log-file=s$i.log --pidfile=s$i.pid --unixctl=s$i \
+                   --remote=punix:s$i.ovsdb                           \
+                   m4_if([$2], [], [], [--remote=$2]) s$i.db])
+   done
+
+   for i in $(seq $n); do
+       OVS_WAIT_UNTIL([ovs-appctl -t $(pwd)/s$i cluster/status ${schema_name} \
+                                           | grep -q 'Status: cluster member'])
+   done
+])
+
+
 # OVSDB_CHECK_IDL_C(TITLE, [PRE-IDL-TXN], TRANSACTIONS, OUTPUT, [KEYWORDS],
 #                   [FILTER])
 #
@@ -131,7 +141,7 @@ m4_define([OVSDB_CHECK_IDL_REGISTER_COLUMNS_PY],
    AT_CHECK([ovsdb_start_idltest])
    m4_if([$2], [], [],
      [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore])])
-   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket ?simple:b,ba,i,ia,r,ra,s,sa,u,ua?link1:i,k,ka,l2?link2:i,l1?singleton:name $3],
+   AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py  -t10 idl $srcdir/idltest.ovsschema unix:socket ?simple:b,ba,i,ia,r,ra,s,sa,u,ua?simple3:name,uset,uref?simple4:name?simple6:name,weak_ref?link1:i,k,ka,l2?link2:i,l1?singleton:name $3],
             [0], [stdout], [ignore])
    AT_CHECK([sort stdout | uuidfilt]m4_if([$6],,, [[| $6]]),
             [0], [$4])
@@ -345,28 +355,28 @@ OVSDB_CHECK_IDL([simple idl, initially empty, various ops],
     'reconnect']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
-002: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-002: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+002: table simple: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 003: {"error":null,"result":[{"count":2}]}
-004: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-004: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+004: table simple: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 005: {"error":null,"result":[{"count":2}]}
-006: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-006: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+006: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+006: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]}
-008: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-008: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-008: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+008: table simple: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+008: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+008: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 009: {"error":null,"result":[{"count":2}]}
-010: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-010: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-010: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+010: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+010: table simple: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+010: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 011: {"error":null,"result":[{"count":1}]}
-012: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-012: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+012: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+012: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 013: reconnect
-014: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-014: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+014: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+014: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 015: done
 ]])
 
@@ -393,11 +403,11 @@ OVSDB_CHECK_IDL([simple idl, initially populated],
        "table": "simple",
        "where": [],
        "row": {"b": true}}]']],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-000: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+000: table simple: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
 001: {"error":null,"result":[{"count":2}]}
-002: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-002: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
+002: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
 003: done
 ]])
 
@@ -421,14 +431,14 @@ OVSDB_CHECK_IDL([simple idl, writing via IDL],
        "row": {}}]']],
   [['verify 0 b, verify 1 r, set 0 b 1, set 1 r 3.5' \
     'insert 2, verify 2 i, verify 1 b, delete 1']],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-000: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+000: table simple: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
 001: commit, status=success
-002: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-002: i=1 r=3.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
+002: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=3.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<5>
 003: commit, status=success
-004: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-004: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<6>
+004: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: table simple: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<6>
 005: done
 ]])
 
@@ -438,10 +448,10 @@ OVSDB_CHECK_IDL([simple idl, writing via IDL with unicode],
        "table": "simple",
        "row": {"s": "(╯°□°)╯︵ ┻━┻"}}]']],
   [['set 0 b 1, insert 1, set 1 s "¯\_(ツ)_/¯"']],
-  [[000: i=0 r=0 b=false s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+  [[000: table simple: i=0 r=0 b=false s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 001: commit, status=success
-002: i=0 r=0 b=true s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-002: i=1 r=0 b=false s="¯\_(ツ)_/¯" u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+002: table simple: i=0 r=0 b=true s=(╯°□°)╯︵ ┻━┻ u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=0 b=false s="¯\_(ツ)_/¯" u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 003: done
 ]])
 
@@ -465,10 +475,10 @@ OVSDB_CHECK_IDL_PY_WITH_EXPOUT([simple idl, writing large data via IDL with unic
        "table": "simple",
        "row": {"s": "'$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50})'"}}]']],
   [['set 0 b 1, insert 1, set 1 s '$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..100})'']],
-  [[000: i=0 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+  [[000: table simple: i=0 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 001: commit, status=success
-002: i=0 r=0 b=true s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-002: i=1 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..100}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+002: table simple: i=0 r=0 b=true s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..50}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=0 b=false s=$(printf "测试超过四千零九十六个字节的中文字符串以使解码出现问题。%.0s" {1..100}) u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 003: done]])
 
 OVSDB_CHECK_IDL([simple idl, handling verification failure],
@@ -489,16 +499,16 @@ OVSDB_CHECK_IDL([simple idl, handling verification failure],
     '+verify 1 r, set 1 r 3' \
     'verify 1 r, set 1 r 3' \
     ]],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-000: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+000: table simple: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 001: commit, status=success
 002: {"error":null,"result":[{"count":1}]}
 003: commit, status=try again
-004: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-004: i=1 r=5 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+004: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: table simple: i=1 r=5 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 005: commit, status=success
-006: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-006: i=1 r=3 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+006: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+006: table simple: i=1 r=3 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 007: done
 ]])
 
@@ -508,9 +518,9 @@ OVSDB_CHECK_IDL([simple idl, increment operation],
        "table": "simple",
        "row": {}}]']],
   [['set 0 r 2.0, increment 0']],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 001: commit, status=success, increment=1
-002: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=2 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 003: done
 ]])
 
@@ -521,10 +531,10 @@ OVSDB_CHECK_IDL([simple idl, aborting],
        "row": {}}]']],
   [['set 0 r 2.0, abort' \
 '+set 0 b 1']],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 001: commit, status=aborted
 002: commit, status=success
-003: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: done
 ]])
 
@@ -535,10 +545,10 @@ OVSDB_CHECK_IDL([simple idl, destroy without commit or abort],
        "row": {}}]']],
   [['set 0 r 2.0, destroy' \
 '+set 0 b 1']],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 001: destroy
 002: commit, status=success
-003: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=0 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: done
 ]])
 
@@ -554,7 +564,7 @@ OVSDB_CHECK_IDL([simple idl, conditional, false condition],
   [[000: change conditions
 001: empty
 002: change conditions
-003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: done
 ]])
 
@@ -570,7 +580,7 @@ OVSDB_CHECK_IDL([simple idl, conditional, true condition],
   [[000: change conditions
 001: empty
 002: change conditions
-003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: done
 ]])
 
@@ -591,8 +601,8 @@ OVSDB_CHECK_IDL([simple idl, conditional, multiple clauses in condition],
   [[000: change conditions
 001: empty
 002: change conditions
-003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-003: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 004: done
 ]])
 
@@ -608,7 +618,7 @@ OVSDB_CHECK_IDL([simple idl, conditional, modify as insert due to condition],
   [[000: change conditions
 001: empty
 002: change conditions
-003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: done
 ]])
 
@@ -631,11 +641,11 @@ OVSDB_CHECK_IDL([simple idl, conditional, modify as delete due to condition],
   [[000: change conditions
 001: empty
 002: change conditions
-003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: change conditions
 005: empty
 006: {"error":null,"result":[{"uuid":["uuid","<2>"]}]}
-007: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+007: table simple: i=2 r=3 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 008: done
 ]])
 
@@ -666,15 +676,15 @@ OVSDB_CHECK_IDL([simple idl, conditional, multiple tables],
   [[000: change conditions
 001: empty
 002: change conditions
-003: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 004: change conditions
-005: i=0 k=0 ka=[] l2= uuid=<2>
-005: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+005: table link1: i=0 k=0 ka=[] l2= uuid=<2>
+005: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 006: change conditions
 007: {"error":null,"result":[{"uuid":["uuid","<3>"]}]}
-008: i=0 k=0 ka=[] l2= uuid=<2>
-008: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-008: i=3 l1= uuid=<3>
+008: table link1: i=0 k=0 ka=[] l2= uuid=<2>
+008: table link2: i=3 l1= uuid=<3>
+008: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 009: done
 ]])
 
@@ -706,19 +716,19 @@ OVSDB_CHECK_IDL([self-linking idl, consistent ops],
        "row": {"k": ["uuid", "#0#"]}}]']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]}
-002: i=0 k=0 ka=[] l2= uuid=<0>
+002: table link1: i=0 k=0 ka=[] l2= uuid=<0>
 003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
-004: i=0 k=0 ka=[] l2= uuid=<0>
-004: i=1 k=2 ka=[] l2= uuid=<1>
-004: i=2 k=1 ka=[] l2= uuid=<2>
+004: table link1: i=0 k=0 ka=[] l2= uuid=<0>
+004: table link1: i=1 k=2 ka=[] l2= uuid=<1>
+004: table link1: i=2 k=1 ka=[] l2= uuid=<2>
 005: {"error":null,"result":[{"count":1}]}
-006: i=0 k=0 ka=[] l2= uuid=<0>
-006: i=1 k=1 ka=[] l2= uuid=<1>
-006: i=2 k=1 ka=[] l2= uuid=<2>
+006: table link1: i=0 k=0 ka=[] l2= uuid=<0>
+006: table link1: i=1 k=1 ka=[] l2= uuid=<1>
+006: table link1: i=2 k=1 ka=[] l2= uuid=<2>
 007: {"error":null,"result":[{"count":3}]}
-008: i=0 k=0 ka=[] l2= uuid=<0>
-008: i=1 k=0 ka=[] l2= uuid=<1>
-008: i=2 k=0 ka=[] l2= uuid=<2>
+008: table link1: i=0 k=0 ka=[] l2= uuid=<0>
+008: table link1: i=1 k=0 ka=[] l2= uuid=<1>
+008: table link1: i=2 k=0 ka=[] l2= uuid=<2>
 009: done
 ]])
 
@@ -757,12 +767,12 @@ OVSDB_CHECK_IDL([self-linking idl, inconsistent ops],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"details":"Table link1 column k row <0> references nonexistent row <1> in table link1.","error":"referential integrity violation"}]}
 002: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
-003: i=1 k=1 ka=[] l2= uuid=<2>
-003: i=2 k=1 ka=[] l2= uuid=<3>
+003: table link1: i=1 k=1 ka=[] l2= uuid=<2>
+003: table link1: i=2 k=1 ka=[] l2= uuid=<3>
 004: {"error":null,"result":[{"count":2},{"details":"Table link1 column k row <x> references nonexistent row <4> in table link1.","error":"referential integrity violation"}]}
 005: {"error":null,"result":[{"count":1},{"details":"cannot delete link1 row <2> because of 1 remaining reference(s)","error":"referential integrity violation"}]}
 006: {"error":null,"result":[{"count":1}]}
-007: i=1 k=1 ka=[] l2= uuid=<2>
+007: table link1: i=1 k=1 ka=[] l2= uuid=<2>
 008: {"error":null,"result":[{"count":1}]}
 009: empty
 010: done
@@ -805,15 +815,15 @@ OVSDB_CHECK_IDL([self-linking idl, sets],
        "where": []}]']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
-002: i=0 k=0 ka=[0] l2= uuid=<0>
-002: i=1 k=0 ka=[1] l2= uuid=<1>
-002: i=2 k=0 ka=[2] l2= uuid=<2>
-002: i=3 k=0 ka=[3] l2= uuid=<3>
+002: table link1: i=0 k=0 ka=[0] l2= uuid=<0>
+002: table link1: i=1 k=0 ka=[1] l2= uuid=<1>
+002: table link1: i=2 k=0 ka=[2] l2= uuid=<2>
+002: table link1: i=3 k=0 ka=[3] l2= uuid=<3>
 003: {"error":null,"result":[{"count":4}]}
-004: i=0 k=0 ka=[0 1 2 3] l2= uuid=<0>
-004: i=1 k=0 ka=[0 1 2 3] l2= uuid=<1>
-004: i=2 k=0 ka=[0 1 2 3] l2= uuid=<2>
-004: i=3 k=0 ka=[0 1 2 3] l2= uuid=<3>
+004: table link1: i=0 k=0 ka=[0 1 2 3] l2= uuid=<0>
+004: table link1: i=1 k=0 ka=[0 1 2 3] l2= uuid=<1>
+004: table link1: i=2 k=0 ka=[0 1 2 3] l2= uuid=<2>
+004: table link1: i=3 k=0 ka=[0 1 2 3] l2= uuid=<3>
 005: {"error":null,"result":[{"count":1},{"details":"Table link1 column ka row <2> references nonexistent row <4> in table link1.","error":"referential integrity violation"}]}
 006: {"error":null,"result":[{"count":4}]}
 007: empty
@@ -833,8 +843,8 @@ OVSDB_CHECK_IDL([external-linking idl, consistent ops],
        "uuid-name": "row1"}]']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
-002: i=0 l1= uuid=<0>
-002: i=1 k=1 ka=[] l2=0 uuid=<1>
+002: table link1: i=1 k=1 ka=[] l2=0 uuid=<1>
+002: table link2: i=0 l1= uuid=<0>
 003: done
 ]])
 
@@ -857,20 +867,49 @@ OVSDB_CHECK_IDL([singleton idl, constraints],
        "row": {"name": "bar"}}]']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]}
-002: name=foo uuid=<0>
+002: table singleton: name=foo uuid=<0>
 003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"details":"transaction causes \"singleton\" table to contain 2 rows, greater than the schema-defined limit of 1 row(s)","error":"constraint violation"}]}
 004: {"error":null,"result":[{"count":1},{"uuid":["uuid","<2>"]}]}
-005: name=bar uuid=<2>
+005: table singleton: name=bar uuid=<2>
 006: done
 ]])
 
+dnl This test creates a database with references and checks that deleting both
+dnl source and destination rows of a reference in a single update doesn't leak
+dnl rows that got orphaned when processing the update.
+OVSDB_CHECK_IDL([simple idl, references, multiple deletes],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"},
+       "uuid-name": "weak_row0"},
+      {"op": "insert",
+       "table": "simple6",
+       "row": {"name": "first_row",
+               "weak_ref": ["set",
+                             [["named-uuid", "weak_row0"]]
+                           ]}}]']],
+  [['["idltest",
+      {"op": "delete",
+       "table": "simple",
+       "where": [["s", "==", "row0_s"]]},
+      {"op": "delete",
+       "table": "simple6",
+       "where": [["name", "==", "first_row"]]}]']],
+  [[000: table simple6: name=first_row weak_ref=[<0>] uuid=<1>
+000: table simple: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
+001: {"error":null,"result":[{"count":1},{"count":1}]}
+002: empty
+003: done
+]])
+
 OVSDB_CHECK_IDL_PY([external-linking idl, insert ops],
   [],
   [['linktest']],
   [[000: empty
 001: commit, status=success
-002: i=1 k=1 ka=[1] l2= uuid=<0>
-002: i=2 k=1 ka=[1 2] l2= uuid=<1>
+002: table link1: i=1 k=1 ka=[1] l2= uuid=<0>
+002: table link1: i=2 k=1 ka=[1 2] l2= uuid=<1>
 003: done
 ]])
 
@@ -879,7 +918,7 @@ OVSDB_CHECK_IDL_PY([getattr idl, insert ops],
   [['getattrtest']],
   [[000: empty
 001: commit, status=success
-002: i=2 k=2 ka=[] l2= uuid=<0>
+002: table link1: i=2 k=2 ka=[] l2= uuid=<0>
 003: done
 ]])
 
@@ -892,11 +931,11 @@ OVSDB_CHECK_IDL_PY([row-from-json idl, whats this],
        "table": "simple",
        "row": {}}]']],
   [['notifytest insert 2, notifytest set 1 b 1, notifytest delete 0']],
-  [[000: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-000: i=1 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+  [[000: table simple: i=0 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+000: table simple: i=1 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
 001: commit, status=success, events=create|2|None, delete|0|None, update|1|b
-002: i=1 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
-002: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+002: table simple: i=1 r=0 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+002: table simple: i=2 r=0 b=false s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
 003: done
 ]])
 
@@ -936,25 +975,28 @@ AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 idl uni
 AT_CHECK([sort stdout | uuidfilt], [0],
     [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]}]}
-002: i=0 k=0 ka=[] l2= uuid=<0>
+002: table link1: i=0 k=0 ka=[] l2= uuid=<0>
 003: {"error":null,"result":[{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]}]}
-004: i=0 k=0 ka=[] l2= uuid=<0>
-004: i=1 k=2 ka=[] l2= uuid=<1>
-004: i=2 k=1 ka=[] l2= uuid=<2>
+004: table link1: i=0 k=0 ka=[] l2= uuid=<0>
+004: table link1: i=1 k=2 ka=[] l2= uuid=<1>
+004: table link1: i=2 k=1 ka=[] l2= uuid=<2>
 005: {"error":null,"result":[{"count":1}]}
-006: i=0 k=0 ka=[] l2= uuid=<0>
-006: i=1 k=1 ka=[] l2= uuid=<1>
-006: i=2 k=1 ka=[] l2= uuid=<2>
+006: table link1: i=0 k=0 ka=[] l2= uuid=<0>
+006: table link1: i=1 k=1 ka=[] l2= uuid=<1>
+006: table link1: i=2 k=1 ka=[] l2= uuid=<2>
 007: {"error":null,"result":[{"count":3}]}
-008: i=0 k=0 ka=[] l2= uuid=<0>
-008: i=1 k=0 ka=[] l2= uuid=<1>
-008: i=2 k=0 ka=[] l2= uuid=<2>
+008: table link1: i=0 k=0 ka=[] l2= uuid=<0>
+008: table link1: i=1 k=0 ka=[] l2= uuid=<1>
+008: table link1: i=2 k=0 ka=[] l2= uuid=<2>
 009: done
 ]])
 
 # Check that ovsdb-idl figured out that table link2 and column l2 are missing.
 AT_CHECK([grep ovsdb_idl stderr | sort], [0], [dnl
+test-ovsdb|ovsdb_idl|idltest database lacks indexed table (database needs upgrade?)
 test-ovsdb|ovsdb_idl|idltest database lacks link2 table (database needs upgrade?)
+test-ovsdb|ovsdb_idl|idltest database lacks simple5 table (database needs upgrade?)
+test-ovsdb|ovsdb_idl|idltest database lacks simple6 table (database needs upgrade?)
 test-ovsdb|ovsdb_idl|idltest database lacks singleton table (database needs upgrade?)
 test-ovsdb|ovsdb_idl|link1 table in idltest database lacks l2 column (database needs upgrade?)
 ])
@@ -1009,11 +1051,11 @@ OVSDB_CHECK_IDL_FETCH_COLUMNS([simple idl, initially populated],
        "row": {}}]']],
   [?simple:i,r!],
   ['fetch 0 r'],
-  [[000: i=0 uuid=<0>
-000: i=1 uuid=<1>
+  [[000: table simple: i=0 uuid=<0>
+000: table simple: i=1 uuid=<1>
 001: commit, status=success
-002: i=0 r=0 uuid=<0>
-002: i=1 uuid=<1>
+002: table simple: i=0 r=0 uuid=<0>
+002: table simple: i=1 uuid=<1>
 003: done
 ]])
 
@@ -1085,28 +1127,28 @@ OVSDB_CHECK_IDL_WO_MONITOR_COND([simple idl disable monitor-cond],
     'reconnect']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
-002: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-002: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+002: table simple: i=0 r=0 b=false s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+002: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 003: {"error":null,"result":[{"count":2}]}
-004: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-004: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+004: table simple: i=0 r=0 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: table simple: i=1 r=2 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 005: {"error":null,"result":[{"count":2}]}
-006: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-006: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+006: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+006: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]}
-008: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-008: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-008: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+008: table simple: i=-1 r=125 b=false s= u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+008: table simple: i=0 r=123.5 b=true s= u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+008: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 009: {"error":null,"result":[{"count":2}]}
-010: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-010: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-010: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+010: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+010: table simple: i=0 r=123.5 b=true s=newstring u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+010: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 011: {"error":null,"result":[{"count":1}]}
-012: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-012: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+012: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+012: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 013: reconnect
-014: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-014: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
+014: table simple: i=-1 r=125 b=false s=newstring u=<2> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+014: table simple: i=1 r=123.5 b=true s=mystring u=<3> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<4> <5>] uuid=<0>
 015: done
 ]])
 
@@ -1149,15 +1191,354 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated],
        "table": "simple",
        "where": [],
        "row": {"b": true}}]']],
-  [[000: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3>
-000: updated columns: b ba i ia r ra s sa u ua
+  [[000: table simple: inserted row: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3>
+000: table simple: updated columns: b ba i ia r ra s sa u ua
 001: {"error":null,"result":[{"count":2}]}
-002: i=0 r=0 b=true s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<5>
-002: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3>
-002: updated columns: b
+002: table simple: i=0 r=0 b=true s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<5>
+002: table simple: i=1 r=2 b=true s=mystring u=<0> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<1> <2>] uuid=<3>
+002: table simple: updated columns: b
 003: done
 ]])
 
+dnl This test creates database with weak references and checks that orphan
+dnl rows created for weak references are not available for iteration via
+dnl list of tracked changes.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, orphan weak references],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"},
+       "uuid-name": "weak_row0"},
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row1_s"},
+       "uuid-name": "weak_row1"},
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row2_s"},
+       "uuid-name": "weak_row2"},
+      {"op": "insert",
+       "table": "simple6",
+       "row": {"name": "first_row",
+               "weak_ref": ["set",
+                             [["named-uuid", "weak_row0"],
+                              ["named-uuid", "weak_row1"],
+                              ["named-uuid", "weak_row2"]]
+                           ]}}]']],
+  [['condition simple []' \
+    'condition simple [["s","==","row1_s"]]' \
+    '["idltest",
+      {"op": "update",
+      "table": "simple6",
+      "where": [],
+      "row": {"name": "new_name"}}]' \
+    '["idltest",
+      {"op": "delete",
+      "table": "simple6",
+      "where": []}]']],
+  [[000: change conditions
+001: table simple6: inserted row: name=first_row weak_ref=[] uuid=<0>
+001: table simple6: updated columns: name weak_ref
+002: change conditions
+003: table simple6: name=first_row weak_ref=[<1>] uuid=<0>
+003: table simple: inserted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: updated columns: s
+004: {"error":null,"result":[{"count":1}]}
+005: table simple6: name=new_name weak_ref=[<1>] uuid=<0>
+005: table simple6: updated columns: name
+006: {"error":null,"result":[{"count":1}]}
+007: table simple: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+008: done
+]])
+
+dnl This test creates database with weak references and checks that the
+dnl content of orphaned rows created for weak references after monitor
+dnl condition change are not leaked when the row is reinserted and deleted.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, orphan rows, conditional],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"},
+       "uuid-name": "weak_row0"},
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row1_s"},
+       "uuid-name": "weak_row1"},
+      {"op": "insert",
+       "table": "simple6",
+       "row": {"name": "first_row",
+               "weak_ref": ["set",
+                             [["named-uuid", "weak_row0"]]
+                           ]}}]']],
+  [['condition simple []' \
+    'condition simple [["s","==","row0_s"]]' \
+    'condition simple [["s","==","row1_s"]]' \
+    'condition simple [["s","==","row0_s"]]' \
+    '["idltest",
+      {"op": "delete",
+      "table": "simple6",
+      "where": []}]']],
+  [[000: change conditions
+001: table simple6: inserted row: name=first_row weak_ref=[] uuid=<0>
+001: table simple6: updated columns: name weak_ref
+002: change conditions
+003: table simple6: name=first_row weak_ref=[<1>] uuid=<0>
+003: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: updated columns: s
+004: change conditions
+005: table simple6: name=first_row weak_ref=[] uuid=<0>
+005: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+005: table simple: inserted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+005: table simple: updated columns: s
+006: change conditions
+007: table simple6: name=first_row weak_ref=[<1>] uuid=<0>
+007: table simple: deleted row: i=0 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+007: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+007: table simple: updated columns: s
+008: {"error":null,"result":[{"count":1}]}
+009: table simple: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+010: done
+]])
+
+dnl This test checks that deleting the destination of a weak reference
+dnl without deleting the source, through monitor condition change, updates
+dnl the source tracked record.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, references, conditional delete],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s", "i": 0},
+       "uuid-name": "weak_row0"},
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row1_s", "i": 1},
+       "uuid-name": "weak_row1"},
+      {"op": "insert",
+       "table": "simple6",
+       "row": {"name": "first_row",
+               "weak_ref": ["set",
+                             [["named-uuid", "weak_row0"],
+                              ["named-uuid", "weak_row1"]]
+                           ]}}]']],
+  [['condition simple []' \
+    'condition simple [["s","==","row0_s"]]' \
+    'condition simple [["s","==","row1_s"]]' \
+    '["idltest",
+      {"op": "update",
+      "table": "simple6",
+      "where": [],
+      "row": {"name": "new_name"}}]' \
+    '["idltest",
+      {"op": "delete",
+      "table": "simple6",
+      "where": []}]']],
+  [[000: change conditions
+001: table simple6: inserted row: name=first_row weak_ref=[] uuid=<0>
+001: table simple6: updated columns: name weak_ref
+002: change conditions
+003: table simple6: name=first_row weak_ref=[<1>] uuid=<0>
+003: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+003: table simple: updated columns: s
+004: change conditions
+005: table simple6: name=first_row weak_ref=[<3>] uuid=<0>
+005: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+005: table simple: inserted row: i=1 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+005: table simple: updated columns: i s
+006: {"error":null,"result":[{"count":1}]}
+007: table simple6: name=new_name weak_ref=[<3>] uuid=<0>
+007: table simple6: updated columns: name
+008: {"error":null,"result":[{"count":1}]}
+009: table simple: i=1 r=0 b=false s=row1_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+010: done
+]])
+
+dnl This test checks that deleting the destination of a reference updates the
+dnl source tracked record.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, references, single delete],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"},
+       "uuid-name": "uuid_row0_s"},
+      {"op": "insert",
+       "table": "simple6",
+       "row": {"name": "row0_s6",
+               "weak_ref": ["set",
+                             [["named-uuid", "uuid_row0_s"]]
+                           ]}}]']],
+  [['condition simple [true];simple6 [true]' \
+    '["idltest",
+      {"op": "delete",
+       "table": "simple",
+       "where": []}]' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"}}]']],
+  [[000: change conditions
+001: table simple6: inserted row: name=row0_s6 weak_ref=[<0>] uuid=<1>
+001: table simple6: updated columns: name weak_ref
+001: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
+001: table simple: updated columns: s
+002: {"error":null,"result":[{"count":1}]}
+003: table simple6: name=row0_s6 weak_ref=[] uuid=<1>
+003: table simple6: updated columns: weak_ref
+003: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
+004: {"error":null,"result":[{"uuid":["uuid","<3>"]}]}
+005: table simple6: name=row0_s6 weak_ref=[] uuid=<1>
+005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+005: table simple: updated columns: s
+006: done
+]])
+
+dnl This test checks that deleting both the destination and source of the
+dnl reference doesn't remove the reference in the source tracked record.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, weak references, multiple deletes],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"},
+       "uuid-name": "uuid_row0_s"},
+      {"op": "insert",
+       "table": "simple6",
+       "row": {"name": "row0_s6",
+               "weak_ref": ["set",
+                             [["named-uuid", "uuid_row0_s"]]
+                           ]}}]']],
+  [['condition simple [true];simple6 [true]' \
+    '["idltest",
+      {"op": "delete",
+       "table": "simple",
+       "where": []},
+      {"op": "delete",
+       "table": "simple6",
+       "where": []}]' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"}}]']],
+  [[000: change conditions
+001: table simple6: inserted row: name=row0_s6 weak_ref=[<0>] uuid=<1>
+001: table simple6: updated columns: name weak_ref
+001: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
+001: table simple: updated columns: s
+002: {"error":null,"result":[{"count":1},{"count":1}]}
+003: table simple6: deleted row: name=row0_s6 weak_ref=[<0>] uuid=<1>
+003: table simple: deleted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<0>
+004: {"error":null,"result":[{"uuid":["uuid","<3>"]}]}
+005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<2> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+005: table simple: updated columns: s
+006: done
+]])
+
+dnl This test checks that deleting both the destination and source of the
+dnl reference doesn't remove the reference in the source tracked record.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, strong references, multiple deletes],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple4",
+       "row": {"name": "row0_s4"},
+       "uuid-name": "uuid_row0_s4"},
+      {"op": "insert",
+       "table": "simple3",
+       "row": {"name": "row0_s3",
+               "uref": ["set",
+                         [["named-uuid", "uuid_row0_s4"]]
+                       ]}}]']],
+  [['condition simple [true];simple3 [true];simple4 [true]' \
+    '["idltest",
+      {"op": "delete",
+       "table": "simple3",
+       "where": []},
+      {"op": "delete",
+       "table": "simple4",
+       "where": []}]' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"}}]']],
+  [[000: change conditions
+001: table simple3: inserted row: name=row0_s3 uset=[] uref=[<0>] uuid=<1>
+001: table simple3: updated columns: name uref
+001: table simple4: inserted row: name=row0_s4 uuid=<0>
+001: table simple4: updated columns: name
+002: {"error":null,"result":[{"count":1},{"count":1}]}
+003: table simple3: deleted row: name=row0_s3 uset=[] uref=[<0>] uuid=<1>
+003: table simple4: deleted row: name=row0_s4 uuid=<0>
+004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]}
+005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<3> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+005: table simple: updated columns: s
+006: done
+]])
+
+dnl This test checks that changing conditions to not include the target of
+dnl a strong reference also updates the source row when change tracking is
+dnl enabled.
+OVSDB_CHECK_IDL_TRACK([track, simple idl, initially populated, strong references, conditional],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple4",
+       "row": {"name": "row0_s4"},
+       "uuid-name": "uuid_row0_s4"},
+      {"op": "insert",
+       "table": "simple3",
+       "row": {"name": "row0_s3",
+               "uref": ["set",
+                         [["named-uuid", "uuid_row0_s4"]]
+                       ]}}]']],
+  [['condition simple [true];simple3 [true];simple4 [true]' \
+    'condition simple4 []' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"}}]']],
+  [[000: change conditions
+001: table simple3: inserted row: name=row0_s3 uset=[] uref=[<0>] uuid=<1>
+001: table simple3: updated columns: name uref
+001: table simple4: inserted row: name=row0_s4 uuid=<0>
+001: table simple4: updated columns: name
+002: change conditions
+003: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1>
+003: table simple4: deleted row: name=row0_s4 uuid=<0>
+004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]}
+005: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1>
+005: table simple: inserted row: i=0 r=0 b=false s=row0_s u=<3> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+005: table simple: updated columns: s
+006: done
+]])
+
+dnl This test checks that changing conditions to not include the target of
+dnl a strong reference also updates the source row when change tracking is
+dnl disabled.
+OVSDB_CHECK_IDL([simple idl, initially populated, strong references, conditional],
+  [['["idltest",
+      {"op": "insert",
+       "table": "simple4",
+       "row": {"name": "row0_s4"},
+       "uuid-name": "uuid_row0_s4"},
+      {"op": "insert",
+       "table": "simple3",
+       "row": {"name": "row0_s3",
+               "uref": ["set",
+                         [["named-uuid", "uuid_row0_s4"]]
+                       ]}}]']],
+  [['condition simple [true];simple3 [true];simple4 [true]' \
+    'condition simple4 []' \
+    '["idltest",
+      {"op": "insert",
+       "table": "simple",
+       "row": {"s": "row0_s"}}]']],
+  [[000: change conditions
+001: table simple3: name=row0_s3 uset=[] uref=[<0>] uuid=<1>
+001: table simple4: name=row0_s4 uuid=<0>
+002: change conditions
+003: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1>
+004: {"error":null,"result":[{"uuid":["uuid","<2>"]}]}
+005: table simple3: name=row0_s3 uset=[] uref=[] uuid=<1>
+005: table simple: i=0 r=0 b=false s=row0_s u=<3> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+006: done
+]])
+
 OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops],
   [],
   [['["idltest",
@@ -1211,31 +1592,31 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops],
     'reconnect']],
   [[000: empty
 001: {"error":null,"result":[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]}
-002: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0>
-002: updated columns: b ba i ia r ra s sa u ua
+002: table simple: inserted row: i=1 r=2 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0>
+002: table simple: updated columns: b ba i ia r ra s sa u ua
 003: {"error":null,"result":[{"count":2}]}
-004: i=0 r=0 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-004: updated columns: b
+004: table simple: i=0 r=0 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: table simple: updated columns: b
 005: {"error":null,"result":[{"count":2}]}
-006: i=0 r=123.5 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-006: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0>
-006: updated columns: r
-006: updated columns: r
+006: table simple: i=0 r=123.5 b=true s= u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+006: table simple: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0>
+006: table simple: updated columns: r
+006: table simple: updated columns: r
 007: {"error":null,"result":[{"uuid":["uuid","<6>"]}]}
-008: i=-1 r=125 b=false s= u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-008: updated columns: ba i ia r ra
+008: table simple: inserted row: i=-1 r=125 b=false s= u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+008: table simple: updated columns: ba i ia r ra
 009: {"error":null,"result":[{"count":2}]}
-010: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-010: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
-010: updated columns: s
-010: updated columns: s
+010: table simple: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+010: table simple: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+010: table simple: updated columns: s
+010: table simple: updated columns: s
 011: {"error":null,"result":[{"count":1}]}
-012: ##deleted## uuid=<1>
+012: table simple: deleted row: i=0 r=123.5 b=true s=newstring u=<5> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
 013: reconnect
-014: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
-014: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0>
-014: updated columns: b ba i ia r ra s sa u ua
-014: updated columns: ba i ia r ra s
+014: table simple: inserted row: i=-1 r=125 b=false s=newstring u=<5> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<6>
+014: table simple: inserted row: i=1 r=123.5 b=true s=mystring u=<2> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<3> <4>] uuid=<0>
+014: table simple: updated columns: b ba i ia r ra s sa u ua
+014: table simple: updated columns: ba i ia r ra s
 015: done
 ]])
 
@@ -1275,19 +1656,31 @@ OVSDB_CHECK_IDL_PY([partial-map idl],
                 "row":{"name":"myString1","smap":["map",[["key1","value1"],["key2","value2"]]]} }]']
 ],
   [?simple2:name,smap,imap 'partialmapinsertelement' 'partialmapinsertmultipleelements' 'partialmapdelelements' 'partialmapmutatenew'],
-[[000: name=myString1 smap=[(key1 value1) (key2 value2)] imap=[]
+[[000: table simple2: name=myString1 smap=[(key1 value1) (key2 value2)] imap=[] uuid=<0>
 001: commit, status=success
-002: name=String2 smap=[(key1 myList1) (key2 value2)] imap=[(3 myids2)]
+002: table simple2: name=String2 smap=[(key1 myList1) (key2 value2)] imap=[(3 myids2)] uuid=<0>
 003: commit, status=success
-004: name=String2 smap=[(key1 myList1) (key2 myList2) (key3 myList3) (key4 myList4)] imap=[(3 myids2)]
+004: table simple2: name=String2 smap=[(key1 myList1) (key2 myList2) (key3 myList3) (key4 myList4)] imap=[(3 myids2)] uuid=<0>
 005: commit, status=success
-006: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)]
+006: table simple2: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)] uuid=<0>
 007: commit, status=success
-008: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)]
-008: name=String2New smap=[(key1 newList1) (key2 newList2)] imap=[]
+008: table simple2: name=String2 smap=[(key2 myList2)] imap=[(3 myids2)] uuid=<0>
+008: table simple2: name=String2New smap=[(key1 newList1) (key2 newList2)] imap=[] uuid=<1>
 009: done
 ]])
 
+OVSDB_CHECK_IDL_PY([partial-map update set refmap idl],
+[['["idltest", {"op":"insert", "table":"simple3", "row":{"name":"myString1"}},
+               {"op":"insert", "table":"simple5", "row":{"name":"myString2"}}]']],
+['partialmapmutateirefmap'],
+[[000: table simple3: name=myString1 uset=[] uref=[] uuid=<0>
+000: table simple5: name=myString2 irefmap=[] uuid=<1>
+001: commit, status=success
+002: table simple3: name=myString1 uset=[] uref=[] uuid=<0>
+002: table simple5: name=myString2 irefmap=[(1 <0>)] uuid=<1>
+003: done
+]])
+
 m4_define([OVSDB_CHECK_IDL_PARTIAL_UPDATE_SET_COLUMN],
   [AT_SETUP([$1 - C])
    AT_KEYWORDS([ovsdb server idl partial update set column positive $5])
@@ -1307,17 +1700,17 @@ OVSDB_CHECK_IDL_PARTIAL_UPDATE_SET_COLUMN([set, simple3 idl-partial-update-set-c
 ],
 [],
 [[000: Getting records
-001: name=mySet1 uset=[[<0>],[<1>]] uref=[]
+001: table simple3: name=mySet1 uset=[<0>,<1>] uref=[] uuid=<2>
 002: After rename+add new value
-003: name=String2 uset=[[<0>],[<1>],[<2>]] uref=[]
+003: table simple3: name=String2 uset=[<0>,<1>,<3>] uref=[] uuid=<2>
 004: After add new value
-005: name=String2 uset=[[<0>],[<1>],[<2>],[<3>]] uref=[]
+005: table simple3: name=String2 uset=[<0>,<1>,<3>,<4>] uref=[] uuid=<2>
 006: After delete value
-007: name=String2 uset=[[<0>],[<1>],[<3>]] uref=[]
+007: table simple3: name=String2 uset=[<0>,<1>,<4>] uref=[] uuid=<2>
 008: After trying to delete a deleted value
-009: name=String2 uset=[[<0>],[<1>],[<3>]] uref=[]
+009: table simple3: name=String2 uset=[<0>,<1>,<4>] uref=[] uuid=<2>
 010: After add to other table + set of strong ref
-011: name=String2 uset=[[<0>],[<1>],[<3>]] uref=[[<4>]]
+011: table simple3: name=String2 uset=[<0>,<1>,<4>] uref=[<5>] uuid=<2>
 012: End test
 ]])
 
@@ -1329,22 +1722,26 @@ OVSDB_CHECK_IDL_PY([partial-set idl],
                     "mutations": [["uset", "insert", ["set", [["uuid", "000d2f6a-76af-412f-b59d-e7bcd3e84eff"]]]]]}]']
 ],
   ['partialrenamesetadd' 'partialduplicateadd' 'partialsetdel' 'partialsetref' 'partialsetoverrideops' 'partialsetadddelete' 'partialsetmutatenew'],
-[[000: name=mySet1 uset=[<0> <1>]
+[[000: table simple3: name=mySet1 uset=[<0> <1>] uref=[] uuid=<2>
 001: commit, status=success
-002: name=String2 uset=[<0> <1> <2>]
+002: table simple3: name=String2 uset=[<0> <1> <3>] uref=[] uuid=<2>
 003: commit, status=success
-004: name=String2 uset=[<0> <1> <2> <3>]
+004: table simple3: name=String2 uset=[<0> <1> <3> <4>] uref=[] uuid=<2>
 005: commit, status=success
-006: name=String2 uset=[<0> <1> <3>]
+006: table simple3: name=String2 uset=[<0> <1> <4>] uref=[] uuid=<2>
 007: commit, status=success
-008: name=String2 uset=[<0> <1> <3>]
+008: table simple3: name=String2 uset=[<0> <1> <4>] uref=[<5>] uuid=<2>
+008: table simple4: name=test uuid=<5>
 009: commit, status=success
-010: name=String2 uset=[<3>]
+010: table simple3: name=String2 uset=[<4>] uref=[<5>] uuid=<2>
+010: table simple4: name=test uuid=<5>
 011: commit, status=success
-012: name=String2 uset=[<4> <5>]
+012: table simple3: name=String2 uset=[<6> <7>] uref=[<5>] uuid=<2>
+012: table simple4: name=test uuid=<5>
 013: commit, status=success
-014: name=String2 uset=[<4> <5>]
-014: name=String3 uset=[<6>]
+014: table simple3: name=String2 uset=[<6> <7>] uref=[<5>] uuid=<2>
+014: table simple3: name=String3 uset=[<8>] uref=[] uuid=<9>
+014: table simple4: name=test uuid=<5>
 015: done
 ]])
 
@@ -1352,6 +1749,28 @@ m4_define([OVSDB_CHECK_IDL_NOTIFY],
    [OVSDB_CHECK_IDL_PY([$1], [], [$2], [$3], [notify $4], [$5])
     OVSDB_CHECK_IDL_SSL_PY([$1], [], [$2], [$3], [notify $4], [$5])])
 
+OVSDB_CHECK_IDL_NOTIFY([simple link idl verify notify],
+  [['track-notify' \
+    '["idltest",
+       {"op": "insert",
+       "table": "link1",
+       "row": {"i": 1, "k": ["named-uuid", "l1row"], "l2": ["set", [["named-uuid", "l2row"]]]},
+       "uuid-name": "l1row"},
+      {"op": "insert",
+       "table": "link2",
+       "uuid-name": "l2row",
+       "row": {"i": 2, "l1": ["set", [["named-uuid", "l1row"]]]}}]']],
+[[000: empty
+000: event:create, row={}, uuid=<0>, updates=None
+000: event:create, row={}, uuid=<1>, updates=None
+001: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
+002: event:create, row={i=1 l2=[<3>]}, uuid=<2>, updates=None
+002: event:create, row={i=2 l1=[<2>]}, uuid=<3>, updates=None
+002: table link1: i=1 k=1 ka=[] l2=2 uuid=<2>
+002: table link2: i=2 l1=1 uuid=<3>
+003: done
+]])
+
 OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify],
   [['track-notify' \
     '["idltest",
@@ -1404,44 +1823,44 @@ OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify],
        "where": [["i", "==", 0]]}]' \
     'reconnect']],
   [[000: empty
-000: event:create, row={uuid=<0>}, updates=None
-000: event:create, row={uuid=<1>}, updates=None
+000: event:create, row={}, uuid=<0>, updates=None
+000: event:create, row={}, uuid=<1>, updates=None
 001: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
-002: event:create, row={i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates=None
-002: event:create, row={i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates=None
-002: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
-002: i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+002: event:create, row={i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates=None
+002: event:create, row={i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates=None
+002: table simple: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+002: table simple: i=1 r=2 b=true s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 003: {"error":null,"result":[{"count":2}]}
-004: event:update, row={i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates={b=true uuid=<2>}
-004: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
-004: i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+004: event:update, row={i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates={b=true}
+004: table simple: i=0 r=0 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+004: table simple: i=1 r=2 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 005: {"error":null,"result":[{"count":2}]}
-006: event:update, row={i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates={r=0 uuid=<3>}
-006: event:update, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates={r=2 uuid=<2>}
-006: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
-006: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+006: event:update, row={i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates={r=0}
+006: event:update, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates={r=2}
+006: table simple: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+006: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 007: {"error":null,"result":[{"uuid":["uuid","<8>"]}]}
-008: event:create, row={i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates=None
-008: i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
-008: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
-008: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+008: event:create, row={i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[]}, uuid=<8>, updates=None
+008: table simple: i=-1 r=125 b=false s= u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
+008: table simple: i=0 r=123.5 b=false s= u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+008: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 009: {"error":null,"result":[{"count":2}]}
-010: event:update, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates={s= uuid=<8>}
-010: event:update, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates={s= uuid=<3>}
-010: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
-010: i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
-010: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+010: event:update, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[]}, uuid=<8>, updates={s=}
+010: event:update, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates={s=}
+010: table simple: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
+010: table simple: i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>
+010: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 011: {"error":null,"result":[{"count":1}]}
-012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<3>}, updates=None
-012: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
-012: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+012: event:delete, row={i=0 r=123.5 b=false s=newstring u=<4> ia=[] ra=[] ba=[] sa=[] ua=[]}, uuid=<3>, updates=None
+012: table simple: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
+012: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 013: reconnect
-014: event:create, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>}, updates=None
-014: event:create, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>}, updates=None
-014: event:create, row={uuid=<0>}, updates=None
-014: event:create, row={uuid=<1>}, updates=None
-014: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
-014: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
+014: event:create, row={i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[]}, uuid=<8>, updates=None
+014: event:create, row={i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>]}, uuid=<2>, updates=None
+014: event:create, row={}, uuid=<0>, updates=None
+014: event:create, row={}, uuid=<1>, updates=None
+014: table simple: i=-1 r=125 b=false s=newstring u=<4> ia=[1] ra=[1.5] ba=[false] sa=[] ua=[] uuid=<8>
+014: table simple: i=1 r=123.5 b=false s=mystring u=<5> ia=[1 2 3] ra=[-0.5] ba=[true] sa=[abc def] ua=[<6> <7>] uuid=<2>
 015: done
 ]])
 
@@ -1754,43 +2173,35 @@ OVSDB_CHECK_IDL_COMPOUND_INDEX_WITH_REF([set, simple3 idl-compound-index-with-re
 [],
 [],
 [[000: After add to other table + set of strong ref
-001: name= uset=[] uref=[[<0>]]
+001: table simple3: name= uset=[] uref=[<0>] uuid=<1>
 002: check simple4: not empty
 003: Query using index with reference
-004: name= uset=[] uref=[[<0>]]
+004: table simple3: name= uset=[] uref=[<0>] uuid=<1>
 005: After delete
 007: check simple4: empty
 008: End test
 ]])
 
 m4_define([CHECK_STREAM_OPEN_BLOCK],
-  [AT_SETUP([Check Stream open block - C - $1])
-   AT_SKIP_IF([test "$1" = "tcp6" && test "$IS_WIN32" = "yes"])
-   AT_SKIP_IF([test "$1" = "tcp6" && test "$HAVE_IPV6" = "no"])
-   AT_KEYWORDS([Check Stream open block $1])
-   AT_CHECK([ovsdb_start_idltest "ptcp:0:$2"])
+  [AT_SETUP([Check stream open block - $1 - $3])
+   AT_SKIP_IF([test "$3" = "tcp6" && test "$IS_WIN32" = "yes"])
+   AT_SKIP_IF([test "$3" = "tcp6" && test "$HAVE_IPV6" = "no"])
+   AT_KEYWORDS([ovsdb server stream open_block $3])
+   AT_CHECK([ovsdb_start_idltest "ptcp:0:$4"])
    PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
    WRONG_PORT=$(($TCP_PORT + 101))
-   AT_CHECK([test-stream tcp:$2:$TCP_PORT], [0], [ignore])
-   AT_CHECK([test-stream tcp:$2:$WRONG_PORT], [1], [ignore], [ignore])
+   AT_CHECK([$2 tcp:$4:$TCP_PORT], [0], [ignore])
+   AT_CHECK([$2 tcp:$4:$WRONG_PORT], [1], [ignore], [ignore])
    OVSDB_SERVER_SHUTDOWN
-   AT_CHECK([test-stream tcp:$2:$TCP_PORT], [1], [ignore], [ignore])
+   AT_CHECK([$2 tcp:$4:$TCP_PORT], [1], [ignore], [ignore])
    AT_CLEANUP])
 
-CHECK_STREAM_OPEN_BLOCK([tcp], [127.0.0.1])
-CHECK_STREAM_OPEN_BLOCK([tcp6], [[[::1]]])
-
-m4_define([CHECK_STREAM_OPEN_BLOCK_PY],
-  [AT_SETUP([$1 - Python3])
-   AT_KEYWORDS([Check PY Stream open block - $3])
-   AT_CHECK([ovsdb_start_idltest "ptcp:0:127.0.0.1"])
-   PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
-   WRONG_PORT=$(($TCP_PORT + 101))
-   AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$TCP_PORT], [0], [ignore])
-   AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$WRONG_PORT], [1], [ignore])
-   OVSDB_SERVER_SHUTDOWN
-   AT_CHECK([$3 $srcdir/test-stream.py tcp:127.0.0.1:$TCP_PORT], [1], [ignore])
-   AT_CLEANUP])
+CHECK_STREAM_OPEN_BLOCK([C], [test-stream], [tcp], [127.0.0.1])
+CHECK_STREAM_OPEN_BLOCK([C], [test-stream], [tcp6], [[[::1]]])
+CHECK_STREAM_OPEN_BLOCK([Python3], [$PYTHON3 $srcdir/test-stream.py],
+                        [tcp], [127.0.0.1])
+CHECK_STREAM_OPEN_BLOCK([Python3], [$PYTHON3 $srcdir/test-stream.py],
+                        [tcp6], [[[::1]]])
 
 # same as OVSDB_CHECK_IDL but uses Python IDL implementation with tcp
 # with multiple remotes to assert the idl connects to the leader of the Raft cluster
@@ -1798,7 +2209,7 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
   [AT_SETUP([$1 - Python3 (leader only)])
    AT_KEYWORDS([ovsdb server idl Python leader_only with tcp socket])
    m4_define([LPBK],[127.0.0.1])
-   AT_CHECK([ovsdb_cluster_start_idltest $2 "ptcp:0:"LPBK])
+   OVSDB_CLUSTER_START_IDLTEST([$2], ["ptcp:0:"LPBK])
    PARSE_LISTENING_PORT([s2.log], [TCP_PORT_1])
    PARSE_LISTENING_PORT([s3.log], [TCP_PORT_2])
    PARSE_LISTENING_PORT([s1.log], [TCP_PORT_3])
@@ -1814,3 +2225,59 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
 
 OVSDB_CHECK_IDL_LEADER_ONLY_PY([Check Python IDL connects to leader], 3, ['remote'])
 OVSDB_CHECK_IDL_LEADER_ONLY_PY([Check Python IDL reconnects to leader], 3, ['remote' '+remotestop' 'remote'])
+
+# same as OVSDB_CHECK_IDL but uses C IDL implementation with tcp
+# with multiple remotes.
+m4_define([OVSDB_CHECK_CLUSTER_IDL_C],
+  [AT_SETUP([$1 - C - tcp])
+   AT_KEYWORDS([ovsdb server idl positive tcp socket $5])
+   m4_define([LPBK],[127.0.0.1])
+   OVSDB_CLUSTER_START_IDLTEST([$2], ["ptcp:0:"LPBK])
+   PARSE_LISTENING_PORT([s1.log], [TCP_PORT_1])
+   PARSE_LISTENING_PORT([s2.log], [TCP_PORT_2])
+   PARSE_LISTENING_PORT([s3.log], [TCP_PORT_3])
+   remotes=tcp:LPBK:$TCP_PORT_1,tcp:LPBK:$TCP_PORT_2,tcp:LPBK:$TCP_PORT_3
+
+   m4_if([$3], [], [],
+     [AT_CHECK([ovsdb-client transact $remotes $3], [0], [ignore], [ignore])])
+   AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 idl tcp:LPBK:$TCP_PORT_1 $4],
+            [0], [stdout], [ignore])
+   AT_CHECK([sort stdout | uuidfilt]m4_if([$7],,, [[| $7]]),
+            [0], [$5])
+   AT_CLEANUP])
+
+# Checks that monitor_cond_since works fine when disconnects happen
+# with cond_change requests in flight (i.e., IDL is properly updated).
+OVSDB_CHECK_CLUSTER_IDL_C([simple idl, monitor_cond_since, cluster disconnect],
+  3,
+  [['["idltest",
+       {"op": "insert",
+       "table": "simple",
+       "row": {"i": 1,
+               "r": 1.0,
+               "b": true}},
+       {"op": "insert",
+       "table": "simple",
+       "row": {"i": 2,
+               "r": 1.0,
+               "b": true}}]']],
+  [['condition simple []' \
+    'condition simple [["i","==",2]]' \
+    'condition simple [["i","==",1]]' \
+    '+reconnect' \
+    '["idltest",
+      {"op": "update",
+       "table": "simple",
+       "where": [["i", "==", 1]],
+       "row": {"r": 2.0 }}]']],
+  [[000: change conditions
+001: empty
+002: change conditions
+003: table simple: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+004: change conditions
+005: reconnect
+006: table simple: i=2 r=1 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<1>
+007: {"error":null,"result":[{"count":1}]}
+008: table simple: i=1 r=2 b=true s= u=<0> ia=[] ra=[] ba=[] sa=[] ua=[] uuid=<2>
+009: done
+]])
diff --git a/tests/ovsdb-monitor-sort.py b/tests/ovsdb-monitor-sort.py
index 7d368a7afc..8a7976bdc7 100755
--- a/tests/ovsdb-monitor-sort.py
+++ b/tests/ovsdb-monitor-sort.py
@@ -1,4 +1,17 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
+# Copyright (c) 2020 VMware, Inc.
+#
+# 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.
 
 # Breaks lines read from stdin into groups using blank lines as
 # group separators, then sorts lines within the groups for
diff --git a/tests/sendpkt.py b/tests/sendpkt.py
index 328ae2bc9d..49ac45275a 100755
--- a/tests/sendpkt.py
+++ b/tests/sendpkt.py
@@ -1,6 +1,6 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
 
-# Copyright (c) 2018 VMware, Inc.
+# Copyright (c) 2018, 2020 VMware, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index 68c8774d1a..9d5e24a292 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -275,6 +275,12 @@ m4_define([OVS_START_L7],
    ]
 )
 
+# OFPROTO_CLEAR_DURATION_IDLE([])
+#
+# Clear the duration from the piped input which would differ from test to test
+#
+m4_define([OFPROTO_CLEAR_DURATION_IDLE], [[sed -e 's/duration=.*s,/duration=<cleared>,/g' -e 's/idle_age=[0-9]*,/idle_age=<cleared>,/g']])
+
 # OVS_CHECK_VXLAN()
 #
 # Do basic check for vxlan functionality, skip the test if it's not there.
diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at
index daf66bdec8..26beefcf44 100644
--- a/tests/system-kmod-macros.at
+++ b/tests/system-kmod-macros.at
@@ -99,6 +99,17 @@ m4_define([CHECK_CONNTRACK_FRAG_OVERLAP],
 #
 m4_define([CHECK_CONNTRACK_NAT])
 
+# CHECK_CONNTRACK_ZEROIP_SNAT()
+#
+# Perform requirements checks for running conntrack all-zero IP SNAT tests.
+# The kernel always supports all-zero IP SNAT, so no check is needed.
+# However, the Windows datapath using the same netlink interface does not.
+#
+m4_define([CHECK_CONNTRACK_ZEROIP_SNAT],
+[
+    AT_SKIP_IF([test "$IS_WIN32" = "yes"])
+])
+
 # CHECK_CONNTRACK_TIMEOUT()
 #
 # Perform requirements checks for running conntrack customized timeout tests.
diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
index 379a8a5e92..bfad66e051 100644
--- a/tests/system-offloads-traffic.at
+++ b/tests/system-offloads-traffic.at
@@ -66,3 +66,53 @@ in_port(3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:9, bytes:756, used:
 
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
+
+AT_SETUP([offloads - set ingress_policing_rate and ingress_policing_burst - offloads disabled])
+AT_KEYWORDS([ingress_policing])
+AT_SKIP_IF([test $HAVE_TC = "no"])
+OVS_TRAFFIC_VSWITCHD_START()
+AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=false])
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+ADD_NAMESPACES(at_ns0)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_rate=100])
+AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_burst=10])
+AT_CHECK([ovs-vsctl --columns=other_config list open], [0], [dnl
+other_config        : {hw-offload="false"}
+])
+AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress |
+  sed -n 's/.*\(rate [[0-9]]*[[a-zA-Z]]* burst [[0-9]]*[[a-zA-Z]]*\).*/\1/; T; p; q'],
+  [0],[dnl
+rate 100Kbit burst 1280b
+])
+AT_CHECK([tc -s -d filter show dev ovs-p0 ingress | grep basic |
+  sed -n 's/.*\(basic\).*/\1/; T; p; q'], [0], [dnl
+basic
+])
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([offloads - set ingress_policing_rate and ingress_policing_burst - offloads enabled])
+AT_KEYWORDS([ingress_policing])
+AT_SKIP_IF([test $HAVE_TC = "no"])
+OVS_TRAFFIC_VSWITCHD_START()
+AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:hw-offload=true])
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+ADD_NAMESPACES(at_ns0)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_rate=100])
+AT_CHECK([ovs-vsctl set interface ovs-p0 ingress_policing_burst=10])
+AT_CHECK([ovs-vsctl --columns=other_config list open], [0], [dnl
+other_config        : {hw-offload="true"}
+])
+AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress |
+  sed -n 's/.*\(rate [[0-9]]*[[a-zA-Z]]* burst [[0-9]]*[[a-zA-Z]]*\).*/\1/; T; p; q'],
+  [0],[dnl
+rate 100Kbit burst 1280b
+])
+AT_CHECK([tc -o -s -d filter show dev ovs-p0 ingress | grep matchall |
+  sed -n 's/.*\(matchall\).*/\1/; T; p; q'], [0], [dnl
+matchall
+])
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/system-route.at b/tests/system-route.at
new file mode 100644
index 0000000000..1714273e35
--- /dev/null
+++ b/tests/system-route.at
@@ -0,0 +1,28 @@
+AT_BANNER([system-route])
+
+dnl Add an interface, add/del ip address, check that OVS catches route updates.
+AT_SETUP([ovs-route - add/remove system route])
+AT_KEYWORDS([route])
+OVS_TRAFFIC_VSWITCHD_START()
+
+dnl Create tap port.
+AT_CHECK([ip tuntap add name p1-route mode tap])
+AT_CHECK([ip link set p1-route up])
+on_exit 'ip link del p1-route'
+
+dnl Add ip address.
+AT_CHECK([ip addr add 10.0.0.17/24 dev p1-route], [0], [stdout])
+
+dnl Check that OVS catches route updates.
+OVS_WAIT_UNTIL([ovs-appctl ovs/route/show | grep 'p1-route' | sort], [0], [dnl
+Cached: 10.0.0.17/24 dev p1-route SRC 10.0.0.17
+Cached: 10.0.0.17/32 dev p1-route SRC 10.0.0.17 local
+])
+
+dnl Delete ip address.
+AT_CHECK([ip addr del 10.0.0.17/24 dev p1-route], [0], [stdout])
+dnl Check that routes was removed from OVS.
+OVS_WAIT_UNTIL([test `ovs-appctl ovs/route/show | grep -c 'p1-route'` -eq 0 ])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index 4a39c929c2..b5097f2ac3 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -574,6 +574,60 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([datapath - ping over geneve tunnel, delete flow regression])
+OVS_CHECK_GENEVE()
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-underlay])
+
+AT_DATA([flows.txt], [dnl
+priority=100,icmp actions=resubmit(,10)
+priority=0 actions=NORMAL
+table=10, priority=100, ip, actions=ct(table=20,zone=65520)
+table=20, priority=200, ip, ct_state=-new+trk, actions=resubmit(,30)
+table=20, priority=100, ip, ct_state=+new, actions=resubmit(,30)
+table=20, priority=50, ip, actions=DROP
+table=30, priority=100, ip, actions=ct(commit,table=40,zone=65520)
+table=40, actions=normal
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+                  [vni 0])
+
+dnl First, check the underlay
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl ping over tunnel should work
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+AT_CHECK([ovs-ofctl del-flows br0 "ct_state=+new"])
+
+dnl ping should not go through after removal of the flow
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl
+7 packets transmitted, 0 received, 100% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["/|ERR|/d
+/|WARN|/d"])
+AT_CLEANUP
+
 AT_SETUP([datapath - flow resume with geneve tun_metadata])
 OVS_CHECK_GENEVE()
 
@@ -611,6 +665,16 @@ NS_CHECK_EXEC([at_ns0], [ping -q -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl
 3 packets transmitted, 3 received, 0% packet loss, time 0ms
 ])
 
+dnl Test OVS handles TLV map modifictions properly when restores frozen state.
+NS_CHECK_EXEC([at_ns0], [ping 10.1.1.100 > /dev/null &])
+
+AT_CHECK([ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0x88,len=4}->tun_metadata1"])
+sleep 1
+AT_CHECK([ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0x99,len=4}->tun_metadata2"])
+sleep 1
+AT_CHECK([ovs-ofctl add-tlv-map br0 "{class=0xffff,type=0xaa,len=4}->tun_metadata3"])
+sleep 1
+
 OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
@@ -1925,6 +1989,111 @@ tcp,orig=(src=10.1.1.3,dst=10.1.1.4,sport=<cleared>,dport=<cleared>),reply=(src=
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([conntrack - zones from other field])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
+AT_DATA([flows.txt], [dnl
+priority=1,action=drop
+priority=10,arp,action=normal
+priority=10,icmp,action=normal
+priority=100,in_port=1,tcp,ct_state=-trk,action=ct(zone=5,table=0)
+priority=100,in_port=1,tcp,ct_state=+trk,action=ct(commit,zone=NXM_NX_CT_ZONE[]),2
+priority=100,in_port=2,ct_state=-trk,tcp,action=ct(table=0,zone=5)
+priority=100,in_port=2,ct_state=+trk,ct_zone=5,tcp,action=1
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+OVS_START_L7([at_ns1], [http])
+
+dnl HTTP requests from p0->p1 should work fine.
+NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
+tcp,dnl
+orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),dnl
+reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),dnl
+zone=5,protoinfo=(state=<cleared>)
+])
+
+dnl This is to test when the zoneid is set by a field variable like
+dnl NXM_NX_CT_ZONE, the OVS xlate should generate a megaflow with a form of
+dnl "ct_zone(5), ...  actions: ct(commit, zone=5)".  The match "ct_zone(5)"
+dnl is needed as if we changes the zoneid into 15 in the following, the old
+dnl "ct_zone(5), ... actions: ct(commit, zone=5)" megaflow will not get hit,
+dnl and OVS will generate a new megaflow with the match "ct_zone(0xf)".
+dnl This will make sure that the new packets are committing to zoneid 15
+dnl rather than old 5.
+AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
+              | grep "+trk" | grep -q "ct_zone(0x5)" ], [0], [])
+
+AT_CHECK([ovs-ofctl mod-flows br0 dnl
+            'priority=100,ct_state=-trk,tcp,in_port="ovs-p0" actions=ct(table=0,zone=15)'])
+
+NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
+              | grep "+trk" | grep -q "ct_zone(0xf)" ], [0], [])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+AT_SETUP([conntrack - zones from other field, more tests])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+dnl Allow any traffic from ns0->ns1. Only allow nd, return traffic from ns1->ns0.
+AT_DATA([flows.txt], [dnl
+priority=1,action=drop
+priority=10,arp,action=normal
+priority=10,icmp,action=normal
+priority=100,in_port=1,tcp,ct_state=-trk,action=ct(zone=5,table=0,commit,exec(load:0xffff0005->NXM_NX_CT_LABEL[[0..31]]))
+priority=100,in_port=1,tcp,ct_state=+trk,action=ct(commit,zone=NXM_NX_CT_LABEL[[0..15]]),2
+priority=100,in_port=2,ct_state=-trk,tcp,action=ct(table=0,zone=5)
+priority=100,in_port=2,ct_state=+trk,ct_zone=5,tcp,action=1
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+OVS_START_L7([at_ns1], [http])
+
+dnl HTTP requests from p0->p1 should work fine.
+NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.2)], [0], [dnl
+tcp,dnl
+orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),dnl
+reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),dnl
+zone=5,labels=0xffff0005,protoinfo=(state=<cleared>)
+])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
+              | grep "+trk" | sed 's/0xffff0005\/0xffff/0x5\/0xffff/' dnl
+              | grep -q "ct_label(0x5/0xffff)" ], [0], [])
+
+AT_CHECK([ovs-ofctl mod-flows br0 'priority=100,ct_state=-trk,tcp,in_port="ovs-p0" actions=ct(table=0,zone=15,commit,exec(load:0xffff000f->NXM_NX_CT_LABEL[[0..31]]))'])
+
+NS_CHECK_EXEC([at_ns0], [wget 10.1.1.2 -t 3 -T 1 --retry-connrefused -v -o wget0.log])
+
+AT_CHECK([ovs-appctl dpctl/dump-flows --names filter=in_port=ovs-p0 dnl
+              | grep "+trk" | sed 's/0xffff000f\/0xffff/0xf\/0xffff/' dnl
+              | grep -q "ct_label(0xf/0xffff)" ], [0], [])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([conntrack - multiple bridges])
 CHECK_CONNTRACK()
 OVS_TRAFFIC_VSWITCHD_START(
@@ -2331,6 +2500,35 @@ NXST_FLOW reply:
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([conntrack - generic IP protocol])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg ofproto_dpif_upcall:dbg])
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_DATA([flows.txt], [dnl
+table=0, priority=1,action=drop
+table=0, priority=10,arp,action=normal
+table=0, priority=100,ip,action=ct(table=1)
+table=1, priority=100,in_port=1,ip,ct_state=+trk+new,action=ct(commit)
+table=1, priority=100,in_port=1,ct_state=+trk+est,action=normal
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=01005e00001200005e000101080045c0002800000000ff7019cdc0a8001ee0000012210164010001ba52c0a800010000000000000000000000000000 actions=resubmit(,0)"])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=192\.168\.0\.30,"], [], [dnl
+112,orig=(src=192.168.0.30,dst=224.0.0.18,sport=0,dport=0),reply=(src=224.0.0.18,dst=192.168.0.30,sport=0,dport=0)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([conntrack - ICMP related])
 AT_SKIP_IF([test $HAVE_NC = no])
 CHECK_CONNTRACK()
@@ -3220,6 +3418,46 @@ NS_CHECK_EXEC([at_ns0], [ping6 -s 3200 -q -c 3 -i 0.3 -w 2 fc00::2 | FORMAT_PING
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([conntrack - IPv4 Fragmentation + NAT])
+AT_SKIP_IF([test $HAVE_TCPDUMP = no])
+CHECK_CONNTRACK()
+
+OVS_TRAFFIC_VSWITCHD_START(
+   [set-fail-mode br0 secure -- ])
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+
+ADD_VETH(p0, at_ns0, br0, "10.2.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.2.1.2/24")
+
+dnl Create a dummy route for NAT
+NS_CHECK_EXEC([at_ns1], [ip addr add 10.1.1.2/32 dev lo])
+NS_CHECK_EXEC([at_ns0], [ip route add 10.1.1.0/24 via 10.2.1.2])
+NS_CHECK_EXEC([at_ns1], [ip route add 10.1.1.0/24 via 10.2.1.1])
+
+dnl Solely for debugging when things go wrong
+NS_EXEC([at_ns0], [tcpdump -l -n -xx -U -i p0 -w p0.pcap >tcpdump.out 2>/dev/null &])
+NS_EXEC([at_ns1], [tcpdump -l -n -xx -U -i p1 -w p1.pcap >tcpdump.out 2>/dev/null &])
+
+AT_DATA([flows.txt], [dnl
+table=0,arp,actions=normal
+table=0,ct_state=-trk,ip,in_port=ovs-p0, actions=ct(table=1, nat)
+table=0,ct_state=-trk,ip,in_port=ovs-p1, actions=ct(table=1, nat)
+table=1,ct_state=+trk+new,ip,in_port=ovs-p0, actions=ct(commit, nat(src=10.1.1.1)),ovs-p1
+table=1,ct_state=+trk+est,ip,in_port=ovs-p0, actions=ovs-p1
+table=1,ct_state=+trk+est,ip,in_port=ovs-p1, actions=ovs-p0
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+
+dnl Check connectivity
+NS_CHECK_EXEC([at_ns0], [ping -c 1 10.1.1.2 -M dont -s 4500 | FORMAT_PING], [0], [dnl
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([conntrack - resubmit to ct multiple times])
 CHECK_CONNTRACK()
 
@@ -4379,6 +4617,52 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+
+AT_SETUP([conntrack - all-zero IP SNAT])
+AT_SKIP_IF([test $HAVE_NC = no])
+CHECK_CONNTRACK()
+CHECK_CONNTRACK_ZEROIP_SNAT()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+NS_CHECK_EXEC([at_ns0], [ip route add 172.1.1.0/24 via 10.1.1.2])
+
+OVS_START_L7([at_ns1], [http])
+
+AT_DATA([flows.txt], [dnl
+table=0,priority=30,ct_state=-trk,ip,action=ct(table=0)
+table=0,priority=20,ct_state=-rpl,ip,nw_dst=10.1.1.0/24,actions=ct(commit,nat(src=0.0.0.0),table=10)
+table=0,priority=20,ct_state=+rpl,ip,nw_dst=10.1.1.0/24,actions=resubmit(,10)
+table=0,priority=20,ip,nw_dst=172.1.1.2,actions=ct(commit,nat(dst=10.1.1.2),table=10)
+table=0,priority=10,arp,action=normal
+table=0,priority=1,action=drop
+table=10,priority=20,ct_state=+rpl,ip,nw_dst=10.1.1.0/24 actions=ct(table=20,nat)
+table=10,priority=10,ip,nw_dst=10.1.1.0/24 actions=resubmit(,20)
+table=20,priority=10,ip,nw_dst=10.1.1.1,action=1
+table=20,priority=10,ip,nw_dst=10.1.1.2,action=2
+])
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+dnl - Test to make sure src nat is NOT done when not needed
+NS_CHECK_EXEC([at_ns0], [echo "TEST" | nc -p 30000 10.1.1.2 80 > nc-1.log])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=10\.1\.1\.1,"], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=30000,dport=80),reply=(src=10.1.1.2,dst=10.1.1.1,sport=80,dport=30000),protoinfo=(state=TIME_WAIT)
+])
+
+dnl - Test to make sure src nat is done when needed
+NS_CHECK_EXEC([at_ns0], [echo "TEST2" | nc -p 30001 172.1.1.2 80 > nc-2.log])
+NS_CHECK_EXEC([at_ns0], [echo "TEST3" | nc -p 30001 10.1.1.2 80 > nc-3.log])
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep 30001 | grep "orig=.src=10\.1\.1\.1," | sed -e 's/port=30001/port=<clnt_s_port>/g' -e 's/sport=80,dport=[[0-9]]\+/sport=80,dport=<rnd_port>/g' | sort], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<clnt_s_port>,dport=80),reply=(src=10.1.1.2,dst=10.1.1.1,sport=80,dport=<rnd_port>),protoinfo=(state=TIME_WAIT)
+tcp,orig=(src=10.1.1.1,dst=172.1.1.2,sport=<clnt_s_port>,dport=80),reply=(src=10.1.1.2,dst=10.1.1.1,sport=80,dport=<clnt_s_port>),protoinfo=(state=TIME_WAIT)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+
 AT_SETUP([conntrack - simple DNAT])
 CHECK_CONNTRACK()
 CHECK_CONNTRACK_NAT()
@@ -4434,6 +4718,41 @@ tcp,orig=(src=10.1.1.1,dst=10.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([conntrack - DNAT with additional SNAT])
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+NS_CHECK_EXEC([at_ns0], [ip route add 172.1.1.0/24 via 10.1.1.2])
+
+OVS_START_L7([at_ns1], [http])
+
+AT_DATA([flows.txt], [dnl
+table=0,priority=30,in_port=1,ip,nw_dst=172.1.1.2,actions=ct(commit,nat(dst=10.1.1.2:80),table=1)
+table=0,priority=20,in_port=2,ip,actions=ct(nat),1
+table=0,priority=10,arp,actions=NORMAL
+table=0,priority=1,actions=drop
+dnl Be sure all ct() actions but src nat are executed
+table=1,ip,actions=ct(commit,nat(src=10.1.1.240),exec(set_field:0xac->ct_mark,set_field:0xac->ct_label),table=2)
+table=2,in_port=1,ip,ct_mark=0xac,ct_label=0xac,actions=2
+])
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+NS_CHECK_EXEC([at_ns0], [wget http://172.1.1.2:8080 -t 5 -T 1 --retry-connrefused -v -o wget0.log])
+
+dnl - make sure only dst nat has been performed
+AT_CHECK([ovs-appctl dpctl/dump-conntrack |  FORMAT_CT(10.1.1.240)], [0], [dnl
+])
+
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1.1)], [0], [dnl
+tcp,orig=(src=10.1.1.1,dst=172.1.1.2,sport=<cleared>,dport=<cleared>),reply=(src=10.1.1.2,dst=10.1.1.1,sport=<cleared>,dport=<cleared>),mark=172,labels=0xac,protoinfo=(state=<cleared>)
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([conntrack - more complex DNAT])
 CHECK_CONNTRACK()
 CHECK_CONNTRACK_NAT()
@@ -5873,6 +6192,50 @@ ovs-appctl dpif/dump-flows br0
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([conntrack - Multiple ICMP traverse])
+dnl This tracks sending ICMP packets via conntrack multiple times for the
+dnl same packet
+CHECK_CONNTRACK()
+OVS_TRAFFIC_VSWITCHD_START()
+OVS_CHECK_CT_CLEAR()
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
+dnl setup ct flows
+AT_DATA([flows.txt], [dnl
+table=0,priority=10  ip,icmp,ct_state=-trk action=ct(zone=1,table=1)
+table=0,priority=0   action=drop
+table=1,priority=10  ct_state=-est+trk+new,ip,ct_zone=1,in_port=1 action=ct(commit,table=2)
+table=1,priority=10  ct_state=+est-new+trk,ct_zone=1,in_port=1 action=resubmit(,2)
+table=1,priority=0   action=drop
+table=2,priority=10  ct_state=+trk+new,in_port=1 action=drop
+table=2,priority=10  ct_state=+trk+est action=drop
+])
+
+AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
+
+# sending icmp pkts, first and second
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 1c 00 01 00 00 40 01 64 dc 0a 01 01 01 0a 01 01 02 08 00 f7 ff ff ff ff ff > /dev/null])
+
+NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 1c 00 01 00 00 40 01 64 dc 0a 01 01 01 0a 01 01 02 08 00 f7 ff ff ff ff ff > /dev/null])
+
+sleep 1
+
+dnl ensure CT picked up the packet
+AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
+icmp,orig=(src=10.1.1.1,dst=10.1.1.2,id=<cleared>,type=8,code=0),reply=(src=10.1.1.2,dst=10.1.1.1,id=<cleared>,type=0,code=0)
+])
+
+AT_CHECK([ovs-ofctl dump-flows br0 | grep table=2, | OFPROTO_CLEAR_DURATION_IDLE],
+         [0], [dnl
+ cookie=0x0, duration=<cleared>, table=2, n_packets=2, n_bytes=84, idle_age=<cleared>, priority=10,ct_state=+new+trk,in_port=1 actions=drop
+ cookie=0x0, duration=<cleared>, table=2, n_packets=0, n_bytes=0, idle_age=<cleared>, priority=10,ct_state=+est+trk actions=drop
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_BANNER([802.1ad])
 
 AT_SETUP([802.1ad - vlan_limit])
diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at
index ba7f4102f4..5c96f943df 100644
--- a/tests/system-userspace-macros.at
+++ b/tests/system-userspace-macros.at
@@ -96,6 +96,16 @@ m4_define([CHECK_CONNTRACK_FRAG_OVERLAP])
 #
 m4_define([CHECK_CONNTRACK_NAT])
 
+# CHECK_CONNTRACK_ZEROIP_SNAT()
+#
+# Perform requirements checks for running conntrack all-zero IP SNAT tests.
+# The userspace datapath does not support all-zero IP SNAT.
+#
+m4_define([CHECK_CONNTRACK_ZEROIP_SNAT],
+[
+    AT_SKIP_IF([:])
+])
+
 # CHECK_CONNTRACK_TIMEOUT()
 #
 # Perform requirements checks for running conntrack customized timeout tests.
diff --git a/tests/system-userspace-packet-type-aware.at b/tests/system-userspace-packet-type-aware.at
index c2246316de..974304758f 100644
--- a/tests/system-userspace-packet-type-aware.at
+++ b/tests/system-userspace-packet-type-aware.at
@@ -129,6 +129,7 @@ AT_CHECK([
     ip addr add 10.0.0.1/24 dev br-p1
     ip link set br-p1 up
 ], [0], [stdout])
+OVS_WAIT_UNTIL([ovs-appctl ovs/route/show | grep -q br-p1])
 
 AT_CHECK([
     ovs-appctl ovs/route/add 10.0.0.0/24 br-p1
@@ -141,6 +142,7 @@ AT_CHECK([
     ip addr add 20.0.0.2/24 dev br-p2
     ip link set br-p2 up
 ], [0], [stdout])
+OVS_WAIT_UNTIL([ovs-appctl ovs/route/show | grep -q br-p2])
 
 AT_CHECK([
     ovs-appctl ovs/route/add 20.0.0.0/24 br-p2
@@ -153,6 +155,7 @@ AT_CHECK([
     ip addr add 30.0.0.3/24 dev br-p3
     ip link set br-p3 up
 ], [0], [stdout])
+OVS_WAIT_UNTIL([ovs-appctl ovs/route/show | grep -q br-p3])
 
 AT_CHECK([
     ovs-appctl ovs/route/add 30.0.0.0/24 br-p3
diff --git a/tests/system-userspace-testsuite.at b/tests/system-userspace-testsuite.at
index b40da9579e..2e9659a675 100644
--- a/tests/system-userspace-testsuite.at
+++ b/tests/system-userspace-testsuite.at
@@ -26,3 +26,4 @@ m4_include([tests/system-traffic.at])
 m4_include([tests/system-layer3-tunnels.at])
 m4_include([tests/system-interface.at])
 m4_include([tests/system-userspace-packet-type-aware.at])
+m4_include([tests/system-route.at])
diff --git a/tests/test-classifier.c b/tests/test-classifier.c
index 6d53d016de..2d98fad485 100644
--- a/tests/test-classifier.c
+++ b/tests/test-classifier.c
@@ -512,8 +512,9 @@ verify_tries(struct classifier *cls)
     int i;
 
     for (i = 0; i < cls->n_tries; i++) {
-        n_rules += trie_verify(&cls->tries[i].root, 0,
-                               cls->tries[i].field->n_bits);
+        const struct mf_field * cls_field
+            = ovsrcu_get(struct mf_field *, &cls->tries[i].field);
+        n_rules += trie_verify(&cls->tries[i].root, 0, cls_field->n_bits);
     }
     assert(n_rules <= cls->n_rules);
 }
diff --git a/tests/test-conntrack.c b/tests/test-conntrack.c
index f77ee75e38..da1ac63b6c 100644
--- a/tests/test-conntrack.c
+++ b/tests/test-conntrack.c
@@ -82,6 +82,7 @@ ct_thread_main(void *aux_)
 {
     struct thread_aux *aux = aux_;
     struct dp_packet_batch *pkt_batch;
+    struct dp_packet *pkt;
     ovs_be16 dl_type;
     size_t i;
     long long now = time_msec();
@@ -91,6 +92,9 @@ ct_thread_main(void *aux_)
     for (i = 0; i < n_pkts; i += batch_size) {
         conntrack_execute(ct, pkt_batch, dl_type, false, true, 0, NULL, NULL,
                           0, 0, NULL, NULL, now);
+        DP_PACKET_BATCH_FOR_EACH (j, pkt, pkt_batch) {
+            pkt_metadata_init_conn(&pkt->md);
+        }
     }
     ovs_barrier_block(&barrier);
     destroy_packets(pkt_batch);
diff --git a/tests/test-jsonrpc.py b/tests/test-jsonrpc.py
index 3eabcd78d5..1df5afa221 100644
--- a/tests/test-jsonrpc.py
+++ b/tests/test-jsonrpc.py
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import argparse
 import errno
 import os
diff --git a/tests/test-l7.py b/tests/test-l7.py
index d7854a1df3..32a77392c6 100755
--- a/tests/test-l7.py
+++ b/tests/test-l7.py
@@ -1,5 +1,5 @@
-#!/usr/bin/env python
-# Copyright (c) 2015, 2016 Nicira, Inc.
+#!/usr/bin/env python3
+# Copyright (c) 2015, 2016, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index b1a4be36bb..a886f971e7 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <getopt.h>
 #include <inttypes.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -52,6 +53,8 @@
 #include "util.h"
 #include "openvswitch/vlog.h"
 
+VLOG_DEFINE_THIS_MODULE(test_ovsdb);
+
 struct test_ovsdb_pvt_context {
     bool track;
 };
@@ -1844,164 +1847,319 @@ compare_link1(const void *a_, const void *b_)
     return a->i < b->i ? -1 : a->i > b->i;
 }
 
+static void OVS_PRINTF_FORMAT(1, 2)
+print_and_log(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    char *message = xvasprintf(format, args);
+    va_end(args);
+
+    printf("%s\n", message);
+    VLOG_INFO("%s", message);
+
+    free(message);
+}
+
+static char *
+format_idl_row(const struct ovsdb_idl_row *row, int step, const char *contents)
+{
+    const char *change_str =
+        !ovsdb_idl_track_is_set(row->table)
+        ? ""
+        : ovsdb_idl_row_get_seqno(row, OVSDB_IDL_CHANGE_INSERT) > 0
+          ? "inserted row: "
+          : ovsdb_idl_row_get_seqno(row, OVSDB_IDL_CHANGE_DELETE) > 0
+            ? "deleted row: "
+            : "";
+
+    return xasprintf("%03d: table %s: %s%s uuid=" UUID_FMT,
+                     step, row->table->class_->name, change_str, contents,
+                     UUID_ARGS(&row->uuid));
+}
+
 static void
 print_idl_row_updated_simple(const struct idltest_simple *s, int step)
 {
-    size_t i;
-    bool updated = false;
-
-    for (i = 0; i < IDLTEST_SIMPLE_N_COLUMNS; i++) {
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_SIMPLE_N_COLUMNS; i++) {
         if (idltest_simple_is_updated(s, i)) {
-            if (!updated) {
-                printf("%03d: updated columns:", step);
-                updated = true;
-            }
-            printf(" %s", idltest_simple_columns[i].name);
+            ds_put_format(&updates, " %s", idltest_simple_columns[i].name);
         }
     }
-    if (updated) {
-        printf("\n");
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, s->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
     }
 }
 
 static void
 print_idl_row_updated_link1(const struct idltest_link1 *l1, int step)
 {
-    size_t i;
-    bool updated = false;
-
-    for (i = 0; i < IDLTEST_LINK1_N_COLUMNS; i++) {
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_LINK1_N_COLUMNS; i++) {
         if (idltest_link1_is_updated(l1, i)) {
-            if (!updated) {
-                printf("%03d: updated columns:", step);
-                updated = true;
-            }
-            printf(" %s", idltest_link1_columns[i].name);
+            ds_put_format(&updates, " %s", idltest_link1_columns[i].name);
         }
     }
-    if (updated) {
-        printf("\n");
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, l1->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
     }
 }
 
 static void
 print_idl_row_updated_link2(const struct idltest_link2 *l2, int step)
 {
-    size_t i;
-    bool updated = false;
-
-    for (i = 0; i < IDLTEST_LINK2_N_COLUMNS; i++) {
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_LINK2_N_COLUMNS; i++) {
         if (idltest_link2_is_updated(l2, i)) {
-            if (!updated) {
-                printf("%03d: updated columns:", step);
-                updated = true;
-            }
-            printf(" %s", idltest_link2_columns[i].name);
+            ds_put_format(&updates, " %s", idltest_link2_columns[i].name);
         }
     }
-    if (updated) {
-        printf("\n");
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, l2->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
     }
 }
 
 static void
-print_idl_row_updated_singleton(const struct idltest_singleton *sng, int step)
+print_idl_row_updated_simple3(const struct idltest_simple3 *s3, int step)
 {
-    size_t i;
-    bool updated = false;
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_SIMPLE3_N_COLUMNS; i++) {
+        if (idltest_simple3_is_updated(s3, i)) {
+            ds_put_format(&updates, " %s", idltest_simple3_columns[i].name);
+        }
+    }
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, s3->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
+    }
+}
+
+static void
+print_idl_row_updated_simple4(const struct idltest_simple4 *s4, int step)
+{
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_SIMPLE4_N_COLUMNS; i++) {
+        if (idltest_simple4_is_updated(s4, i)) {
+            ds_put_format(&updates, " %s", idltest_simple4_columns[i].name);
+        }
+    }
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, s4->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
+    }
+}
 
-    for (i = 0; i < IDLTEST_SINGLETON_N_COLUMNS; i++) {
+static void
+print_idl_row_updated_simple6(const struct idltest_simple6 *s6, int step)
+{
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_SIMPLE6_N_COLUMNS; i++) {
+        if (idltest_simple6_is_updated(s6, i)) {
+            ds_put_format(&updates, " %s", idltest_simple6_columns[i].name);
+        }
+    }
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, s6->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
+    }
+}
+
+static void
+print_idl_row_updated_singleton(const struct idltest_singleton *sng, int step)
+{
+    struct ds updates = DS_EMPTY_INITIALIZER;
+    for (size_t i = 0; i < IDLTEST_SINGLETON_N_COLUMNS; i++) {
         if (idltest_singleton_is_updated(sng, i)) {
-            if (!updated) {
-                printf("%03d: updated columns:", step);
-                updated = true;
-            }
-            printf(" %s", idltest_singleton_columns[i].name);
+            ds_put_format(&updates, " %s", idltest_singleton_columns[i].name);
         }
     }
-    if (updated) {
-        printf("\n");
+    if (updates.length) {
+        print_and_log("%03d: table %s: updated columns:%s",
+                      step, sng->header_.table->class_->name,
+                      ds_cstr(&updates));
+        ds_destroy(&updates);
     }
 }
 
 static void
 print_idl_row_simple(const struct idltest_simple *s, int step)
 {
-    size_t i;
-
-    printf("%03d: i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[",
-           step, s->i, s->r, s->b ? "true" : "false",
-           s->s, UUID_ARGS(&s->u));
-    for (i = 0; i < s->n_ia; i++) {
-        printf("%s%"PRId64, i ? " " : "", s->ia[i]);
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    ds_put_format(&msg, "i=%"PRId64" r=%g b=%s s=%s u="UUID_FMT" ia=[",
+                  s->i, s->r, s->b ? "true" : "false",
+                  s->s, UUID_ARGS(&s->u));
+    for (size_t i = 0; i < s->n_ia; i++) {
+        ds_put_format(&msg, "%s%"PRId64, i ? " " : "", s->ia[i]);
     }
-    printf("] ra=[");
-    for (i = 0; i < s->n_ra; i++) {
-        printf("%s%g", i ? " " : "", s->ra[i]);
+    ds_put_cstr(&msg, "] ra=[");
+    for (size_t i = 0; i < s->n_ra; i++) {
+        ds_put_format(&msg, "%s%g", i ? " " : "", s->ra[i]);
     }
-    printf("] ba=[");
-    for (i = 0; i < s->n_ba; i++) {
-        printf("%s%s", i ? " " : "", s->ba[i] ? "true" : "false");
+    ds_put_cstr(&msg, "] ba=[");
+    for (size_t i = 0; i < s->n_ba; i++) {
+        ds_put_format(&msg, "%s%s", i ? " " : "", s->ba[i] ? "true" : "false");
     }
-    printf("] sa=[");
-    for (i = 0; i < s->n_sa; i++) {
-        printf("%s%s", i ? " " : "", s->sa[i]);
+    ds_put_cstr(&msg, "] sa=[");
+    for (size_t i = 0; i < s->n_sa; i++) {
+        ds_put_format(&msg, "%s%s", i ? " " : "", s->sa[i]);
     }
-    printf("] ua=[");
-    for (i = 0; i < s->n_ua; i++) {
-        printf("%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i]));
+    ds_put_cstr(&msg, "] ua=[");
+    for (size_t i = 0; i < s->n_ua; i++) {
+        ds_put_format(&msg, "%s"UUID_FMT, i ? " " : "", UUID_ARGS(&s->ua[i]));
     }
-    printf("] uuid="UUID_FMT"\n", UUID_ARGS(&s->header_.uuid));
+    ds_put_cstr(&msg, "]");
+
+    char *row_msg = format_idl_row(&s->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
     print_idl_row_updated_simple(s, step);
 }
 
 static void
 print_idl_row_link1(const struct idltest_link1 *l1, int step)
 {
-    struct idltest_link1 **links;
-    size_t i;
-
-    printf("%03d: i=%"PRId64" k=", step, l1->i);
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    ds_put_format(&msg, "i=%"PRId64" k=", l1->i);
     if (l1->k) {
-        printf("%"PRId64, l1->k->i);
+        ds_put_format(&msg, "%"PRId64, l1->k->i);
     }
-    printf(" ka=[");
-    links = xmemdup(l1->ka, l1->n_ka * sizeof *l1->ka);
+    ds_put_cstr(&msg, " ka=[");
+    struct idltest_link1 **links = xmemdup(l1->ka, l1->n_ka * sizeof *l1->ka);
     qsort(links, l1->n_ka, sizeof *links, compare_link1);
-    for (i = 0; i < l1->n_ka; i++) {
-        printf("%s%"PRId64, i ? " " : "", links[i]->i);
+    for (size_t i = 0; i < l1->n_ka; i++) {
+        ds_put_format(&msg, "%s%"PRId64, i ? " " : "", links[i]->i);
     }
     free(links);
-    printf("] l2=");
+    ds_put_cstr(&msg, "] l2=");
     if (l1->l2) {
-        printf("%"PRId64, l1->l2->i);
+        ds_put_format(&msg, "%"PRId64, l1->l2->i);
     }
-    printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l1->header_.uuid));
+
+    char *row_msg = format_idl_row(&l1->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
     print_idl_row_updated_link1(l1, step);
 }
 
 static void
 print_idl_row_link2(const struct idltest_link2 *l2, int step)
 {
-    printf("%03d: i=%"PRId64" l1=", step, l2->i);
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    ds_put_format(&msg, "i=%"PRId64" l1=", l2->i);
     if (l2->l1) {
-        printf("%"PRId64, l2->l1->i);
+        ds_put_format(&msg, "%"PRId64, l2->l1->i);
     }
-    printf(" uuid="UUID_FMT"\n", UUID_ARGS(&l2->header_.uuid));
+
+    char *row_msg = format_idl_row(&l2->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
     print_idl_row_updated_link2(l2, step);
 }
 
+static void
+print_idl_row_simple3(const struct idltest_simple3 *s3, int step)
+{
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    size_t i;
+
+    ds_put_format(&msg, "name=%s uset=[", s3->name);
+    for (i = 0; i < s3->n_uset; i++) {
+        ds_put_format(&msg, UUID_FMT"%s",
+                      UUID_ARGS(&s3->uset[i]),
+                      i < s3->n_uset - 1 ? "," : "");
+    }
+    ds_put_cstr(&msg, "] uref=[");
+    for (i = 0; i < s3->n_uref; i++) {
+        ds_put_format(&msg, UUID_FMT"%s",
+                      UUID_ARGS(&s3->uref[i]->header_.uuid),
+                      i < s3->n_uref -1 ? "," : "");
+    }
+    ds_put_cstr(&msg, "]");
+
+    char *row_msg = format_idl_row(&s3->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
+    print_idl_row_updated_simple3(s3, step);
+}
+
+static void
+print_idl_row_simple4(const struct idltest_simple4 *s4, int step)
+{
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    ds_put_format(&msg, "name=%s", s4->name);
+
+    char *row_msg = format_idl_row(&s4->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
+    print_idl_row_updated_simple4(s4, step);
+}
+
+static void
+print_idl_row_simple6(const struct idltest_simple6 *s6, int step)
+{
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    ds_put_format(&msg, "name=%s ", s6->name);
+    ds_put_cstr(&msg, "weak_ref=[");
+    for (size_t i = 0; i < s6->n_weak_ref; i++) {
+        ds_put_format(&msg, "%s"UUID_FMT, i ? " " : "",
+                      UUID_ARGS(&s6->weak_ref[i]->header_.uuid));
+    }
+    ds_put_cstr(&msg, "]");
+
+    char *row_msg = format_idl_row(&s6->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
+    print_idl_row_updated_simple6(s6, step);
+}
+
 static void
 print_idl_row_singleton(const struct idltest_singleton *sng, int step)
 {
-    printf("%03d: name=%s", step, sng->name);
-    printf(" uuid="UUID_FMT"\n", UUID_ARGS(&sng->header_.uuid));
+    struct ds msg = DS_EMPTY_INITIALIZER;
+    ds_put_format(&msg, "name=%s", sng->name);
+
+    char *row_msg = format_idl_row(&sng->header_, step, ds_cstr(&msg));
+    print_and_log("%s", row_msg);
+    ds_destroy(&msg);
+    free(row_msg);
+
     print_idl_row_updated_singleton(sng, step);
 }
 
 static void
 print_idl(struct ovsdb_idl *idl, int step)
 {
+    const struct idltest_simple3 *s3;
+    const struct idltest_simple4 *s4;
+    const struct idltest_simple6 *s6;
     const struct idltest_simple *s;
     const struct idltest_link1 *l1;
     const struct idltest_link2 *l2;
@@ -2020,49 +2178,65 @@ print_idl(struct ovsdb_idl *idl, int step)
         print_idl_row_link2(l2, step);
         n++;
     }
+    IDLTEST_SIMPLE3_FOR_EACH (s3, idl) {
+        print_idl_row_simple3(s3, step);
+        n++;
+    }
+    IDLTEST_SIMPLE4_FOR_EACH (s4, idl) {
+        print_idl_row_simple4(s4, step);
+        n++;
+    }
+    IDLTEST_SIMPLE6_FOR_EACH (s6, idl) {
+        print_idl_row_simple6(s6, step);
+        n++;
+    }
     IDLTEST_SINGLETON_FOR_EACH (sng, idl) {
         print_idl_row_singleton(sng, step);
         n++;
     }
     if (!n) {
-        printf("%03d: empty\n", step);
+        print_and_log("%03d: empty", step);
     }
 }
 
 static void
-print_idl_track(struct ovsdb_idl *idl, int step, unsigned int seqno)
+print_idl_track(struct ovsdb_idl *idl, int step)
 {
+    const struct idltest_simple3 *s3;
+    const struct idltest_simple4 *s4;
+    const struct idltest_simple6 *s6;
     const struct idltest_simple *s;
     const struct idltest_link1 *l1;
     const struct idltest_link2 *l2;
     int n = 0;
 
     IDLTEST_SIMPLE_FOR_EACH_TRACKED (s, idl) {
-        if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) {
-            printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid));
-        } else {
-            print_idl_row_simple(s, step);
-        }
+        print_idl_row_simple(s, step);
         n++;
     }
     IDLTEST_LINK1_FOR_EACH_TRACKED (l1, idl) {
-        if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) {
-            printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid));
-        } else {
-            print_idl_row_link1(l1, step);
-        }
+        print_idl_row_link1(l1, step);
         n++;
     }
     IDLTEST_LINK2_FOR_EACH_TRACKED (l2, idl) {
-        if (idltest_simple_row_get_seqno(s, OVSDB_IDL_CHANGE_DELETE) >= seqno) {
-            printf("%03d: ##deleted## uuid="UUID_FMT"\n", step, UUID_ARGS(&s->header_.uuid));
-        } else {
-            print_idl_row_link2(l2, step);
-        }
+        print_idl_row_link2(l2, step);
         n++;
     }
+    IDLTEST_SIMPLE3_FOR_EACH_TRACKED (s3, idl) {
+        print_idl_row_simple3(s3, step);
+        n++;
+    }
+    IDLTEST_SIMPLE4_FOR_EACH_TRACKED (s4, idl) {
+        print_idl_row_simple4(s4, step);
+        n++;
+    }
+    IDLTEST_SIMPLE6_FOR_EACH_TRACKED (s6, idl) {
+        print_idl_row_simple6(s6, step);
+        n++;
+    }
+
     if (!n) {
-        printf("%03d: empty\n", step);
+        print_and_log("%03d: empty", step);
     }
 }
 
@@ -2251,7 +2425,7 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
             ovsdb_idl_check_consistency(idl);
             break;
         } else if (!strcmp(name, "destroy")) {
-            printf("%03d: destroy\n", step);
+            print_and_log("%03d: destroy", step);
             ovsdb_idl_txn_destroy(txn);
             ovsdb_idl_check_consistency(idl);
             return;
@@ -2262,13 +2436,17 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
     }
 
     status = ovsdb_idl_txn_commit_block(txn);
-    printf("%03d: commit, status=%s",
-           step, ovsdb_idl_txn_status_to_string(status));
+
+    struct ds s = DS_EMPTY_INITIALIZER;
+    ds_put_format(&s, "%03d: commit, status=%s",
+                  step, ovsdb_idl_txn_status_to_string(status));
     if (increment) {
-        printf(", increment=%"PRId64,
-               ovsdb_idl_txn_get_increment_new_value(txn));
+        ds_put_format(&s, ", increment=%"PRId64,
+                      ovsdb_idl_txn_get_increment_new_value(txn));
     }
-    putchar('\n');
+    print_and_log("%s", ds_cstr(&s));
+    ds_destroy(&s);
+
     ovsdb_idl_txn_destroy(txn);
     ovsdb_idl_check_consistency(idl);
 }
@@ -2282,6 +2460,12 @@ find_table_class(const char *name)
         return &idltest_table_link1;
     } else if (!strcmp(name, "link2")) {
         return &idltest_table_link2;
+    } else if (!strcmp(name, "simple3")) {
+        return &idltest_table_simple3;
+    } else if (!strcmp(name, "simple4")) {
+        return &idltest_table_simple4;
+    } else if (!strcmp(name, "simple6")) {
+        return &idltest_table_simple6;
     }
     return NULL;
 }
@@ -2391,6 +2575,10 @@ update_conditions(struct ovsdb_idl *idl, char *commands)
         if (seqno == next_seqno ) {
             ovs_fatal(0, "condition unchanged");
         }
+        unsigned int new_next_seqno = ovsdb_idl_set_condition(idl, tc, &cond);
+        if (next_seqno != new_next_seqno) {
+            ovs_fatal(0, "condition expected seqno changed");
+        }
         ovsdb_idl_condition_destroy(&cond);
         json_destroy(json);
     }
@@ -2436,7 +2624,7 @@ do_idl(struct ovs_cmdl_context *ctx)
     const char cond_s[] = "condition ";
     if (ctx->argc > 2 && strstr(ctx->argv[2], cond_s)) {
         update_conditions(idl, ctx->argv[2] + strlen(cond_s));
-        printf("%03d: change conditions\n", step++);
+        print_and_log("%03d: change conditions", step++);
         i = 3;
     } else {
         i = 2;
@@ -2465,7 +2653,7 @@ do_idl(struct ovs_cmdl_context *ctx)
 
             /* Print update. */
             if (track) {
-                print_idl_track(idl, step++, ovsdb_idl_get_seqno(idl));
+                print_idl_track(idl, step++);
                 ovsdb_idl_track_clear(idl);
             } else {
                 print_idl(idl, step++);
@@ -2474,11 +2662,11 @@ do_idl(struct ovs_cmdl_context *ctx)
         seqno = ovsdb_idl_get_seqno(idl);
 
         if (!strcmp(arg, "reconnect")) {
-            printf("%03d: reconnect\n", step++);
+            print_and_log("%03d: reconnect", step++);
             ovsdb_idl_force_reconnect(idl);
         }  else if (!strncmp(arg, cond_s, strlen(cond_s))) {
             update_conditions(idl, arg + strlen(cond_s));
-            printf("%03d: change conditions\n", step++);
+            print_and_log("%03d: change conditions", step++);
         } else if (arg[0] != '[') {
             idl_set(idl, arg, step++);
         } else {
@@ -2489,13 +2677,17 @@ do_idl(struct ovs_cmdl_context *ctx)
             if (error || reply->error) {
                 ovs_fatal(error, "jsonrpc transaction failed");
             }
-            printf("%03d: ", step++);
             if (reply->result) {
                 parse_uuids(reply->result, symtab, &n_uuids);
             }
             json_destroy(reply->id);
             reply->id = NULL;
-            print_and_free_json(jsonrpc_msg_to_json(reply));
+
+            struct json *msg_json = jsonrpc_msg_to_json(reply);
+            char *msg_s = json_to_string(msg_json, JSSF_SORT);
+            json_destroy(msg_json);
+            print_and_log("%03d: %s", step++, msg_s);
+            free(msg_s);
         }
     }
     ovsdb_symbol_table_destroy(symtab);
@@ -2515,7 +2707,7 @@ do_idl(struct ovs_cmdl_context *ctx)
     print_idl(idl, step++);
     ovsdb_idl_track_clear(idl);
     ovsdb_idl_destroy(idl);
-    printf("%03d: done\n", step);
+    print_and_log("%03d: done", step);
 }
 
 static void
@@ -2625,27 +2817,6 @@ do_idl_partial_update_map_column(struct ovs_cmdl_context *ctx)
     printf("%03d: End test\n", step);
 }
 
-static void
-print_idl_row_simple3(const struct idltest_simple3 *s, int step)
-{
-    size_t i;
-    const struct ovsdb_datum *uset;
-    const struct ovsdb_datum *uref;
-
-    uset = idltest_simple3_get_uset(s, OVSDB_TYPE_UUID);
-    printf("%03d: name=%s uset=[",
-           step, s->name);
-    for (i = 0; i < uset->n; i++) {
-        printf("["UUID_FMT"]%s", UUID_ARGS(&(uset->keys[i].uuid)), i < uset->n-1? ",": "");
-    }
-    uref = idltest_simple3_get_uref(s, OVSDB_TYPE_UUID);
-    printf("] uref=[");
-    for (i = 0; i < uref->n; i++) {
-        printf("["UUID_FMT"]%s", UUID_ARGS(&(uref->keys[i].uuid)), i < uref->n-1? ",": "");
-    }
-    printf("]\n");
-}
-
 static void
 dump_simple3(struct ovsdb_idl *idl,
              const struct idltest_simple3 *myRow,
diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
index 1b94b79a07..72a319123e 100644
--- a/tests/test-ovsdb.py
+++ b/tests/test-ovsdb.py
@@ -28,6 +28,7 @@ import ovs.util
 import ovs.vlog
 from ovs.db import data
 from ovs.db import error
+from ovs.db.idl import _row_to_uuid as row_to_uuid
 from ovs.fatal_signal import signal_alarm
 
 vlog = ovs.vlog.Vlog("test-ovsdb")
@@ -159,7 +160,12 @@ def get_simple_printable_row_string(row, columns):
                                          is ovs.db.data.Atom):
             value = getattr(row, column)
             if isinstance(value, dict):
-                value = sorted(value.items())
+                value = sorted((row_to_uuid(k), row_to_uuid(v))
+                               for k, v in value.items())
+            if isinstance(value, (list, tuple)):
+                value = sorted((row_to_uuid(v) for v in value))
+            elif isinstance(value, list):
+                value = sorted(row_to_uuid(v) for v in value)
             s += "%s=%s " % (column, value)
     s = s.strip()
     s = re.sub('""|,|u?\'', "", s)
@@ -170,9 +176,10 @@ def get_simple_printable_row_string(row, columns):
     return s
 
 
-def get_simple_table_printable_row(row):
+def get_simple_table_printable_row(row, *additional_columns):
     simple_columns = ["i", "r", "b", "s", "u", "ia",
-                      "ra", "ba", "sa", "ua", "uuid"]
+                      "ra", "ba", "sa", "ua"]
+    simple_columns.extend(additional_columns)
     return get_simple_printable_row_string(row, simple_columns)
 
 
@@ -182,73 +189,118 @@ def get_simple2_table_printable_row(row):
 
 
 def get_simple3_table_printable_row(row):
-    simple3_columns = ["name", "uset"]
+    simple3_columns = ["name", "uset", "uref"]
     return get_simple_printable_row_string(row, simple3_columns)
 
 
+def get_simple4_table_printable_row(row):
+    simple4_columns = ["name"]
+    return get_simple_printable_row_string(row, simple4_columns)
+
+
+def get_simple5_table_printable_row(row):
+    simple5_columns = ["name", "irefmap"]
+    return get_simple_printable_row_string(row, simple5_columns)
+
+
+def get_simple6_table_printable_row(row):
+    simple6_columns = ["name", "weak_ref"]
+    return get_simple_printable_row_string(row, simple6_columns)
+
+
+def get_link1_table_printable_row(row):
+    s = ["i=%s k=" % row.i]
+    if hasattr(row, "k") and row.k:
+        s.append(str(row.k.i))
+    if hasattr(row, "ka"):
+        s.append(" ka=[")
+        s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
+        s.append("] l2=")
+    if hasattr(row, "l2") and row.l2:
+        s.append(str(row.l2[0].i))
+    return ''.join(s)
+
+
+def get_link2_table_printable_row(row):
+    s = "i=%s l1=" % row.i
+    if hasattr(row, "l1") and row.l1:
+        s += str(row.l1[0].i)
+    return s
+
+
+def get_singleton_table_printable_row(row):
+    return "name=%s" % row.name
+
+
+def print_row(table, row, step, contents):
+    s = "%03d: table %s: %s " % (step, table, contents)
+    s += get_simple_printable_row_string(row, ["uuid"])
+    print(s)
+
+
 def print_idl(idl, step):
     n = 0
     if "simple" in idl.tables:
         simple = idl.tables["simple"].rows
         for row in simple.values():
-            s = "%03d: " % step
-            s += get_simple_table_printable_row(row)
-            print(s)
+            print_row("simple", row, step,
+                      get_simple_table_printable_row(row))
             n += 1
 
     if "simple2" in idl.tables:
         simple2 = idl.tables["simple2"].rows
         for row in simple2.values():
-            s = "%03d: " % step
-            s += get_simple2_table_printable_row(row)
-            print(s)
+            print_row("simple2", row, step,
+                      get_simple2_table_printable_row(row))
             n += 1
 
     if "simple3" in idl.tables:
         simple3 = idl.tables["simple3"].rows
         for row in simple3.values():
-            s = "%03d: " % step
-            s += get_simple3_table_printable_row(row)
-            print(s)
+            print_row("simple3", row, step,
+                      get_simple3_table_printable_row(row))
+            n += 1
+
+    if "simple4" in idl.tables:
+        simple4 = idl.tables["simple4"].rows
+        for row in simple4.values():
+            print_row("simple4", row, step,
+                      get_simple4_table_printable_row(row))
+            n += 1
+
+    if "simple5" in idl.tables:
+        simple5 = idl.tables["simple5"].rows
+        for row in simple5.values():
+            print_row("simple5", row, step,
+                      get_simple5_table_printable_row(row))
+            n += 1
+
+    if "simple6" in idl.tables:
+        simple6 = idl.tables["simple6"].rows
+        for row in simple6.values():
+            print_row("simple6", row, step,
+                      get_simple6_table_printable_row(row))
             n += 1
 
     if "link1" in idl.tables:
         l1 = idl.tables["link1"].rows
         for row in l1.values():
-            s = ["%03d: i=%s k=" % (step, row.i)]
-            if hasattr(row, "k") and row.k:
-                s.append(str(row.k.i))
-            if hasattr(row, "ka"):
-                s.append(" ka=[")
-                s.append(' '.join(sorted(str(ka.i) for ka in row.ka)))
-                s.append("] l2=")
-            if hasattr(row, "l2") and row.l2:
-                s.append(str(row.l2[0].i))
-            if hasattr(row, "uuid"):
-                s.append(" uuid=%s" % row.uuid)
-            print(''.join(s))
+            print_row("link1", row, step,
+                      get_link1_table_printable_row(row))
             n += 1
 
     if "link2" in idl.tables:
         l2 = idl.tables["link2"].rows
         for row in l2.values():
-            s = ["%03d:" % step]
-            s.append(" i=%s l1=" % row.i)
-            if hasattr(row, "l1") and row.l1:
-                s.append(str(row.l1[0].i))
-            if hasattr(row, "uuid"):
-                s.append(" uuid=%s" % row.uuid)
-            print(''.join(s))
+            print_row("link2", row, step,
+                      get_link2_table_printable_row(row))
             n += 1
 
     if "singleton" in idl.tables:
         sng = idl.tables["singleton"].rows
         for row in sng.values():
-            s = ["%03d:" % step]
-            s.append(" name=%s" % row.name)
-            if hasattr(row, "uuid"):
-                s.append(" uuid=%s" % row.uuid)
-            print(''.join(s))
+            print_row("singleton", row, step,
+                      get_singleton_table_printable_row(row))
             n += 1
 
     if not n:
@@ -303,6 +355,11 @@ def idltest_find_simple3(idl, i):
     return next(idl.index_equal("simple3", "simple3_by_name", i), None)
 
 
+def idltest_find(idl, table, col, match):
+    return next((r for r in idl.tables[table].rows.values() if
+                getattr(r, col) == match), None)
+
+
 def idl_set(idl, commands, step):
     txn = ovs.db.idl.Transaction(idl)
     increment = False
@@ -524,6 +581,12 @@ def idl_set(idl, commands, step):
             setattr(new_row3, 'name', 'String3')
             new_row3.addvalue('uset', new_row41.uuid)
             assert len(getattr(new_row3, 'uset', [])) == 1
+        elif name == 'partialmapmutateirefmap':
+            row3 = idltest_find_simple3(idl, "myString1")
+            row5 = idltest_find(idl, "simple5", "name", "myString2")
+            row5.setkey('irefmap', 1, row3.uuid)
+            maplen = len(row5.irefmap)
+            assert maplen == 1, "expected 1, got %d" % maplen
         else:
             sys.stderr.write("unknown command %s\n" % name)
             sys.exit(1)
@@ -616,7 +679,8 @@ def do_idl(schema_file, remote, *commands):
     def mock_notify(event, row, updates=None):
         output = "%03d: " % step
         output += "event:" + str(event) + ", row={"
-        output += get_simple_table_printable_row(row) + "}, updates="
+        output += get_simple_table_printable_row(row, 'l2', 'l1') + "}, "
+        output += get_simple_printable_row_string(row, ["uuid"]) + ", updates="
         if updates is None:
             output += "None"
         else:
diff --git a/tests/test-reconnect.c b/tests/test-reconnect.c
index 5a14e7fe58..bf0463e25c 100644
--- a/tests/test-reconnect.c
+++ b/tests/test-reconnect.c
@@ -48,6 +48,7 @@ test_reconnect_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 
     now = 1000;
     reconnect = reconnect_create(now);
+    reconnect_receive_attempted(reconnect, LLONG_MAX);
     reconnect_set_name(reconnect, "remote");
     reconnect_get_stats(reconnect, now, &prev);
     printf("### t=%d ###\n", now);
diff --git a/tests/test-reconnect.py b/tests/test-reconnect.py
index 6cd052878e..ef669b0417 100644
--- a/tests/test-reconnect.py
+++ b/tests/test-reconnect.py
@@ -12,8 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import errno
 import sys
 
diff --git a/tests/test-sha1.c b/tests/test-sha1.c
index b7279db6aa..cc80888a7d 100644
--- a/tests/test-sha1.c
+++ b/tests/test-sha1.c
@@ -137,6 +137,42 @@ test_big_vector(void)
     free(vec.data);
 }
 
+static void
+test_huge_vector(void)
+{
+    enum { SIZE = 1000000000 };
+    struct test_vector vec = {
+        NULL, SIZE,
+        /* Computed by the sha1sum utility for a file with 10^9 symbols 'a'. */
+        { 0xD0, 0xF3, 0xE4, 0xF2, 0xF3, 0x1C, 0x66, 0x5A, 0xBB, 0xD8,
+          0xF5, 0x18, 0xE8, 0x48, 0xD5, 0xCB, 0x80, 0xCA, 0x78, 0xF7 }
+    };
+    int chunk = random_range(SIZE / 10000);
+    uint8_t md[SHA1_DIGEST_SIZE];
+    struct sha1_ctx sha1;
+    size_t i, sz;
+
+    /* It's not user-friendly to allocate 1GB of memory for a unit test,
+     * so we're allocating only a small chunk and re-using it. */
+    vec.data = xmalloc(chunk);
+    for (i = 0; i < chunk; i++) {
+        vec.data[i] = 'a';
+    }
+
+    sha1_init(&sha1);
+    for (sz = 0; sz < SIZE; sz += chunk) {
+        int n = sz + chunk < SIZE ? chunk : SIZE - sz;
+
+        sha1_update(&sha1, vec.data, n);
+    }
+    sha1_final(&sha1, md);
+    ovs_assert(!memcmp(md, vec.output, SHA1_DIGEST_SIZE));
+
+    free(vec.data);
+    putchar('.');
+    fflush(stdout);
+}
+
 static void
 test_shar1_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
@@ -147,6 +183,7 @@ test_shar1_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
     }
 
     test_big_vector();
+    test_huge_vector();
 
     putchar('\n');
 }
diff --git a/tests/test-stream.c b/tests/test-stream.c
index 4af44200e8..68ce2c5442 100644
--- a/tests/test-stream.c
+++ b/tests/test-stream.c
@@ -42,5 +42,6 @@ main(int argc, char *argv[])
         VLOG_ERR("stream_open_block(%s) failure: %s",
                  argv[1], ovs_strerror(error));
     }
+    stream_close(stream);
     return (error || !stream) ? 1 : 0;
 }
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index b92c23fde8..320ae5c9c2 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -573,6 +573,64 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 50540000000a5054000000091235 | wc
 OVS_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([tunnel_push_pop - packet_out debug_slow])
+
+OVS_VSWITCHD_START(
+    [add-port br0 p0 dnl
+     -- set Interface p0 type=dummy ofport_request=1 dnl
+                         other-config:hwaddr=aa:55:aa:55:00:00])
+AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg])
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy])
+AT_CHECK([ovs-vsctl add-port int-br t2 dnl
+          -- set Interface t2 type=geneve options:remote_ip=1.1.2.92 dnl
+                              options:key=123 ofport_request=2])
+
+dnl First setup dummy interface IP address, then add the route
+dnl so that tnl-port table can get valid IP address for the device.
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], [OK
+])
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+
+dnl This ARP reply from p0 has two effects:
+dnl 1. The ARP cache will learn that 1.1.2.92 is at f8:bc:12:44:34:b6.
+dnl 2. The br0 mac learning will learn that f8:bc:12:44:34:b6 is on p0.
+AT_CHECK([
+  ovs-appctl netdev-dummy/receive p0 dnl
+      'recirc_id(0),in_port(2),dnl
+       eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),dnl
+       arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'
+])
+
+AT_CHECK([ovs-vsctl -- set Interface p0 options:tx_pcap=p0.pcap])
+
+packet=50540000000a505400000009123
+dnl Source port is based on a packet hash, so it may differ depending on the
+dnl compiler flags and CPU type.  Masked with '....'.
+encap=f8bc124434b6aa55aa5500000800450000320000400040113406010102580101025c....17c1001e00000000655800007b00
+
+dnl Output to tunnel from a int-br internal port.
+dnl Checking that the packet arrived and it was correctly encapsulated.
+AT_CHECK([ovs-ofctl add-flow int-br "in_port=LOCAL,actions=debug_slow,output:2"])
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}4"])
+OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | egrep "${encap}${packet}4" | wc -l` -ge 1])
+dnl Sending again to exercise the non-miss upcall path.
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "${packet}4"])
+OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | egrep "${encap}${packet}4" | wc -l` -ge 2])
+
+dnl Output to tunnel from the controller.
+AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out int-br CONTROLLER "debug_slow,output:2" "${packet}5"])
+OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | egrep "${encap}${packet}5" | wc -l` -ge 1])
+
+dnl Datapath actions should not have tunnel push action.
+AT_CHECK([ovs-appctl dpctl/dump-flows | grep -q tnl_push], [1])
+dnl There should be slow_path action instead.
+AT_CHECK([ovs-appctl dpctl/dump-flows | grep -q 'slow_path(action)'], [0])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([tunnel_push_pop - underlay bridge match])
 
 OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
diff --git a/tests/tunnel.at b/tests/tunnel.at
index ce000a25e6..7a6b7f42c6 100644
--- a/tests/tunnel.at
+++ b/tests/tunnel.at
@@ -110,6 +110,35 @@ Datapath actions: drop
 OVS_VSWITCHD_STOP(["/dropping tunnel packet marked ECN CE but is not ECN capable/d"])
 AT_CLEANUP
 
+AT_SETUP([tunnel - too long nested attributes])
+OVS_VSWITCHD_START([add-port br0 p1 \
+    -- set Interface p1 type=gre options:remote_ip=1.1.1.1 ofport_request=1 \
+    -- add-port br0 p2 -- set Interface p2 type=dummy ofport_request=2])
+
+AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
+    br0 65534/100: (dummy-internal)
+    p1 1/1: (gre: remote_ip=1.1.1.1)
+    p2 2/2: (dummy)
+])
+
+dst_single="dst=1.1.1.1"
+dst_rep=${dst_single}
+dnl Size of one OVS_TUNNEL_KEY_ATTR_IPV4_DST is 4 bytes + NLA_HDRLEN (4 bytes).
+dnl One nested message has room for UINT16_MAX - NLA_HDRLEN (4) bytes, i.e.
+dnl (UINT16_MAX - NLA_HDRLEN) / (4 + NLA_HDRLEN) = 8191.375 of dst addresses.
+for i in `seq 1 8192` ; do
+    dst_rep="${dst_rep},${dst_single}"
+done
+
+AT_CHECK([ovs-appctl dpctl/add-flow "tunnel(${dst_rep})" "2" 2>&1 | dnl
+          sed "s/${dst_single},//g"], [], [dnl
+ovs-vswitchd: parsing flow key (syntax error at tunnel(dst=1.1.1.1)) (Argument list too long)
+ovs-appctl: ovs-vswitchd: server returned an error
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([tunnel - output])
 OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=gre \
                     options:remote_ip=1.1.1.1 options:local_ip=2.2.2.2 \
diff --git a/tests/uuidfilt.py b/tests/uuidfilt.py
index bc49aa480e..39679dd444 100755
--- a/tests/uuidfilt.py
+++ b/tests/uuidfilt.py
@@ -1,4 +1,20 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
+# Copyright (c) 2020 VMware, Inc.
+#
+# 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.
+# Breaks lines read from stdin into groups using blank lines as
+# group separators, then sorts lines within the groups for
+# reproducibility.
 
 import re
 import sys
diff --git a/utilities/bugtool/ovs-bugtool.in b/utilities/bugtool/ovs-bugtool.in
index e55bfc2ed5..987d211069 100755
--- a/utilities/bugtool/ovs-bugtool.in
+++ b/utilities/bugtool/ovs-bugtool.in
@@ -33,8 +33,7 @@
 # or func_output().
 #
 
-import StringIO
-import commands
+from io import BytesIO
 import fcntl
 import getopt
 import hashlib
@@ -48,7 +47,7 @@ import warnings
 import zipfile
 from select import select
 from signal import SIGTERM
-from subprocess import PIPE, Popen
+from subprocess import PIPE, Popen, check_output
 
 from xml.dom.minidom import getDOMImplementation, parse
 
@@ -348,7 +347,7 @@ def collect_data():
             cap = v['cap']
             if 'cmd_args' in v:
                 if 'output' not in v.keys():
-                    v['output'] = StringIOmtime()
+                    v['output'] = BytesIOmtime()
                 if v['repeat_count'] > 0:
                     if cap not in process_lists:
                         process_lists[cap] = []
@@ -373,20 +372,23 @@ def collect_data():
         if 'filename' in v and v['filename'].startswith('/proc/'):
             # proc files must be read into memory
             try:
-                f = open(v['filename'], 'r')
+                f = open(v['filename'], 'rb')
                 s = f.read()
                 f.close()
                 if check_space(cap, v['filename'], len(s)):
-                    v['output'] = StringIOmtime(s)
+                    v['output'] = BytesIOmtime(s)
             except:
                 pass
         elif 'func' in v:
             try:
                 s = v['func'](cap)
             except Exception as e:
-                s = str(e)
+                s = str(e).encode()
             if check_space(cap, k, len(s)):
-                v['output'] = StringIOmtime(s)
+                if isinstance(s, str):
+                    v['output'] = BytesIOmtime(s.encode())
+                else:
+                    v['output'] = BytesIOmtime(s)
 
 
 def main(argv=None):
@@ -682,8 +684,8 @@ exclude those logs from the archive.
         ovs_info_caps = [CAP_NETWORK_STATUS, CAP_SYSTEM_LOGS,
                          CAP_OPENVSWITCH_LOGS, CAP_NETWORK_CONFIG]
         ovs_info_list = ['process-tree']
-        # We cannot use iteritems, since we modify 'data' as we pass through
-        for (k, v) in data.items():
+        # We cannot use items(), since we modify 'data' as we pass through
+        for (k, v) in list(data.items()):
             cap = v['cap']
             if 'filename' in v:
                 info = k[0]
@@ -703,8 +705,8 @@ exclude those logs from the archive.
         pass
 
     # permit the user to filter out data
-    # We cannot use iteritems, since we modify 'data' as we pass through
-    for (k, v) in sorted(data.items()):
+    # We cannot use items(), since we modify 'data' as we pass through
+    for (k, v) in list(data.items()):
         cap = v['cap']
         if 'filename' in v:
             key = k[0]
@@ -721,7 +723,7 @@ exclude those logs from the archive.
 
     # include inventory
     data['inventory.xml'] = {'cap': None,
-                        'output': StringIOmtime(make_inventory(data, subdir))}
+                        'output': BytesIOmtime(make_inventory(data, subdir))}
 
     # create archive
     if output_fd == -1:
@@ -782,7 +784,7 @@ def dump_scsi_hosts(cap):
 
 
 def module_info(cap):
-    output = StringIO.StringIO()
+    output = BytesIO()
     modules = open(PROC_MODULES, 'r')
     procs = []
 
@@ -806,7 +808,7 @@ def multipathd_topology(cap):
 
 
 def dp_list():
-    output = StringIO.StringIO()
+    output = BytesIO()
     procs = [ProcOutput([OVS_DPCTL, 'dump-dps'],
              caps[CAP_NETWORK_STATUS][MAX_TIME], output)]
 
@@ -828,7 +830,7 @@ def collect_ovsdb():
             if os.path.isfile(OPENVSWITCH_COMPACT_DB):
                 os.unlink(OPENVSWITCH_COMPACT_DB)
 
-            output = StringIO.StringIO()
+            output = BytesIO()
             max_time = 5
             procs = [ProcOutput(['ovsdb-tool', 'compact',
                                 OPENVSWITCH_CONF_DB, OPENVSWITCH_COMPACT_DB],
@@ -871,7 +873,7 @@ def fd_usage(cap):
 
 
 def dump_rdac_groups(cap):
-    output = StringIO.StringIO()
+    output = BytesIO()
     procs = [ProcOutput([MPPUTIL, '-a'], caps[cap][MAX_TIME], output)]
 
     run_procs([procs])
@@ -896,7 +898,7 @@ def load_plugins(just_capabilities=False, filter=None):
         for node in nodelist:
             if node.nodeType == node.TEXT_NODE:
                 rc += node.data
-        return rc.encode()
+        return rc
 
     def getBoolAttr(el, attr, default=False):
         ret = default
@@ -1037,7 +1039,7 @@ def make_tar(subdir, suffix, output_fd, output_file):
                     s = os.stat(v['filename'])
                     ti.mtime = s.st_mtime
                     ti.size = s.st_size
-                    tf.addfile(ti, open(v['filename']))
+                    tf.addfile(ti, open(v['filename'], 'rb'))
             except:
                 pass
     finally:
@@ -1095,12 +1097,12 @@ def make_inventory(inventory, subdir):
     s.setAttribute('date', time.strftime('%c'))
     s.setAttribute('hostname', platform.node())
     s.setAttribute('uname', ' '.join(platform.uname()))
-    s.setAttribute('uptime', commands.getoutput(UPTIME))
+    s.setAttribute('uptime', check_output(UPTIME).decode())
     document.getElementsByTagName(INVENTORY_XML_ROOT)[0].appendChild(s)
 
     map(lambda k_v: inventory_entry(document, subdir, k_v[0], k_v[1]),
         inventory.items())
-    return document.toprettyxml()
+    return document.toprettyxml().encode()
 
 
 def inventory_entry(document, subdir, k, v):
@@ -1301,7 +1303,7 @@ class ProcOutput(object):
             line = self.proc.stdout.readline()
         else:
             line = self.proc.stdout.read(self.bufsize)
-        if line == '':
+        if line == b'':
             # process exited
             self.proc.stdout.close()
             self.status = self.proc.wait()
@@ -1391,13 +1393,13 @@ def get_free_disk_space(path):
     return s.f_frsize * s.f_bfree
 
 
-class StringIOmtime(StringIO.StringIO):
-    def __init__(self, buf=''):
-        StringIO.StringIO.__init__(self, buf)
+class BytesIOmtime(BytesIO):
+    def __init__(self, buf=b''):
+        BytesIO.__init__(self, buf)
         self.mtime = time.time()
 
     def write(self, s):
-        StringIO.StringIO.write(self, s)
+        BytesIO.write(self, s)
         self.mtime = time.time()
 
 
diff --git a/utilities/checkpatch.py b/utilities/checkpatch.py
index fc9e20bf1b..893244578a 100755
--- a/utilities/checkpatch.py
+++ b/utilities/checkpatch.py
@@ -13,7 +13,6 @@
 # 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.
-from __future__ import print_function
 
 import email
 import getopt
diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
index 8c5cd70327..4156da20ef 100644
--- a/utilities/ovs-ctl.in
+++ b/utilities/ovs-ctl.in
@@ -43,7 +43,8 @@ set_hostname () {
     else
         hn="$(uname -n)"
     fi
-    ovs_vsctl set Open_vSwitch . external-ids:hostname="$hn"
+    # Set the hostname if it wasn't set before
+    ovs_vsctl add Open_vSwitch . external-ids hostname="$hn"
 }
 
 set_system_ids () {
@@ -225,14 +226,21 @@ start_forwarding () {
     if test X"$OVS_VSWITCHD" = Xyes; then
         do_start_forwarding || return 1
     fi
-    set_hostname &
+    if test X"$RECORD_HOSTNAME" = Xyes; then
+        set_hostname &
+    fi
     return 0
 }
 
 start_ovs_ipsec () {
+    if test X$RESTART_IKE_DAEMON = Xno; then
+        no_restart="--no-restart-ike-daemon"
+    fi
+
     ${datadir}/scripts/ovs-monitor-ipsec \
         --pidfile=${rundir}/ovs-monitor-ipsec.pid \
         --ike-daemon=$IKE_DAEMON \
+        $no_restart \
         --log-file --detach --monitor unix:${rundir}/db.sock || return 1
     return 0
 }
@@ -254,8 +262,7 @@ stop_forwarding () {
 }
 
 stop_ovs_ipsec () {
-    ${bindir}/ovs-appctl -t ovs-monitor-ipsec exit || return 1
-    return 0
+    stop_daemon ovs-monitor-ipsec
 }
 
 ## --------------- ##
@@ -312,6 +319,7 @@ set_defaults () {
     SYSTEM_ID=
 
     FULL_HOSTNAME=yes
+    RECORD_HOSTNAME=yes
 
     DELETE_BRIDGES=no
     DELETE_TRANSIENT_PORTS=no
@@ -341,6 +349,7 @@ set_defaults () {
     SPORT=
 
     IKE_DAEMON=
+    RESTART_IKE_DAEMON=yes
 
     type_file=$etcdir/system-type.conf
     version_file=$etcdir/system-version.conf
@@ -372,19 +381,24 @@ This program is intended to be invoked internally by Open vSwitch startup
 scripts.  System administrators should not normally invoke it directly.
 
 Commands:
-  start                   start Open vSwitch daemons
-  stop                    stop Open vSwitch daemons
-  restart                 stop and start Open vSwitch daemons
-  status                  check whether Open vSwitch daemons are running
-  version                 print versions of Open vSwitch daemons
-  load-kmod               insert modules if not already present
-  force-reload-kmod       save OVS network device state, stop OVS, unload kernel
-                          module, reload kernel module, start OVS, restore state
-  enable-protocol         enable protocol specified in options with iptables
-  delete-transient-ports  delete transient (other_config:transient=true) ports
-  start-ovs-ipsec         start Open vSwitch ipsec daemon
-  stop-ovs-ipsec          stop Open vSwitch ipsec daemon
-  help                    display this help message
+  start                       start Open vSwitch daemons
+  stop                        stop Open vSwitch daemons
+  restart                     stop and start Open vSwitch daemons
+  status                      check whether Open vSwitch daemons are running
+  version                     print versions of Open vSwitch daemons
+  load-kmod                   insert modules if not already present
+  force-reload-kmod           save OVS network device state, stop OVS, unload
+                              kernel module, reload kernel module, start OVS,
+                              restore state
+  enable-protocol             enable protocol specified in options with
+                              iptables
+  delete-transient-ports      delete transient (other_config:transient=true)
+                              ports
+  start-ovs-ipsec             start Open vSwitch ipsec daemon
+  stop-ovs-ipsec              stop Open vSwitch ipsec daemon
+  record-hostname-if-not-set  determine the system hostname and record it in
+                              the Open vSwitch database if not already set
+  help                        display this help message
 
 One of the following options is required for "start", "restart" and "force-reload-kmod":
   --system-id=UUID   set specific ID to uniquely identify this system
@@ -405,6 +419,8 @@ Less important options for "start", "restart" and "force-reload-kmod":
   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
   --no-full-hostname             set short hostname instead of full hostname
+  --no-record-hostname           do not attempt to determine/record system
+                                 hostname as part of start command
 
 Debugging options for "start", "restart" and "force-reload-kmod":
   --ovsdb-server-wrapper=WRAPPER
@@ -424,6 +440,8 @@ Options for "enable-protocol":
 Option for "start-ovs-ipsec":
   --ike-daemon=IKE_DAEMON
       the IKE daemon for ipsec tunnels (either libreswan or strongswan)
+  --no-restart-ike-daemon
+      do not restart the IKE daemon on startup
 
 Other options:
   -h, --help                  display this help message
@@ -561,6 +579,9 @@ case $command in
     stop-ovs-ipsec)
         stop_ovs_ipsec
         ;;
+    record-hostname-if-not-set)
+        set_hostname
+        ;;
     help)
         usage
         ;;
diff --git a/utilities/ovs-dev.py b/utilities/ovs-dev.py
index 248d22ab9a..c45788acd5 100755
--- a/utilities/ovs-dev.py
+++ b/utilities/ovs-dev.py
@@ -1,5 +1,5 @@
-#!/usr/bin/env python
-# Copyright (c) 2013, 2014, 2015, 2016 Nicira, Inc.
+#!/usr/bin/env python3
+# Copyright (c) 2013, 2014, 2015, 2016, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/utilities/ovs-dpctl-top.in b/utilities/ovs-dpctl-top.in
index f2cc3f7f2a..fbe6e4f560 100755
--- a/utilities/ovs-dpctl-top.in
+++ b/utilities/ovs-dpctl-top.in
@@ -480,6 +480,8 @@ def elements_to_dict(elements):
     """ Convert line to a hierarchy of dictionaries. """
     result = {}
     for element in elements:
+        if (element == "eth()"):
+            continue
         match = FIELDS_CMPND.search(element)
         if (match):
             key = match.group(1)
@@ -592,7 +594,7 @@ def flows_read(ihdl, flow_db):
 
         try:
             flow_db.flow_line_add(line)
-        except ValueError, arg:
+        except ValueError as arg:
             logging.error(arg)
 
     return flow_db
@@ -958,6 +960,9 @@ class FlowDB:
         change order of fields of the same flow.
         """
 
+        if not isinstance(line, str):
+           line = str(line)
+
         line = line.rstrip("\n")
         (fields, stats, _) = flow_line_split(line)
 
@@ -988,7 +993,7 @@ class FlowDB:
 
             self.flow_event(fields_dict, stats_old_dict, stats_dict)
 
-        except ValueError, arg:
+        except ValueError as arg:
             logging.error(arg)
             self._error_count += 1
             raise
@@ -1192,7 +1197,7 @@ def flows_top(args):
                         flows_read(ihdl, flow_db)
                     finally:
                         ihdl.close()
-                except OSError, arg:
+                except OSError as arg:
                     logging.critical(arg)
                     break
 
@@ -1220,7 +1225,7 @@ def flows_top(args):
 
     # repeat output
     for (count, line) in lines:
-        print line
+        print(line)
 
 
 def flows_script(args):
@@ -1249,7 +1254,7 @@ def flows_script(args):
     render = Render(console_width, Render.FIELD_SELECT_SCRIPT)
 
     for line in render.format(flow_db):
-        print line
+        print(line)
 
 
 def main():
diff --git a/utilities/ovs-l3ping.in b/utilities/ovs-l3ping.in
index 92d32acb3f..1ece06457c 100644
--- a/utilities/ovs-l3ping.in
+++ b/utilities/ovs-l3ping.in
@@ -19,7 +19,7 @@ achieved by tunneling the control connection inside the tunnel itself.
 """
 
 import socket
-import xmlrpclib
+import xmlrpc.client
 
 import ovstest.args as args
 import ovstest.tests as tests
@@ -64,13 +64,13 @@ if __name__ == '__main__':
             ps = get_packet_sizes(me, he, args.client[0])
             tests.do_direct_tests(me, he, bandwidth, interval, ps)
     except KeyboardInterrupt:
-        print "Terminating"
-    except xmlrpclib.Fault:
-        print "Couldn't contact peer"
+        print("Terminating")
+    except xmlrpc.client.Fault:
+        print("Couldn't contact peer")
     except socket.error:
-        print "Couldn't contact peer"
-    except xmlrpclib.ProtocolError:
-        print "XMLRPC control channel was abruptly terminated"
+        print("Couldn't contact peer")
+    except xmlrpc.client.ProtocolError:
+        print("XMLRPC control channel was abruptly terminated")
     finally:
         if local_server is not None:
             local_server.terminate()
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 3601890f40..ede7f1e61a 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -4020,6 +4020,7 @@ ofctl_meter_mod__(const char *bridge, const char *str, int command)
     enum ofputil_protocol usable_protocols;
     enum ofp_version version;
 
+    memset(&mm, 0, sizeof mm);
     if (str) {
         char *error;
         error = parse_ofp_meter_mod_str(&mm, str, command, &usable_protocols);
@@ -4030,7 +4031,6 @@ ofctl_meter_mod__(const char *bridge, const char *str, int command)
         usable_protocols = OFPUTIL_P_OF13_UP;
         mm.command = command;
         mm.meter.meter_id = OFPM13_ALL;
-        mm.meter.bands = NULL;
     }
 
     protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols);
@@ -4050,6 +4050,7 @@ ofctl_meter_request__(const char *bridge, const char *str,
     enum ofputil_protocol protocol;
     enum ofp_version version;
 
+    memset(&mm, 0, sizeof mm);
     if (str) {
         char *error;
         error = parse_ofp_meter_mod_str(&mm, str, -1, &usable_protocols);
@@ -4059,7 +4060,6 @@ ofctl_meter_request__(const char *bridge, const char *str,
     } else {
         usable_protocols = OFPUTIL_P_OF13_UP;
         mm.meter.meter_id = OFPM13_ALL;
-        mm.meter.bands = NULL;
     }
 
     protocol = open_vconn_for_flow_mod(bridge, &vconn, usable_protocols);
@@ -5051,7 +5051,7 @@ static const struct ovs_cmdl_command all_commands[] = {
     { "add-group", "switch group",
       1, 2, ofctl_add_group, OVS_RW },
     { "add-groups", "switch file",
-      1, 2, ofctl_add_groups, OVS_RW },
+      2, 2, ofctl_add_groups, OVS_RW },
     { "mod-group", "switch group",
       1, 2, ofctl_mod_group, OVS_RW },
     { "del-groups", "switch [group]",
diff --git a/utilities/ovs-parse-backtrace.in b/utilities/ovs-parse-backtrace.in
index d5506769a8..f44f05cd1e 100755
--- a/utilities/ovs-parse-backtrace.in
+++ b/utilities/ovs-parse-backtrace.in
@@ -70,7 +70,7 @@ result.  Expected usage is for ovs-appctl backtrace to be piped in.""")
         if os.path.exists(debug):
             binary = debug
 
-    print "Binary: %s\n" % binary
+    print("Binary: %s\n" % binary)
 
     stdin = sys.stdin.read()
 
@@ -88,15 +88,15 @@ result.  Expected usage is for ovs-appctl backtrace to be piped in.""")
     for lines, count in traces:
         longest = max(len(l) for l in lines)
 
-        print "Backtrace Count: %d" % count
+        print("Backtrace Count: %d" % count)
         for line in lines:
             match = re.search(r'\[(0x.*)]', line)
             if match:
-                print "%s %s" % (line.ljust(longest),
-                                 addr2line(binary, match.group(1)))
+                print("%s %s" % (line.ljust(longest),
+                                 addr2line(binary, match.group(1))))
             else:
-                print line
-        print
+                print(line)
+        print()
 
 
 if __name__ == "__main__":
diff --git a/utilities/ovs-pcap.in b/utilities/ovs-pcap.in
index dddbee4dfb..6b5f63399e 100755
--- a/utilities/ovs-pcap.in
+++ b/utilities/ovs-pcap.in
@@ -14,8 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function
-
 import binascii
 import getopt
 import struct
@@ -79,7 +77,7 @@ if __name__ == "__main__":
         try:
             options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
                                               ['help', 'version'])
-        except getopt.GetoptException as geo:
+        except getopt.GetoptError as geo:
             sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
             sys.exit(1)
 
diff --git a/utilities/ovs-pipegen.py b/utilities/ovs-pipegen.py
index ee5797221c..a3b6a661de 100755
--- a/utilities/ovs-pipegen.py
+++ b/utilities/ovs-pipegen.py
@@ -1,5 +1,5 @@
-#! /usr/bin/env python
-# Copyright (c) 2013, 2014, 2015 Nicira, Inc.
+#! /usr/bin/env python3
+# Copyright (c) 2013, 2014, 2015, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/utilities/ovs-vlan-test.in b/utilities/ovs-vlan-test.in
index 154573a9b5..de3ae16862 100755
--- a/utilities/ovs-vlan-test.in
+++ b/utilities/ovs-vlan-test.in
@@ -14,9 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import BaseHTTPServer
 import getopt
-import httplib
+import http.client
+import http.server
 import os
 import threading
 import time
@@ -84,7 +84,7 @@ class UDPReceiver:
 
         try:
             sock.bind((self.vlan_ip, self.vlan_port))
-        except socket.error, e:
+        except socket.error as e:
             print_safe('Failed to bind to %s:%d with error: %s'
                     % (self.vlan_ip, self.vlan_port, e))
             os._exit(1) #sys.exit only exits the current thread.
@@ -95,7 +95,7 @@ class UDPReceiver:
                 data, _ = sock.recvfrom(4096)
             except socket.timeout:
                 continue
-            except socket.error, e:
+            except socket.error as e:
                 print_safe('Failed to receive from %s:%d with error: %s'
                     % (self.vlan_ip, self.vlan_port, e))
                 os._exit(1)
@@ -180,7 +180,7 @@ class VlanServer:
             for _ in range(send_time * 2):
                 try:
                     send_packet(test_id, size, ip, port)
-                except socket.error, e:
+                except socket.error as e:
                     self.set_result(test_id, 'Failure: ' + str(e))
                     return
                 time.sleep(.5)
@@ -194,15 +194,15 @@ class VlanServer:
     def run(self):
         self.udp_recv.start()
         try:
-            BaseHTTPServer.HTTPServer((self.server_ip, self.server_port),
+            http.server.HTTPServer((self.server_ip, self.server_port),
                     VlanServerHandler).serve_forever()
-        except socket.error, e:
+        except socket.error as e:
             print_safe('Failed to start control server: %s' % e)
             self.udp_recv.stop()
 
         return 1
 
-class VlanServerHandler(BaseHTTPServer.BaseHTTPRequestHandler):
+class VlanServerHandler(http.server.BaseHTTPRequestHandler):
     def do_GET(self):
 
         #Guarantee three arguments.
@@ -244,7 +244,7 @@ class VlanClient:
         self.udp_recv       = UDPReceiver(vlan_ip, vlan_port)
 
     def request(self, resource):
-        conn = httplib.HTTPConnection(self.server_ip_port)
+        conn = http.client.HTTPConnection(self.server_ip_port)
         conn.request('GET', resource)
         return conn
 
@@ -256,7 +256,7 @@ class VlanClient:
         try:
             conn = self.request('/start/recv')
             data = conn.getresponse().read()
-        except (socket.error, httplib.HTTPException), e:
+        except (socket.error, http.client.HTTPException) as e:
             error_msg(e)
             return False
 
@@ -277,7 +277,7 @@ class VlanClient:
                 send_packet(test_id, size, ip, port)
                 resp = self.request('/result/%d' % test_id).getresponse()
                 data = resp.read()
-            except (socket.error, httplib.HTTPException), e:
+            except (socket.error, http.client.HTTPException) as e:
                 error_msg(e)
                 return False
 
@@ -302,7 +302,7 @@ class VlanClient:
         try:
             conn    = self.request(resource)
             test_id = conn.getresponse().read()
-        except (socket.error, httplib.HTTPException), e:
+        except (socket.error, http.client.HTTPException) as e:
             error_msg(e)
             return False
 
@@ -335,7 +335,7 @@ class VlanClient:
         try:
             resp = self.request('/ping').getresponse()
             data = resp.read()
-        except (socket.error, httplib.HTTPException), e:
+        except (socket.error, http.client.HTTPException) as e:
             error_msg(e)
             return False
 
@@ -383,7 +383,7 @@ def main():
     try:
         options, args = getopt.gnu_getopt(sys.argv[1:], 'hVs',
                                           ['help', 'version', 'server'])
-    except getopt.GetoptError, geo:
+    except getopt.GetoptError as geo:
         print_safe('%s: %s\n' % (sys.argv[0], geo.msg))
         return 1
 
diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c
index bd3972636e..37cc72d401 100644
--- a/utilities/ovs-vsctl.c
+++ b/utilities/ovs-vsctl.c
@@ -1344,9 +1344,13 @@ cmd_list_zone_tp(struct ctl_context *ctx)
 
         struct ovsrec_ct_timeout_policy *tp = zone->timeout_policy;
 
-        for (int j = 0; j < tp->n_timeouts; j++) {
-            ds_put_format(&ctx->output, "%s=%"PRIu64" ",
-                          tp->key_timeouts[j], tp->value_timeouts[j]);
+        if (tp) {
+            for (int j = 0; j < tp->n_timeouts; j++) {
+                ds_put_format(&ctx->output, "%s=%"PRIu64" ",
+                        tp->key_timeouts[j], tp->value_timeouts[j]);
+            }
+        } else {
+            ds_put_cstr(&ctx->output, "system default");
         }
         ds_chomp(&ctx->output, ' ');
         ds_put_char(&ctx->output, '\n');
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index e591c26a6c..ce348b9d16 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -634,8 +634,10 @@ static void
 get_timeout_policy_from_ovsrec(struct simap *tp,
                                const struct ovsrec_ct_timeout_policy *tp_cfg)
 {
-    for (size_t i = 0; i < tp_cfg->n_timeouts; i++) {
-        simap_put(tp, tp_cfg->key_timeouts[i], tp_cfg->value_timeouts[i]);
+    if (tp_cfg) {
+        for (size_t i = 0; i < tp_cfg->n_timeouts; i++) {
+            simap_put(tp, tp_cfg->key_timeouts[i], tp_cfg->value_timeouts[i]);
+        }
     }
 }
 
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index 3ddaaefda8..fd13281a7f 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -653,8 +653,9 @@
               type='{"type": "boolean"}'>
         <p>
          Configures PMD Auto Load Balancing that allows automatic assignment of
-         RX queues to PMDs if any of PMDs is overloaded (i.e. processing cycles
-         > 95%).
+         RX queues to PMDs if any of PMDs is overloaded (i.e. a processing
+         cycles >
+         <ref column="other_config" key="pmd-auto-lb-load-threshold"/>).
         </p>
         <p>
          It uses current scheme of cycle based assignment of RX queues that
@@ -690,6 +691,32 @@
          once in few hours or a day or a week.
         </p>
       </column>
+      <column name="other_config" key="pmd-auto-lb-load-threshold"
+              type='{"type": "integer", "minInteger": 0, "maxInteger": 100}'>
+        <p>
+         Specifies the minimum PMD thread load threshold (% of used cycles) of
+         any non-isolated PMD threads when a PMD Auto Load Balance may be
+         triggered.
+        </p>
+        <p>
+         The default value is <code>95%</code>.
+        </p>
+      </column>
+      <column name="other_config" key="pmd-auto-lb-improvement-threshold"
+              type='{"type": "integer", "minInteger": 0, "maxInteger": 100}'>
+        <p>
+         Specifies the minimum evaluated % improvement in load distribution
+         across the non-isolated PMD threads that will allow a PMD Auto Load
+         Balance to occur.
+        </p>
+        <p>
+         Note, setting this parameter to 0 will always allow an auto load
+         balance to occur regardless of estimated improvement or not.
+        </p>
+        <p>
+         The default value is <code>25%</code>.
+        </p>
+      </column>
       <column name="other_config" key="userspace-tso-enable"
               type='{"type": "boolean"}'>
         <p>
@@ -2971,8 +2998,8 @@
       <group title="Tunnel Options: IPsec">
         <p>
           Setting any of these options enables IPsec support for a given
-          tunnel.  <code>gre</code>, <code>ip6gre</code>,
-          <code>geneve</code>, <code>vxlan</code> and <code>stt</code>
+          tunnel.  <code>gre</code>, <code>geneve</code>,
+          <code>vxlan</code> and <code>stt</code>
           interfaces support these options.  See the <code>IPsec</code>
           section in the <ref table="Open_vSwitch"/> table for a description
           of each mode.
@@ -4530,7 +4557,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
         packets per second the CIR would be set to to to 46000000. This value
         can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing
         rate for the number of packets per second and 46 represents the size
-        of the packet data for a 64 byte ip packet.
+        of the packet data for a 64 bytes IP packet without 14 bytes Ethernet
+        and 4 bytes FCS header.
       </column>
       <column name="other_config" key="cbs" type='{"type": "integer"}'>
         The Committed Burst Size (CBS) is measured in bytes and represents a
@@ -4551,7 +4579,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
         packets per second the EIR would be set to to to 46000000. This value
         can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing
         rate for the number of packets per second and 46 represents the size
-        of the packet data for a 64 byte ip packet.
+        of the packet data for a 64 bytes IP packet without 14 bytes Ethernet
+        and 4 bytes FCS header.
       </column>
       <column name="other_config" key="ebs" type='{"type": "integer"}'>
         The Excess Burst Size (EBS) is measured in bytes and represents a
@@ -5976,6 +6005,15 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
         True if the datapath supports OVS_ACTION_ATTR_DROP.  If false,
         explicit drop action will not be sent to the datapath.
       </column>
+      <column name="capabilities" key="ct_zero_snat"
+              type='{"type": "boolean"}'>
+        True if the datapath supports all-zero SNAT. This is a special case
+        if the <code>src</code> IP address is configured as all 0's, i.e.,
+        <code>nat(src=0.0.0.0)</code>. In this case, when a source port
+        collision is detected during the commit, the source port will be
+        translated to an ephemeral port. If there is no collision, no SNAT
+        is performed.
+      </column>
     </group>
 
     <group title="Common Columns">
diff --git a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update b/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update
index e7404e3b00..b8db881949 100755
--- a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update
+++ b/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update
@@ -1,10 +1,10 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # xapi plugin script to update the cache of configuration items in the
 # ovs-vswitchd configuration that are managed in the xapi database when
 # integrated with Citrix management tools.
 
-# Copyright (C) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
diff --git a/xenserver/opt_xensource_libexec_interface-reconfigure b/xenserver/opt_xensource_libexec_interface-reconfigure
index a82043fb5b..9c20725de2 100755
--- a/xenserver/opt_xensource_libexec_interface-reconfigure
+++ b/xenserver/opt_xensource_libexec_interface-reconfigure
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (c) 2008,2009 Citrix Systems, Inc.
 #
diff --git a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
index cf89600253..bff85464ba 100755
--- a/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
+++ b/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
@@ -1,5 +1,5 @@
-#! /usr/bin/env python
-# Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+#!/usr/bin/env python3
+# Copyright (c) 2009, 2010, 2011, 2012, 2013, 2020 Nicira, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.