aboutsummaryrefslogtreecommitdiffstats
path: root/dpdk
diff options
context:
space:
mode:
Diffstat (limited to 'dpdk')
-rw-r--r--dpdk/Makefile101
-rw-r--r--dpdk/dpdk-v18.11_patches/0001-eal-don-t-start-the-interrupt-mp-thread.patch35
-rw-r--r--dpdk/dpdk-v18.11_patches/0002-eal-prioritize-constructor.patch25
-rw-r--r--dpdk/dpdk-v18.11_patches/0003-mbuf-add-single-linked-list.patch33
-rw-r--r--dpdk/dpdk-v18.11_patches/0004-net-virtio-user-add-rss-update-for-virtio-user.patch43
-rw-r--r--dpdk/dpdk-v18.11_patches/0005-net-virtio-user-support-raw-socket-as-backend.patch645
-rw-r--r--dpdk/dpdk-v18.11_patches/0006-mempool-add-dynamic-mempool-support.patch247
-rw-r--r--dpdk/dpdk-v18.11_patches/0007-mbuf-add-dynamic-mbuf-mempool-support.patch305
-rw-r--r--dpdk/dpdk-v18.11_patches/0008-mempool-prioritize-constructor.patch30
-rw-r--r--dpdk/dpdk-v18.11_patches/0009-net-virtio-fill-desc-limit.patch42
10 files changed, 1501 insertions, 5 deletions
diff --git a/dpdk/Makefile b/dpdk/Makefile
index 15204fa..5d92719 100644
--- a/dpdk/Makefile
+++ b/dpdk/Makefile
@@ -21,10 +21,12 @@ DPDK_PKTMBUF_HEADROOM ?= 128
DPDK_MARCH ?= native
DPDK_TUNE ?= generic
DPDK_DEBUG ?= n
+DPDK_DESTDIR ?= $(CURDIR)/install
+PACKETDRILL ?= n
B := $(DPDK_BUILD_DIR)
I := $(DPDK_INSTALL_DIR)
-DPDK_GIT_REPO ?= http://dpdk.org/git/dpdk
+DPDK_GIT_REPO ?= http://dpdk.org/git/dpdk -b v18.11
DPDK_SOURCE := $(B)/dpdk
ifneq (,$(findstring clang,$(CC)))
@@ -40,8 +42,8 @@ endif
JOBS := $(shell grep processor /proc/cpuinfo | wc -l)
# compiler/linker custom arguments
-DPDK_CPU_CFLAGS := -pie -fPIC
-DPDK_CPU_LDFLAGS :=
+DPDK_CPU_CFLAGS := -fPIC
+DPDK_CPU_LDFLAGS := -r
DPDK_EXTRA_LDFLAGS := -g
ifeq ($(DPDK_DEBUG),n)
@@ -78,6 +80,7 @@ DPDK_MAKE_ARGS := -C $(DPDK_SOURCE) -j $(JOBS) \
EXTRA_LDFLAGS="$(DPDK_EXTRA_LDFLAGS)" \
CPU_CFLAGS="$(DPDK_CPU_CFLAGS)" \
CPU_LDFLAGS="$(DPDK_CPU_LDFLAGS)" \
+ DESTDIR="$(DPDK_DESTDIR)" \
$(DPDK_MAKE_EXTRA_ARGS)
DPDK_SOURCE_FILES := $(shell [ -e $(DPDK_SOURCE) ] && \
@@ -102,7 +105,7 @@ $(B)/custom-config: $(B)/.patch.ok Makefile
$(call set,RTE_MAX_LCORE,256)
$(call set,RTE_PKTMBUF_HEADROOM,$(DPDK_PKTMBUF_HEADROOM))
$(call set,RTE_LIBEAL_USE_HPET,y)
- $(call set,RTE_BUILD_COMBINE_LIBS,y)
+ $(call set,RTE_BUILD_COMBINE_LIBS,n)
$(call set,RTE_LIBRTE_I40E_16BYTE_RX_DESC,y)
$(call set,RTE_LIBRTE_I40E_ITR_INTERVAL,16)
$(call set,RTE_LIBRTE_PMD_PCAP,y)
@@ -115,13 +118,101 @@ $(B)/custom-config: $(B)/.patch.ok Makefile
$(call set,RTE_LIBRTE_PMD_BOND,y)
$(call set,RTE_LIBRTE_IP_FRAG,y)
@# not needed
+ $(call set,RTE_LIBRTE_TIMER,y)
$(call set,RTE_LIBRTE_CFGFILE,n)
+ $(call set,RTE_LIBRTE_LPM,y)
+ $(call set,RTE_LIBRTE_ACL,n)
$(call set,RTE_LIBRTE_POWER,n)
$(call set,RTE_LIBRTE_DISTRIBUTOR,n)
$(call set,RTE_LIBRTE_REORDER,n)
+ $(call set,RTE_LIBRTE_PORT,n)
+ $(call set,RTE_LIBRTE_TABLE,n)
+ $(call set,RTE_LIBRTE_PIPELINE,n)
$(call set,RTE_LIBRTE_FLOW_CLASSIFY,n)
$(call set,RTE_LIBRTE_PMD_CRYPTO_SCHEDULER,n)
$(call set,RTE_KNI_KMOD,n)
+ $(call set,RTE_LIBRTE_ENA_PMD,n)
+ $(call set,RTE_LIBRTE_FM10K_PMD,n)
+ $(call set,RTE_LIBRTE_CXGBE_PMD,n)
+ $(call set,RTE_LIBRTE_ENIC_PMD,n)
+ $(call set,RTE_LIBRTE_BNXT_PMD,n)
+ $(call set,RTE_LIBRTE_SFC_EFX_PMD,n)
+ $(call set,RTE_LIBRTE_PMD_SOFTNIC,n)
+ $(call set,RTE_LIBRTE_THUNDERX_NICVF_PMD,n)
+ $(call set,RTE_LIBRTE_LIO_PMD,n)
+ $(call set,RTE_LIBRTE_OCTEONTX_PMD,n)
+ $(call set,RTE_LIBRTE_VMXNET3_PMD,n)
+ $(call set,RTE_LIBRTE_QEDE_PMD,n)
+ $(call set,RTE_LIBRTE_ARK_PMD,n)
+ $(call set,RTE_LIBRTE_PMD_NULL,n)
+ $(call set,RTE_LIBRTE_CRYPTODEV,n)
+ $(call set,RTE_LIBRTE_PMD_NULL_CRYPTO,n)
+ $(call set,RTE_LIBRTE_SECURITY,n)
+ $(call set,RTE_LIBRTE_EVENTDEV,n)
+ $(call set,RTE_LIBRTE_PMD_SKELETON_EVENTDEV,n)
+ $(call set,RTE_LIBRTE_PMD_OCTEONTX_SSOVF,n)
+ $(call set,RTE_LIBRTE_OCTEONTX_MEMPOOL,n)
+ $(call set,RTE_LIBRTE_EFD,n)
+ $(call set,RTE_LIBRTE_MEMBER,n)
+ $(call set,RTE_LIBRTE_JOBSTATS,n)
+ $(call set,RTE_LIBRTE_METER,n)
+ $(call set,RTE_LIBRTE_SCHED,n)
+ $(call set,RTE_APP_TEST,n)
+ $(call set,RTE_APP_CRYPTO_PERF,n)
+ $(call set,RTE_APP_EVENTDEV,n)
+ $(call set,RTE_LIBRTE_PMD_FAILSAFE,n)
+ $(call set,RTE_LIBRTE_EM_PMD,n)
+ $(call set,RTE_LIBRTE_IGB_PMD,n)
+ $(call set,RTE_LIBRTE_LATENCY_STATS,n)
+ $(call set,RTE_EAL_IGB_UIO,n)
+ $(call set,RTE_LIBRTE_KNI,n)
+ $(call set,RTE_LIBRTE_PMD_KNI,n)
+ $(call set,RTE_KNI_KMOD,n)
+ $(call set,RTE_KNI_KMOD_ETHTOOL,n)
+ $(call set,RTE_LIBRTE_BITRATE,n)
+ $(call set,RTE_LIBRTE_METRICS,y)
+ $(call set,RTE_LIBRTE_AVP_PMD,n)
+ $(call set,RTE_LIBRTE_NFP_PMD,n)
+ $(call set,RTE_LIBRTE_PMD_TAP,n)
+ $(call set,RTE_LIBRTE_VHOST,$(PACKETDRILL))
+ $(call set,RTE_LIBRTE_IFC_PMD,n)
+ $(call set,RTE_LIBRTE_PMD_VHOST,n)
+ $(call set,RTE_PROC_INFO,n)
+ $(call set,RTE_TEST_PMD,n)
+ $(call set,RTE_LIBRTE_FSLMC_BUS,n)
+ $(call set,RTE_LIBRTE_DPAA_BUS,n)
+ $(call set,RTE_LIBRTE_VMBUS,n)
+ $(call set,RTE_LIBRTE_IFPGA_BUS,n)
+ $(call set,RTE_LIBRTE_BPF,n)
+ $(call set,RTE_LIBRTE_COMPRESSDEV,n)
+ $(call set,RTE_LIBRTE_VDEV_NETVSC_PMD,n)
+ $(call set,RTE_LIBRTE_NETVSC_PMD,n)
+ $(call set,RTE_LIBRTE_RAWDEV,n)
+ $(call set,RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT,n)
+ $(call set,RTE_LIBRTE_AXGBE_PMD,n)
+ $(call set,RTE_LIBRTE_AVF_PMD,n)
+ $(call set,RTE_LIBRTE_BBDEV,n)
+ $(call set,RTE_LIBRTE_IP_FRAG_MAX_FRAG,48)
+ $(call set,RTE_MAX_NUMA_NODES,2)
+ $(call set,RTE_MAX_ETHPORTS,4)
+ $(call set,RTE_MAX_QUEUES_PER_PORT,8)
+ $(call set,RTE_LIBRTE_I40E_PMD,n)
+ $(call set,RTE_LIBRTE_IXGBE_PMD,n)
+ $(call set,RTE_LIBRTE_ENETC_PMD,n)
+ $(call set,RTE_LIBRTE_PMD_BOND,n)
+ $(call set,RTE_LIBRTE_ATLANTIC_PMD,n)
+ $(call set,RTE_LIBRTE_GSO,n)
+ $(call set,RTE_MAX_VFIO_GROUPS,4)
+ $(call set,RTE_MAX_VFIO_CONTAINERS,4)
+ $(call set,RTE_LIBRTE_COMMON_DPAAX,n)
+ $(call set,RTE_LIBRTE_PMD_OCTEONTX_CRYPTO,n)
+ $(call set,RTE_EAL_NUMA_AWARE_HUGEPAGES,n)
+ $(call set,RTE_DRIVER_MEMPOOL_STACK,y)
+ $(call set,RTE_DRIVER_MEMPOOL_BUCKET,n)
+ $(call set,RTE_LIBRTE_PMD_QAT,n)
+ $(call set,RTE_LIBRTE_PMD_AF_PACKET,n)
+ $(call set,RTE_MAX_MEM_MB,1024)
+ $(call set,RTE_LIBRTE_PDUMP,n)
@rm -f .config.ok
$(B)/.download.ok:
@@ -165,4 +256,4 @@ build: $(B)/.build.ok
.PHONY: clean
clean:
- @rm -rf $(B) $(I)
+ @rm -rf $(DPDK_BUILD_DIR) $(DPDK_DESTDIR)
diff --git a/dpdk/dpdk-v18.11_patches/0001-eal-don-t-start-the-interrupt-mp-thread.patch b/dpdk/dpdk-v18.11_patches/0001-eal-don-t-start-the-interrupt-mp-thread.patch
new file mode 100644
index 0000000..770bf05
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0001-eal-don-t-start-the-interrupt-mp-thread.patch
@@ -0,0 +1,35 @@
+From f68558b0ccbddb4cc81aca36befa0a7730ee051c Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed, 29 Aug 2018 14:24:01 +0000
+Subject: [PATCH 7/9] eal: don't start the interrupt mp thread
+
+---
+ lib/librte_eal/common/eal_common_proc.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/lib/librte_eal/common/eal_common_proc.c b/lib/librte_eal/common/eal_common_proc.c
+index 9fcb91219..79d9e6bbe 100644
+--- a/lib/librte_eal/common/eal_common_proc.c
++++ b/lib/librte_eal/common/eal_common_proc.c
+@@ -615,6 +615,7 @@ rte_mp_channel_init(void)
+ return -1;
+ }
+
++#if 0
+ 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",
+@@ -624,6 +625,10 @@ rte_mp_channel_init(void)
+ mp_fd = -1;
+ return -1;
+ }
++#else
++ RTE_SET_USED(mp_handle);
++ RTE_SET_USED(mp_handle_tid);
++#endif
+
+ /* unlock the directory */
+ flock(dir_fd, LOCK_UN);
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0002-eal-prioritize-constructor.patch b/dpdk/dpdk-v18.11_patches/0002-eal-prioritize-constructor.patch
new file mode 100644
index 0000000..9d2959f
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0002-eal-prioritize-constructor.patch
@@ -0,0 +1,25 @@
+From 7fe32567994a8ce782fa8406613bade1d2100dca Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed, 29 Aug 2018 14:14:09 +0000
+Subject: [PATCH 2/9] eal: prioritize constructor
+
+---
+ lib/librte_eal/common/include/rte_common.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
+index 069c13ec7..a635f5be4 100644
+--- a/lib/librte_eal/common/include/rte_common.h
++++ b/lib/librte_eal/common/include/rte_common.h
+@@ -84,7 +84,7 @@ typedef uint16_t unaligned_uint16_t;
+ #define RTE_PRIORITY_LOG 101
+ #define RTE_PRIORITY_BUS 110
+ #define RTE_PRIORITY_CLASS 120
+-#define RTE_PRIORITY_LAST 65535
++#define RTE_PRIORITY_LAST 130
+
+ #define RTE_PRIO(prio) \
+ RTE_PRIORITY_ ## prio
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0003-mbuf-add-single-linked-list.patch b/dpdk/dpdk-v18.11_patches/0003-mbuf-add-single-linked-list.patch
new file mode 100644
index 0000000..7430d1e
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0003-mbuf-add-single-linked-list.patch
@@ -0,0 +1,33 @@
+From 1416ff5de58922dc32eb2fb9ce2b9b970282136c Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed, 29 Aug 2018 14:18:13 +0000
+Subject: [PATCH 3/9] mbuf: add single linked list
+
+---
+ lib/librte_mbuf/rte_mbuf.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
+index 9ce5d76d7..0081bd6d7 100644
+--- a/lib/librte_mbuf/rte_mbuf.h
++++ b/lib/librte_mbuf/rte_mbuf.h
+@@ -593,6 +593,8 @@ struct rte_mbuf {
+ */
+ struct rte_mbuf_ext_shared_info *shinfo;
+
++ struct rte_mbuf *next_pkt;
++
+ } __rte_cache_aligned;
+
+ /**
+@@ -1237,6 +1239,7 @@ static inline void rte_pktmbuf_reset_headroom(struct rte_mbuf *m)
+ static inline void rte_pktmbuf_reset(struct rte_mbuf *m)
+ {
+ m->next = NULL;
++ m->next_pkt = NULL;
+ m->pkt_len = 0;
+ m->tx_offload = 0;
+ m->vlan_tci = 0;
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0004-net-virtio-user-add-rss-update-for-virtio-user.patch b/dpdk/dpdk-v18.11_patches/0004-net-virtio-user-add-rss-update-for-virtio-user.patch
new file mode 100644
index 0000000..e4eb8e7
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0004-net-virtio-user-add-rss-update-for-virtio-user.patch
@@ -0,0 +1,43 @@
+From 9bbe20eda858fd7fcbd8f137e5f96f51d571a556 Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed, 29 Aug 2018 14:20:51 +0000
+Subject: [PATCH 4/9] net/virtio-user: add rss update for virtio-user
+
+---
+ drivers/net/virtio/virtio_ethdev.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
+index 614357da7..e7336cde9 100644
+--- a/drivers/net/virtio/virtio_ethdev.c
++++ b/drivers/net/virtio/virtio_ethdev.c
+@@ -738,6 +738,18 @@ virtio_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
+ return 0;
+ }
+
++static int
++virtio_rss_hash_update(struct rte_eth_dev *dev,
++ struct rte_eth_rss_conf *rss_conf __rte_unused)
++{
++ struct virtio_hw *hw = dev->data->dev_private;
++
++ if (hw->virtio_user_dev)
++ return 0;
++
++ return -1;
++}
++
+ /*
+ * dev_ops for virtio, bare necessities for basic operation
+ */
+@@ -772,6 +784,7 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
+ .mac_addr_add = virtio_mac_addr_add,
+ .mac_addr_remove = virtio_mac_addr_remove,
+ .mac_addr_set = virtio_mac_addr_set,
++ .rss_hash_update = virtio_rss_hash_update,
+ };
+
+ static void
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0005-net-virtio-user-support-raw-socket-as-backend.patch b/dpdk/dpdk-v18.11_patches/0005-net-virtio-user-support-raw-socket-as-backend.patch
new file mode 100644
index 0000000..1d950c5
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0005-net-virtio-user-support-raw-socket-as-backend.patch
@@ -0,0 +1,645 @@
+From 307f7debe0f2143e70659b7a082537077b20d185 Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Thu, 19 Jul 2018 11:25:22 +0000
+Subject: [PATCH] net/virtio-user: support raw socket as backend
+
+We will support tapfd or raw socket fd opened by application and
+passed into virtio-user for initialization.
+
+Note if there are multiple queue pairs, users are still supposed
+to pass down the iface name with the first queue pair fd passed
+through this parameter.
+
+Signed-off-by: Jianfeng Tan <henry.tjf@antfin.com>
+---
+ drivers/net/virtio/Makefile | 1 +
+ drivers/net/virtio/virtio_user/vhost_kernel.c | 78 ++++++---
+ drivers/net/virtio/virtio_user/vhost_kernel.h | 15 ++
+ .../virtio/virtio_user/vhost_kernel_sock.c | 156 ++++++++++++++++++
+ .../net/virtio/virtio_user/vhost_kernel_tap.c | 64 ++++++-
+ .../net/virtio/virtio_user/vhost_kernel_tap.h | 39 -----
+ .../net/virtio/virtio_user/virtio_user_dev.c | 16 +-
+ .../net/virtio/virtio_user/virtio_user_dev.h | 3 +-
+ drivers/net/virtio/virtio_user_ethdev.c | 20 ++-
+ 9 files changed, 318 insertions(+), 74 deletions(-)
+ create mode 100644 drivers/net/virtio/virtio_user/vhost_kernel.h
+ create mode 100644 drivers/net/virtio/virtio_user/vhost_kernel_sock.c
+ delete mode 100644 drivers/net/virtio/virtio_user/vhost_kernel_tap.h
+
+diff --git a/drivers/net/virtio/Makefile b/drivers/net/virtio/Makefile
+index 6c2c9967b..2e1fc9b5e 100644
+--- a/drivers/net/virtio/Makefile
++++ b/drivers/net/virtio/Makefile
+@@ -41,6 +41,7 @@ ifeq ($(CONFIG_RTE_VIRTIO_USER),y)
+ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost_user.c
+ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost_kernel.c
+ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost_kernel_tap.c
++SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/vhost_kernel_sock.c
+ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user/virtio_user_dev.c
+ SRCS-$(CONFIG_RTE_LIBRTE_VIRTIO_PMD) += virtio_user_ethdev.c
+ endif
+diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.c b/drivers/net/virtio/virtio_user/vhost_kernel.c
+index 6b19180d7..fa84287f5 100644
+--- a/drivers/net/virtio/virtio_user/vhost_kernel.c
++++ b/drivers/net/virtio/virtio_user/vhost_kernel.c
+@@ -6,13 +6,14 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <unistd.h>
++#include <sys/ioctl.h>
+
+ #include <rte_memory.h>
+ #include <rte_eal_memconfig.h>
+
+ #include "vhost.h"
+ #include "virtio_user_dev.h"
+-#include "vhost_kernel_tap.h"
++#include "vhost_kernel.h"
+
+ struct vhost_memory_kernel {
+ uint32_t nregions;
+@@ -152,27 +153,25 @@ prepare_vhost_memory_kernel(void)
+ (1ULL << VIRTIO_NET_F_HOST_TSO6) | \
+ (1ULL << VIRTIO_NET_F_CSUM))
+
+-static unsigned int
+-tap_support_features(void)
++#define PATH_SYS_CLASS_NET "/sys/class/net"
++
++static int
++vhost_kernel_is_tap(struct virtio_user_dev *dev)
+ {
+- int tapfd;
+- unsigned int tap_features;
++ char path[128];
+
+- tapfd = open(PATH_NET_TUN, O_RDWR);
+- if (tapfd < 0) {
+- PMD_DRV_LOG(ERR, "fail to open %s: %s",
+- PATH_NET_TUN, strerror(errno));
+- return -1;
+- }
++ if (dev->ifname == NULL)
++ return 0;
+
+- if (ioctl(tapfd, TUNGETFEATURES, &tap_features) == -1) {
+- PMD_DRV_LOG(ERR, "TUNGETFEATURES failed: %s", strerror(errno));
+- close(tapfd);
+- return -1;
+- }
++ snprintf(path, 128, PATH_SYS_CLASS_NET"/%s", dev->ifname);
++ if(access(path, F_OK) == -1)
++ return 1;
+
+- close(tapfd);
+- return tap_features;
++ snprintf(path, 128, PATH_SYS_CLASS_NET"/%s/tun_flags", dev->ifname);
++ if(access(path, F_OK) != -1)
++ return 1;
++
++ return 0;
+ }
+
+ static int
+@@ -186,7 +185,6 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev,
+ struct vhost_memory_kernel *vm = NULL;
+ int vhostfd;
+ unsigned int queue_sel;
+- unsigned int features;
+
+ PMD_DRV_LOG(INFO, "%s", vhost_msg_strings[req]);
+
+@@ -240,21 +238,36 @@ vhost_kernel_ioctl(struct virtio_user_dev *dev,
+ }
+
+ if (!ret && req_kernel == VHOST_GET_FEATURES) {
+- features = tap_support_features();
+- /* with tap as the backend, all these features are supported
++ int vnet_hdr, mq;
++
++ if (vhost_kernel_is_tap(dev))
++ tap_support_features(&vnet_hdr, &mq);
++ else
++ sock_support_features(dev->be_fd, &vnet_hdr, &mq);
++
++ /* with kernel vhost, all these features are supported
+ * but not claimed by vhost-net, so we add them back when
+ * reporting to upper layer.
+ */
+- if (features & IFF_VNET_HDR) {
++ if (vnet_hdr) {
+ *((uint64_t *)arg) |= VHOST_KERNEL_GUEST_OFFLOADS_MASK;
+ *((uint64_t *)arg) |= VHOST_KERNEL_HOST_OFFLOADS_MASK;
+ }
+
+- /* vhost_kernel will not declare this feature, but it does
++ /* kernel vhost will not declare this feature, but it does
+ * support multi-queue.
+ */
+- if (features & IFF_MULTI_QUEUE)
++ if (mq)
+ *(uint64_t *)arg |= (1ull << VIRTIO_NET_F_MQ);
++
++ /* raw socket only supports vnet header size of 10, so we must
++ * eliminate below features.
++ */
++ if (!vhost_kernel_is_tap(dev) &&
++ vnet_hdr == sizeof(struct virtio_net_hdr)) {
++ *((uint64_t *)arg) &= ~(1ull << VIRTIO_NET_F_MRG_RXBUF);
++ *((uint64_t *)arg) &= ~(1ull << VIRTIO_F_VERSION_1);
++ }
+ }
+
+ if (vm)
+@@ -333,7 +346,8 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
+
+ if (!enable) {
+ if (dev->tapfds[pair_idx] >= 0) {
+- close(dev->tapfds[pair_idx]);
++ if (dev->be_fd < 0)
++ close(dev->tapfds[pair_idx]);
+ dev->tapfds[pair_idx] = -1;
+ }
+ return vhost_kernel_set_backend(vhostfd, -1);
+@@ -347,8 +361,18 @@ vhost_kernel_enable_queue_pair(struct virtio_user_dev *dev,
+ else
+ hdr_size = sizeof(struct virtio_net_hdr);
+
+- tapfd = vhost_kernel_open_tap(&dev->ifname, hdr_size, req_mq,
+- (char *)dev->mac_addr, dev->features);
++ if (vhost_kernel_is_tap(dev)) {
++ tapfd = vhost_kernel_open_tap(&dev->ifname, hdr_size,
++ req_mq, (char *)dev->mac_addr, dev->features);
++ } else {
++ if (pair_idx == 0 && dev->be_fd >= 0)
++ tapfd = vhost_kernel_set_sock(dev->be_fd,
++ hdr_size, req_mq);
++ else
++ tapfd = vhost_kernel_open_sock(dev->ifname,
++ hdr_size, dev->mac_addr, req_mq);
++ }
++
+ if (tapfd < 0) {
+ PMD_DRV_LOG(ERR, "fail to open tap for vhost kernel");
+ return -1;
+diff --git a/drivers/net/virtio/virtio_user/vhost_kernel.h b/drivers/net/virtio/virtio_user/vhost_kernel.h
+new file mode 100644
+index 000000000..75d6c5bf6
+--- /dev/null
++++ b/drivers/net/virtio/virtio_user/vhost_kernel.h
+@@ -0,0 +1,15 @@
++/* SPDX-License-Identifier: BSD-3-Clause
++ * Copyright(c) 2016 Intel Corporation
++ */
++
++int vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
++ const char *mac, uint64_t features);
++
++void tap_support_features(int *vnet_hdr, int *mq);
++
++int vhost_kernel_open_sock(char *ifname, int hdr_size,
++ uint8_t *mac, int req_mq);
++
++int vhost_kernel_set_sock(int sockfd, int hdr_size, int req_mq);
++
++void sock_support_features(int fd, int *vnet_hdr, int *mq);
+diff --git a/drivers/net/virtio/virtio_user/vhost_kernel_sock.c b/drivers/net/virtio/virtio_user/vhost_kernel_sock.c
+new file mode 100644
+index 000000000..7c2ace294
+--- /dev/null
++++ b/drivers/net/virtio/virtio_user/vhost_kernel_sock.c
+@@ -0,0 +1,156 @@
++/* SPDX-License-Identifier: BSD-3-Clause
++ * Copyright(c) 2018 Alibaba Group
++ * Copyright(c) 2018 Ant Financial Services Group
++ */
++
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <net/if.h>
++#include <net/if_arp.h>
++#include <errno.h>
++#include <string.h>
++#include <limits.h>
++#include <sys/socket.h>
++#include <arpa/inet.h>
++#include <netpacket/packet.h>
++#include <linux/if_ether.h>
++#include <sys/ioctl.h>
++
++#include <rte_ether.h>
++
++#include "../virtqueue.h"
++#include "../virtio_logs.h"
++#include "vhost_kernel.h"
++
++#ifndef PACKET_VNET_HDR
++#define PACKET_VNET_HDR 15
++#endif
++
++#ifndef PACKET_FANOUT
++#define PACKET_FANOUT 18
++#endif
++
++#ifndef PACKET_VNET_HDR_SZ
++#define PACKET_VNET_HDR_SZ 128
++#endif
++
++void
++sock_support_features(int fd, int *vnet_hdr, int *mq)
++{
++ int hdr_size = sizeof(struct virtio_net_hdr_mrg_rxbuf);
++ int local_fd = 0;
++
++ if (fd < 0) {
++ fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
++ if (fd < 0) {
++ *mq = 0;
++ *vnet_hdr = 0;
++ return;
++ }
++ local_fd = 1;
++ }
++
++ *mq = 1;
++
++ if (setsockopt(fd, SOL_PACKET, PACKET_VNET_HDR_SZ,
++ (void *)&hdr_size, sizeof(hdr_size))) {
++ *vnet_hdr = sizeof(struct virtio_net_hdr);
++ } else
++ *vnet_hdr = hdr_size;
++
++ if (local_fd)
++ close(fd);
++}
++
++int
++vhost_kernel_set_sock(int sockfd, int hdr_size, int req_mq)
++{
++ int ret;
++ int fanout_type = 0; /* PACKET_FANOUT_HASH */
++
++ if (hdr_size == sizeof(struct virtio_net_hdr))
++ ret = setsockopt(sockfd, SOL_PACKET, PACKET_VNET_HDR,
++ (void *)&hdr_size, sizeof(hdr_size));
++ else
++ ret = setsockopt(sockfd, SOL_PACKET, PACKET_VNET_HDR_SZ,
++ (void *)&hdr_size, sizeof(hdr_size));
++ if (ret) {
++ PMD_DRV_LOG(ERR, "failed to set vnet hdr (%d): %s",
++ hdr_size, strerror(errno));
++ close(sockfd);
++ return -1;
++ }
++
++ if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK))
++ {
++ PMD_DRV_LOG(ERR, "fcntl O_NONBLOCK failed! %s",
++ strerror(errno));
++ close(sockfd);
++ return -1;
++ }
++
++ if (req_mq) {
++ if (setsockopt(sockfd, SOL_PACKET, PACKET_FANOUT,
++ (void *)&fanout_type, sizeof(fanout_type))) {
++ PMD_DRV_LOG(ERR, "PACKET_FANOUT failed! %s",
++ strerror(errno));
++ close(sockfd);
++ return -1;
++ }
++ }
++
++ return sockfd;
++}
++
++int
++vhost_kernel_open_sock(char *ifname, int hdr_size,
++ uint8_t *mac, int req_mq)
++{
++ int sockfd;
++ struct ifreq ifr;
++ struct sockaddr_ll addr_ll;
++
++ sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
++ if (sockfd < 0) {
++ PMD_DRV_LOG(ERR, "socket failed: %s", strerror(errno));
++ return -1;
++ }
++
++ memset(&ifr, 0, sizeof(ifr));
++ strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
++
++ if (ioctl(sockfd, SIOCGIFINDEX, (void*)&ifr)) {
++ PMD_DRV_LOG(ERR, "SIOCGIFINDEX failed: %s", strerror(errno));
++ close(sockfd);
++ return -1;
++ }
++
++ memset(&addr_ll, 0, sizeof(addr_ll));
++ addr_ll.sll_ifindex = ifr.ifr_ifindex;
++ addr_ll.sll_family = AF_PACKET;
++ addr_ll.sll_protocol = htons(ETH_P_ALL);
++ addr_ll.sll_hatype = 0;
++ //addr_ll.sll_pkttype = PACKET_HOST;
++ //addr_ll.sll_halen = ETH_ALEN;
++ if (bind(sockfd, (struct sockaddr*)&addr_ll, sizeof(addr_ll))) {
++ PMD_DRV_LOG(ERR, "bind failed: %s", strerror(errno));
++ close(sockfd);
++ return -1;
++ }
++
++ ifr.ifr_flags |= IFF_PROMISC | IFF_UP;
++
++ if (ioctl(sockfd, SIOCSIFFLAGS, (char*)&ifr)) {
++ PMD_DRV_LOG(ERR, "SIOCSIFFLAGS failed: %s", strerror(errno));
++ close(sockfd);
++ return -1;
++ }
++
++ ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
++ if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) == 0)
++ memcpy(mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
++
++ return vhost_kernel_set_sock(sockfd, hdr_size, req_mq);
++}
+diff --git a/drivers/net/virtio/virtio_user/vhost_kernel_tap.c b/drivers/net/virtio/virtio_user/vhost_kernel_tap.c
+index a3faf1d0c..85dd24dd6 100644
+--- a/drivers/net/virtio/virtio_user/vhost_kernel_tap.c
++++ b/drivers/net/virtio/virtio_user/vhost_kernel_tap.c
+@@ -11,13 +11,75 @@
+ #include <errno.h>
+ #include <string.h>
+ #include <limits.h>
++#include <sys/ioctl.h>
+
+ #include <rte_ether.h>
+
+-#include "vhost_kernel_tap.h"
++#include "vhost_kernel.h"
+ #include "../virtio_logs.h"
+ #include "../virtio_pci.h"
+
++/* TUN ioctls */
++#define TUNSETIFF _IOW('T', 202, int)
++#define TUNGETFEATURES _IOR('T', 207, unsigned int)
++#define TUNSETOFFLOAD _IOW('T', 208, unsigned int)
++#define TUNGETIFF _IOR('T', 210, unsigned int)
++#define TUNSETSNDBUF _IOW('T', 212, int)
++#define TUNGETVNETHDRSZ _IOR('T', 215, int)
++#define TUNSETVNETHDRSZ _IOW('T', 216, int)
++#define TUNSETQUEUE _IOW('T', 217, int)
++#define TUNSETVNETLE _IOW('T', 220, int)
++#define TUNSETVNETBE _IOW('T', 222, int)
++
++/* TUNSETIFF ifr flags */
++#define IFF_TAP 0x0002
++#define IFF_NO_PI 0x1000
++#define IFF_ONE_QUEUE 0x2000
++#define IFF_VNET_HDR 0x4000
++#define IFF_MULTI_QUEUE 0x0100
++#define IFF_ATTACH_QUEUE 0x0200
++#define IFF_DETACH_QUEUE 0x0400
++
++/* Features for GSO (TUNSETOFFLOAD). */
++#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */
++#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */
++#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */
++#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */
++#define TUN_F_UFO 0x10 /* I can handle UFO packets */
++
++/* Constants */
++#define PATH_NET_TUN "/dev/net/tun"
++
++void
++tap_support_features(int *vnet_hdr, int *mq)
++{
++ int tapfd;
++ unsigned int tap_features;
++
++ *vnet_hdr = 0;
++ *mq = 0;
++
++ tapfd = open(PATH_NET_TUN, O_RDWR);
++ if (tapfd < 0) {
++ PMD_DRV_LOG(ERR, "fail to open %s: %s",
++ PATH_NET_TUN, strerror(errno));
++ return;
++ }
++
++ if (ioctl(tapfd, TUNGETFEATURES, &tap_features) == -1) {
++ PMD_DRV_LOG(ERR, "TUNGETFEATURES failed: %s", strerror(errno));
++ close(tapfd);
++ return;
++ }
++
++ close(tapfd);
++
++ if (tap_features & IFF_VNET_HDR)
++ *vnet_hdr = 1;
++ if (tap_features & IFF_MULTI_QUEUE)
++ *mq = 1;
++}
++
+ static int
+ vhost_kernel_tap_set_offload(int fd, uint64_t features)
+ {
+diff --git a/drivers/net/virtio/virtio_user/vhost_kernel_tap.h b/drivers/net/virtio/virtio_user/vhost_kernel_tap.h
+deleted file mode 100644
+index e0e95b4f5..000000000
+--- a/drivers/net/virtio/virtio_user/vhost_kernel_tap.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-/* SPDX-License-Identifier: BSD-3-Clause
+- * Copyright(c) 2016 Intel Corporation
+- */
+-
+-#include <sys/ioctl.h>
+-
+-/* TUN ioctls */
+-#define TUNSETIFF _IOW('T', 202, int)
+-#define TUNGETFEATURES _IOR('T', 207, unsigned int)
+-#define TUNSETOFFLOAD _IOW('T', 208, unsigned int)
+-#define TUNGETIFF _IOR('T', 210, unsigned int)
+-#define TUNSETSNDBUF _IOW('T', 212, int)
+-#define TUNGETVNETHDRSZ _IOR('T', 215, int)
+-#define TUNSETVNETHDRSZ _IOW('T', 216, int)
+-#define TUNSETQUEUE _IOW('T', 217, int)
+-#define TUNSETVNETLE _IOW('T', 220, int)
+-#define TUNSETVNETBE _IOW('T', 222, int)
+-
+-/* TUNSETIFF ifr flags */
+-#define IFF_TAP 0x0002
+-#define IFF_NO_PI 0x1000
+-#define IFF_ONE_QUEUE 0x2000
+-#define IFF_VNET_HDR 0x4000
+-#define IFF_MULTI_QUEUE 0x0100
+-#define IFF_ATTACH_QUEUE 0x0200
+-#define IFF_DETACH_QUEUE 0x0400
+-
+-/* Features for GSO (TUNSETOFFLOAD). */
+-#define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */
+-#define TUN_F_TSO4 0x02 /* I can handle TSO for IPv4 packets */
+-#define TUN_F_TSO6 0x04 /* I can handle TSO for IPv6 packets */
+-#define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */
+-#define TUN_F_UFO 0x10 /* I can handle UFO packets */
+-
+-/* Constants */
+-#define PATH_NET_TUN "/dev/net/tun"
+-
+-int vhost_kernel_open_tap(char **p_ifname, int hdr_size, int req_mq,
+- const char *mac, uint64_t features);
+diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c
+index 20816c936..7e655a0d5 100644
+--- a/drivers/net/virtio/virtio_user/virtio_user_dev.c
++++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c
+@@ -294,7 +294,7 @@ virtio_user_fill_intr_handle(struct virtio_user_dev *dev)
+ eth_dev->intr_handle->max_intr = dev->max_queue_pairs + 1;
+ eth_dev->intr_handle->type = RTE_INTR_HANDLE_VDEV;
+ /* For virtio vdev, no need to read counter for clean */
+- eth_dev->intr_handle->efd_counter_size = 0;
++ eth_dev->intr_handle->efd_counter_size = 8;
+ eth_dev->intr_handle->fd = -1;
+ if (dev->vhostfd >= 0)
+ eth_dev->intr_handle->fd = dev->vhostfd;
+@@ -312,7 +312,9 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
+ {
+ struct virtio_user_dev *dev = arg;
+ struct rte_memseg_list *msl;
++#if 0
+ uint16_t i;
++#endif
+
+ /* ignore externally allocated memory */
+ msl = rte_mem_virt2memseg_list(addr);
+@@ -325,15 +327,19 @@ virtio_user_mem_event_cb(enum rte_mem_event type __rte_unused,
+ goto exit;
+
+ /* Step 1: pause the active queues */
++#if 0
+ for (i = 0; i < dev->queue_pairs; i++)
+ dev->ops->enable_qp(dev, i, 0);
++#endif
+
+ /* Step 2: update memory regions */
+ dev->ops->send_request(dev, VHOST_USER_SET_MEM_TABLE, NULL);
+
+ /* Step 3: resume the active queues */
++#if 0
+ for (i = 0; i < dev->queue_pairs; i++)
+ dev->ops->enable_qp(dev, i, 1);
++#endif
+
+ exit:
+ pthread_mutex_unlock(&dev->mutex);
+@@ -412,7 +418,7 @@ virtio_user_dev_setup(struct virtio_user_dev *dev)
+ int
+ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
+ int cq, int queue_size, const char *mac, char **ifname,
+- int mrg_rxbuf, int in_order)
++ int mrg_rxbuf, int in_order, int fd)
+ {
+ pthread_mutex_init(&dev->mutex, NULL);
+ snprintf(dev->path, PATH_MAX, "%s", path);
+@@ -435,6 +441,12 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
+ return -1;
+ }
+
++ if (fd >= 0) {
++ dev->be_fd = fd;
++ } else {
++ dev->be_fd = -1;
++ }
++
+ if (!dev->is_server) {
+ if (dev->ops->send_request(dev, VHOST_USER_SET_OWNER,
+ NULL) < 0) {
+diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h
+index c42ce5d4b..575c21e3b 100644
+--- a/drivers/net/virtio/virtio_user/virtio_user_dev.h
++++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h
+@@ -21,6 +21,7 @@ struct virtio_user_dev {
+ char *ifname;
+ int *vhostfds;
+ int *tapfds;
++ int be_fd;
+
+ /* for both vhost_user and vhost_kernel */
+ int callfds[VIRTIO_MAX_VIRTQUEUES];
+@@ -50,7 +51,7 @@ int virtio_user_start_device(struct virtio_user_dev *dev);
+ int virtio_user_stop_device(struct virtio_user_dev *dev);
+ int virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues,
+ int cq, int queue_size, const char *mac, char **ifname,
+- int mrg_rxbuf, int in_order);
++ int mrg_rxbuf, int in_order, int fd);
+ void virtio_user_dev_uninit(struct virtio_user_dev *dev);
+ void virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx);
+ uint8_t virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs);
+diff --git a/drivers/net/virtio/virtio_user_ethdev.c b/drivers/net/virtio/virtio_user_ethdev.c
+index f8791391a..d5e87b24c 100644
+--- a/drivers/net/virtio/virtio_user_ethdev.c
++++ b/drivers/net/virtio/virtio_user_ethdev.c
+@@ -221,8 +221,7 @@ virtio_user_get_features(struct virtio_hw *hw)
+ {
+ struct virtio_user_dev *dev = virtio_user_get_dev(hw);
+
+- /* unmask feature bits defined in vhost user protocol */
+- return dev->device_features & VIRTIO_PMD_SUPPORTED_GUEST_FEATURES;
++ return dev->device_features;
+ }
+
+ static void
+@@ -361,6 +360,8 @@ static const char *valid_args[] = {
+ VIRTIO_USER_ARG_MRG_RXBUF,
+ #define VIRTIO_USER_ARG_IN_ORDER "in_order"
+ VIRTIO_USER_ARG_IN_ORDER,
++#define VIRTIO_USER_ARG_FD "fd"
++ VIRTIO_USER_ARG_FD,
+ NULL
+ };
+
+@@ -464,6 +465,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
+ uint64_t server_mode = VIRTIO_USER_DEF_SERVER_MODE;
+ uint64_t mrg_rxbuf = 1;
+ uint64_t in_order = 1;
++ uint64_t fd = -1;
+ char *path = NULL;
+ char *ifname = NULL;
+ char *mac_addr = NULL;
+@@ -581,6 +583,15 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
+ }
+ }
+
++ if (rte_kvargs_count(kvlist, VIRTIO_USER_ARG_FD) == 1) {
++ if (rte_kvargs_process(kvlist, VIRTIO_USER_ARG_FD,
++ &get_integer_arg, &fd) < 0) {
++ PMD_INIT_LOG(ERR, "error to parse %s",
++ VIRTIO_USER_ARG_FD);
++ goto end;
++ }
++ }
++
+ if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+ struct virtio_user_dev *vu_dev;
+
+@@ -598,7 +609,7 @@ virtio_user_pmd_probe(struct rte_vdev_device *dev)
+ vu_dev->is_server = false;
+ if (virtio_user_dev_init(hw->virtio_user_dev, path, queues, cq,
+ queue_size, mac_addr, &ifname, mrg_rxbuf,
+- in_order) < 0) {
++ in_order, fd) < 0) {
+ PMD_INIT_LOG(ERR, "virtio_user_dev_init fails");
+ virtio_user_eth_dev_free(eth_dev);
+ goto end;
+@@ -677,4 +688,5 @@ RTE_PMD_REGISTER_PARAM_STRING(net_virtio_user,
+ "iface=<string> "
+ "server=<0|1> "
+ "mrg_rxbuf=<0|1> "
+- "in_order=<0|1>");
++ "in_order=<0|1>"
++ "fd=<int>");
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0006-mempool-add-dynamic-mempool-support.patch b/dpdk/dpdk-v18.11_patches/0006-mempool-add-dynamic-mempool-support.patch
new file mode 100644
index 0000000..bcc9743
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0006-mempool-add-dynamic-mempool-support.patch
@@ -0,0 +1,247 @@
+From 9d2ddfe6012b37297bc84f6ddcce810232162e5b Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed, 26 Dec 2018 14:39:24 +0000
+Subject: [PATCH 1/2] mempool: add dynamic mempool support
+
+Signed-off-by: Jianfeng Tan <henry.tjf@antfin.com>
+---
+ drivers/mempool/ring/rte_mempool_ring.c | 26 +++++++----
+ lib/librte_mempool/rte_mempool.c | 27 +++++++++--
+ lib/librte_mempool/rte_mempool.h | 62 ++++++++++++++++++++-----
+ 3 files changed, 92 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/mempool/ring/rte_mempool_ring.c b/drivers/mempool/ring/rte_mempool_ring.c
+index bc123fc52..e8fec9119 100644
+--- a/drivers/mempool/ring/rte_mempool_ring.c
++++ b/drivers/mempool/ring/rte_mempool_ring.c
+@@ -49,30 +49,40 @@ common_ring_get_count(const struct rte_mempool *mp)
+ static int
+ common_ring_alloc(struct rte_mempool *mp)
+ {
++ int n;
+ int rg_flags = 0, ret;
+ char rg_name[RTE_RING_NAMESIZE];
+ struct rte_ring *r;
+
+- ret = snprintf(rg_name, sizeof(rg_name),
+- RTE_MEMPOOL_MZ_FORMAT, mp->name);
+- if (ret < 0 || ret >= (int)sizeof(rg_name)) {
+- rte_errno = ENAMETOOLONG;
+- return -rte_errno;
+- }
+-
+ /* ring flags */
+ if (mp->flags & MEMPOOL_F_SP_PUT)
+ rg_flags |= RING_F_SP_ENQ;
+ if (mp->flags & MEMPOOL_F_SC_GET)
+ rg_flags |= RING_F_SC_DEQ;
+
++ if (mp->flags & MEMPOOL_F_DYNAMIC) {
++ n = RTE_MIN(mp->size, mp->populated_size + mp->dynamic_size);
++
++ ret = snprintf(rg_name, sizeof(rg_name),
++ RTE_MEMPOOL_MZ_FORMAT"_%x", mp->name, n);
++ } else {
++ n = mp->size;
++ ret = snprintf(rg_name, sizeof(rg_name),
++ RTE_MEMPOOL_MZ_FORMAT, mp->name);
++ }
++
++ if (ret < 0 || ret >= (int)sizeof(rg_name)) {
++ rte_errno = ENAMETOOLONG;
++ return -rte_errno;
++ }
++
+ /*
+ * Allocate the ring that will be used to store objects.
+ * Ring functions will return appropriate errors if we are
+ * running as a secondary process etc., so no checks made
+ * in this function for that condition.
+ */
+- r = rte_ring_create(rg_name, rte_align32pow2(mp->size + 1),
++ r = rte_ring_create(rg_name, rte_align32pow2(n + 1),
+ mp->socket_id, rg_flags);
+ if (r == NULL)
+ return -rte_errno;
+diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
+index 683b216f9..70039f6c3 100644
+--- a/lib/librte_mempool/rte_mempool.c
++++ b/lib/librte_mempool/rte_mempool.c
+@@ -152,6 +152,8 @@ mempool_add_elem(struct rte_mempool *mp, __rte_unused void *opaque,
+ hdr->mp = mp;
+ hdr->iova = iova;
+ STAILQ_INSERT_TAIL(&mp->elt_list, hdr, next);
++ if (mp->flags & MEMPOOL_F_DYNAMIC && mp->dyn_obj_cb)
++ mp->dyn_obj_cb(mp, NULL, obj, mp->populated_size);
+ mp->populated_size++;
+
+ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG
+@@ -426,9 +428,10 @@ rte_mempool_populate_default(struct rte_mempool *mp)
+ ssize_t mem_size;
+ size_t align, pg_sz, pg_shift;
+ rte_iova_t iova;
+- unsigned mz_id, n;
++ unsigned mz_id, n, avail;
+ int ret;
+ bool no_contig, try_contig, no_pageshift, external;
++ bool dynamic = (mp->flags & MEMPOOL_F_DYNAMIC) ? true : false;
+
+ ret = mempool_ops_alloc_once(mp);
+ if (ret != 0)
+@@ -441,7 +444,7 @@ rte_mempool_populate_default(struct rte_mempool *mp)
+ external = ret;
+
+ /* mempool must not be populated */
+- if (mp->nb_mem_chunks != 0)
++ if (mp->nb_mem_chunks != 0 && !dynamic)
+ return -EEXIST;
+
+ no_contig = mp->flags & MEMPOOL_F_NO_IOVA_CONTIG;
+@@ -512,7 +515,16 @@ rte_mempool_populate_default(struct rte_mempool *mp)
+ pg_shift = rte_bsf32(pg_sz);
+ }
+
+- for (mz_id = 0, n = mp->size; n > 0; mz_id++, n -= ret) {
++ n = mp->size;
++ if (dynamic) {
++ n = RTE_MIN(mp->size - mp->populated_size, mp->dynamic_size);
++ if (mp->nb_mem_chunks != 0 && rte_mempool_ops_alloc(mp) != 0)
++ return -ENOMEM;
++ }
++
++ avail = 0;
++ mz_id = mp->nb_mem_chunks;
++ for (; n > 0; mz_id++, n -= ret, avail += ret) {
+ size_t min_chunk_size;
+ unsigned int flags;
+
+@@ -607,9 +619,16 @@ rte_mempool_populate_default(struct rte_mempool *mp)
+ }
+ }
+
+- return mp->size;
++ return avail;
+
+ fail:
++ if (dynamic) {
++ if (avail)
++ return avail;
++
++ return ret;
++ }
++
+ rte_mempool_free_memchunks(mp);
+ return ret;
+ }
+diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
+index 7c9cd9a2f..0886b19f2 100644
+--- a/lib/librte_mempool/rte_mempool.h
++++ b/lib/librte_mempool/rte_mempool.h
+@@ -207,6 +207,16 @@ struct rte_mempool_info {
+ unsigned int contig_block_size;
+ } __rte_cache_aligned;
+
++struct rte_mempool;
++/**
++ * An object callback function for mempool.
++ *
++ * Used by rte_mempool_create() and rte_mempool_obj_iter().
++ */
++typedef void (rte_mempool_obj_cb_t)(struct rte_mempool *mp,
++ void *opaque, void *obj, unsigned obj_idx);
++typedef rte_mempool_obj_cb_t rte_mempool_obj_ctor_t; /* compat */
++
+ /**
+ * The RTE mempool structure.
+ */
+@@ -247,6 +257,8 @@ struct rte_mempool {
+ struct rte_mempool_cache *local_cache; /**< Per-lcore local cache */
+
+ uint32_t populated_size; /**< Number of populated objects. */
++ uint32_t dynamic_size; /**< Number of dynamic populated objects. */
++ rte_mempool_obj_cb_t *dyn_obj_cb; /**< elem cb for dynamic populated objects. */
+ struct rte_mempool_objhdr_list elt_list; /**< List of objects in pool */
+ uint32_t nb_mem_chunks; /**< Number of memory chunks */
+ struct rte_mempool_memhdr_list mem_list; /**< List of memory chunks */
+@@ -264,6 +276,8 @@ struct rte_mempool {
+ #define MEMPOOL_F_POOL_CREATED 0x0010 /**< Internal: pool is created. */
+ #define MEMPOOL_F_NO_IOVA_CONTIG 0x0020 /**< Don't need IOVA contiguous objs. */
+ #define MEMPOOL_F_NO_PHYS_CONTIG MEMPOOL_F_NO_IOVA_CONTIG /* deprecated */
++#define MEMPOOL_F_DYNAMIC 0x0040 /**< Don't populate element once for all */
++#define MEMPOOL_F_DYNAMIC_NOW 0x0080 /**< It's is dynamically populated now */
+
+ /**
+ * @internal When debug is enabled, store some statistics.
+@@ -839,15 +853,6 @@ int rte_mempool_register_ops(const struct rte_mempool_ops *ops);
+ rte_mempool_register_ops(&ops); \
+ }
+
+-/**
+- * An object callback function for mempool.
+- *
+- * Used by rte_mempool_create() and rte_mempool_obj_iter().
+- */
+-typedef void (rte_mempool_obj_cb_t)(struct rte_mempool *mp,
+- void *opaque, void *obj, unsigned obj_idx);
+-typedef rte_mempool_obj_cb_t rte_mempool_obj_ctor_t; /* compat */
+-
+ /**
+ * A memory callback function for mempool.
+ *
+@@ -989,6 +994,22 @@ struct rte_mempool *
+ rte_mempool_create_empty(const char *name, unsigned n, unsigned elt_size,
+ unsigned cache_size, unsigned private_data_size,
+ int socket_id, unsigned flags);
++
++static inline void
++rte_mempool_set_dynamic_size(struct rte_mempool *mp, int dynamic_size)
++{
++ mp->flags |= MEMPOOL_F_DYNAMIC;
++ mp->dynamic_size = dynamic_size;
++}
++
++static inline void
++rte_mempool_set_dynamic_cb(struct rte_mempool *mp,
++ rte_mempool_obj_cb_t *dyn_obj_cb)
++{
++ mp->flags |= MEMPOOL_F_DYNAMIC;
++ mp->dyn_obj_cb = dyn_obj_cb;
++}
++
+ /**
+ * Free a mempool
+ *
+@@ -1390,9 +1411,28 @@ __mempool_generic_get(struct rte_mempool *mp, void **obj_table,
+ /* get remaining objects from ring */
+ ret = rte_mempool_ops_dequeue_bulk(mp, obj_table, n);
+
+- if (ret < 0)
++ if (ret < 0) {
++ if (mp->flags & MEMPOOL_F_DYNAMIC &&
++ mp->populated_size < mp->size) {
++ int work;
++
++ work = rte_atomic32_cmpset(&mp->flags,
++ mp->flags & ~MEMPOOL_F_DYNAMIC_NOW,
++ mp->flags | MEMPOOL_F_DYNAMIC_NOW);
++ if (work) {
++ int more;
++
++ more = rte_mempool_populate_default(mp);
++ mp->flags &= ~MEMPOOL_F_DYNAMIC_NOW;
++ if (more > 0)
++ goto ring_dequeue;
++ } else {
++ /* mempool is populating, try again */
++ goto ring_dequeue;
++ }
++ }
+ __MEMPOOL_STAT_ADD(mp, get_fail, n);
+- else
++ } else
+ __MEMPOOL_STAT_ADD(mp, get_success, n);
+
+ return ret;
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0007-mbuf-add-dynamic-mbuf-mempool-support.patch b/dpdk/dpdk-v18.11_patches/0007-mbuf-add-dynamic-mbuf-mempool-support.patch
new file mode 100644
index 0000000..8618928
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0007-mbuf-add-dynamic-mbuf-mempool-support.patch
@@ -0,0 +1,305 @@
+From c2a2b8eec349156b31f2faab61cc6063ef3f0c61 Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed, 26 Dec 2018 14:40:07 +0000
+Subject: [PATCH 2/2] mbuf: add dynamic mbuf mempool support
+
+Signed-off-by: Jianfeng Tan <henry.tjf@antfin.com>
+---
+ examples/Makefile | 1 +
+ examples/dynamic_mbuf_pool/Makefile | 56 ++++++++++++++++
+ examples/dynamic_mbuf_pool/main.c | 92 ++++++++++++++++++++++++++
+ examples/dynamic_mbuf_pool/meson.build | 11 +++
+ lib/librte_mbuf/rte_mbuf.c | 51 ++++++++++++++
+ lib/librte_mbuf/rte_mbuf.h | 5 ++
+ lib/librte_mbuf/rte_mbuf_version.map | 8 ++-
+ 7 files changed, 223 insertions(+), 1 deletion(-)
+ create mode 100644 examples/dynamic_mbuf_pool/Makefile
+ create mode 100644 examples/dynamic_mbuf_pool/main.c
+ create mode 100644 examples/dynamic_mbuf_pool/meson.build
+
+diff --git a/examples/Makefile b/examples/Makefile
+index 33fe0e586..3df9cb7ad 100644
+--- a/examples/Makefile
++++ b/examples/Makefile
+@@ -21,6 +21,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_CRYPTODEV) += fips_validation
+ DIRS-$(CONFIG_RTE_LIBRTE_FLOW_CLASSIFY) += flow_classify
+ DIRS-y += flow_filtering
+ DIRS-y += helloworld
++DIRS-y += dynamic_mbuf_pool
+ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += ip_pipeline
+ ifeq ($(CONFIG_RTE_LIBRTE_LPM),y)
+ DIRS-$(CONFIG_RTE_IP_FRAG) += ip_reassembly
+diff --git a/examples/dynamic_mbuf_pool/Makefile b/examples/dynamic_mbuf_pool/Makefile
+new file mode 100644
+index 000000000..f2761f661
+--- /dev/null
++++ b/examples/dynamic_mbuf_pool/Makefile
+@@ -0,0 +1,56 @@
++# SPDX-License-Identifier: BSD-3-Clause
++# Copyright(c) 2010-2014 Intel Corporation
++
++# binary name
++APP = dynamic_mbuf_pool
++
++# all source are stored in SRCS-y
++SRCS-y := main.c
++
++# Build using pkg-config variables if possible
++$(shell pkg-config --exists libdpdk)
++ifeq ($(.SHELLSTATUS),0)
++
++all: shared
++.PHONY: shared static
++shared: build/$(APP)-shared
++ ln -sf $(APP)-shared build/$(APP)
++static: build/$(APP)-static
++ ln -sf $(APP)-static build/$(APP)
++
++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)
++
++build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
++ $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
++
++build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
++ $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
++
++build:
++ @mkdir -p $@
++
++.PHONY: clean
++clean:
++ rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
++ rmdir --ignore-fail-on-non-empty build
++
++else
++
++ifeq ($(RTE_SDK),)
++$(error "Please define RTE_SDK environment variable")
++endif
++
++# Default target, can be overridden by command line or environment
++RTE_TARGET ?= x86_64-native-linuxapp-gcc
++
++include $(RTE_SDK)/mk/rte.vars.mk
++
++CFLAGS += -O3
++CFLAGS += $(WERROR_FLAGS)
++
++include $(RTE_SDK)/mk/rte.extapp.mk
++
++endif
+diff --git a/examples/dynamic_mbuf_pool/main.c b/examples/dynamic_mbuf_pool/main.c
+new file mode 100644
+index 000000000..a568d7cec
+--- /dev/null
++++ b/examples/dynamic_mbuf_pool/main.c
+@@ -0,0 +1,92 @@
++/* SPDX-License-Identifier: BSD-3-Clause
++ * Copyright(c) 2010-2014 Intel Corporation
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include <stdint.h>
++#include <errno.h>
++#include <sys/queue.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++
++#include <rte_memory.h>
++#include <rte_launch.h>
++#include <rte_eal.h>
++#include <rte_per_lcore.h>
++#include <rte_lcore.h>
++#include <rte_debug.h>
++#include <rte_memory.h>
++#include <rte_mbuf.h>
++#include <rte_memzone.h>
++
++#define HUGE_2M "/sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages"
++#define HUGE_1G "/sys/kernel/mm/hugepages/hugepages-1048576kB/free_hugepages"
++
++static long int
++get_value(const char *path)
++{
++ int fd, len;
++ long int value;
++ char buf[1024];
++
++ fd = open(path, O_RDONLY);
++ if (fd < 0)
++ return ULONG_MAX;
++
++ len = read(fd, buf, sizeof(buf));
++
++ close(fd);
++
++ if (len <= 0) {
++ return ULONG_MAX;
++ }
++
++ value = strtol(buf, NULL, 10);
++ return value;
++}
++
++static void
++print_free_hugepages(void)
++{
++ printf("2M: %ld\t\t1G: %ld\n", get_value(HUGE_2M), get_value(HUGE_1G));
++}
++
++int
++main(int argc, char **argv)
++{
++ int i;
++ int ret;
++ int n = 512 * 1024;
++ int dynamic_size = 8 * 1024;
++ struct rte_mbuf *m;
++ struct rte_mempool *mp;
++
++ ret = rte_eal_init(argc, argv);
++ if (ret < 0)
++ rte_panic("Cannot init EAL\n");
++
++ mp = rte_pktmbuf_dynamic_pool_create("mbuf_pool", n,
++ 64, 0, RTE_MBUF_DEFAULT_BUF_SIZE,
++ 0, dynamic_size);
++ if (mp == NULL)
++ rte_panic("Failed to create mbuf mempool");
++
++ for (i = 0; i < n; i++) {
++ m = rte_pktmbuf_alloc(mp);
++ if (m == NULL)
++ break;
++
++ if ((i % dynamic_size) == 1) {
++ print_free_hugepages();
++ usleep(100 * 1000);
++ }
++ }
++
++ printf("have allocated %d mbufs", i);
++ rte_memzone_dump(stdout);
++
++ return 0;
++}
+diff --git a/examples/dynamic_mbuf_pool/meson.build b/examples/dynamic_mbuf_pool/meson.build
+new file mode 100644
+index 000000000..c34e11e36
+--- /dev/null
++++ b/examples/dynamic_mbuf_pool/meson.build
+@@ -0,0 +1,11 @@
++# SPDX-License-Identifier: BSD-3-Clause
++# Copyright(c) 2017 Intel Corporation
++
++# meson file, for building this example as part of a main DPDK build.
++#
++# To build this example as a standalone application with an already-installed
++# DPDK instance, use 'make'
++
++sources = files(
++ 'main.c'
++)
+diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c
+index 9790b4fb1..b70abd88c 100644
+--- a/lib/librte_mbuf/rte_mbuf.c
++++ b/lib/librte_mbuf/rte_mbuf.c
+@@ -167,6 +167,57 @@ rte_pktmbuf_pool_create(const char *name, unsigned int n,
+ data_room_size, socket_id, NULL);
+ }
+
++struct rte_mempool *
++rte_pktmbuf_dynamic_pool_create(const char *name, unsigned int n,
++ unsigned int cache_size, uint16_t priv_size,
++ uint16_t data_room_size, int socket_id, int dynamic_size)
++{
++ struct rte_mempool *mp;
++ struct rte_pktmbuf_pool_private mbp_priv;
++ const char *mp_ops_name;
++ unsigned elt_size;
++ int ret;
++
++ if (RTE_ALIGN(priv_size, RTE_MBUF_PRIV_ALIGN) != priv_size) {
++ RTE_LOG(ERR, MBUF, "mbuf priv_size=%u is not aligned\n",
++ priv_size);
++ rte_errno = EINVAL;
++ return NULL;
++ }
++ elt_size = sizeof(struct rte_mbuf) + (unsigned)priv_size +
++ (unsigned)data_room_size;
++ mbp_priv.mbuf_data_room_size = data_room_size;
++ mbp_priv.mbuf_priv_size = priv_size;
++
++ mp = rte_mempool_create_empty(name, n, elt_size, cache_size,
++ sizeof(struct rte_pktmbuf_pool_private),
++ socket_id, MEMPOOL_F_DYNAMIC);
++ if (mp == NULL)
++ return NULL;
++
++ mp_ops_name = rte_mbuf_best_mempool_ops();
++ ret = rte_mempool_set_ops_byname(mp, mp_ops_name, NULL);
++ if (ret != 0) {
++ RTE_LOG(ERR, MBUF, "error setting mempool handler\n");
++ rte_mempool_free(mp);
++ rte_errno = -ret;
++ return NULL;
++ }
++ rte_pktmbuf_pool_init(mp, &mbp_priv);
++
++ rte_mempool_set_dynamic_size(mp, dynamic_size);
++ rte_mempool_set_dynamic_cb(mp, rte_pktmbuf_init);
++
++ ret = rte_mempool_populate_default(mp);
++ if (ret < 0) {
++ rte_mempool_free(mp);
++ rte_errno = -ret;
++ return NULL;
++ }
++
++ return mp;
++}
++
+ /* do some sanity checks on a mbuf: panic if it fails */
+ void
+ rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header)
+diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h
+index 3dbc6695e..5a2d81605 100644
+--- a/lib/librte_mbuf/rte_mbuf.h
++++ b/lib/librte_mbuf/rte_mbuf.h
+@@ -1183,6 +1183,11 @@ rte_pktmbuf_pool_create(const char *name, unsigned n,
+ unsigned cache_size, uint16_t priv_size, uint16_t data_room_size,
+ int socket_id);
+
++struct rte_mempool *
++rte_pktmbuf_dynamic_pool_create(const char *name, unsigned int n,
++ unsigned int cache_size, uint16_t priv_size,
++ uint16_t data_room_size, int socket_id, int dynamic_size);
++
+ /**
+ * Create a mbuf pool with a given mempool ops name
+ *
+diff --git a/lib/librte_mbuf/rte_mbuf_version.map b/lib/librte_mbuf/rte_mbuf_version.map
+index cae68db8d..d6d25af95 100644
+--- a/lib/librte_mbuf/rte_mbuf_version.map
++++ b/lib/librte_mbuf/rte_mbuf_version.map
+@@ -44,4 +44,10 @@ DPDK_18.08 {
+ rte_mbuf_set_user_mempool_ops;
+ rte_mbuf_user_mempool_ops;
+ rte_pktmbuf_pool_create_by_ops;
+-} DPDK_16.11;
++} DPDK_18.11;
++
++DPDK_18.11 {
++ global:
++
++ rte_pktmbuf_dynamic_pool_create;
++} DPDK_18.12;
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0008-mempool-prioritize-constructor.patch b/dpdk/dpdk-v18.11_patches/0008-mempool-prioritize-constructor.patch
new file mode 100644
index 0000000..c941443
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0008-mempool-prioritize-constructor.patch
@@ -0,0 +1,30 @@
+From cd36895a4a7bfc342915b42e3856bd233452f0bd Mon Sep 17 00:00:00 2001
+From: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Fri, 13 Jul 2018 15:25:22 +0800
+Subject: [PATCH 1/9] mempool: prioritize constructor
+
+---
+ lib/librte_mempool/rte_mempool.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
+index 7c9cd9a2f..bdc32d583 100644
+--- a/lib/librte_mempool/rte_mempool.h
++++ b/lib/librte_mempool/rte_mempool.h
+@@ -833,10 +833,10 @@ int rte_mempool_register_ops(const struct rte_mempool_ops *ops);
+ * more than RTE_MEMPOOL_MAX_OPS_IDX is registered.
+ */
+ #define MEMPOOL_REGISTER_OPS(ops) \
+- void mp_hdlr_init_##ops(void); \
+- void __attribute__((constructor, used)) mp_hdlr_init_##ops(void)\
++ static void __attribute__((constructor(101), used)) \
++ mp_hdlr_init_##ops(void) \
+ { \
+- rte_mempool_register_ops(&ops); \
++ rte_mempool_register_ops(&ops); \
+ }
+
+ /**
+--
+2.17.1
+
diff --git a/dpdk/dpdk-v18.11_patches/0009-net-virtio-fill-desc-limit.patch b/dpdk/dpdk-v18.11_patches/0009-net-virtio-fill-desc-limit.patch
new file mode 100644
index 0000000..146ea88
--- /dev/null
+++ b/dpdk/dpdk-v18.11_patches/0009-net-virtio-fill-desc-limit.patch
@@ -0,0 +1,42 @@
+commit 470acd1b108f20ae12b1216c9f6157b78655bcc7
+Author: Jianfeng Tan <henry.tjf@antfin.com>
+Date: Wed Dec 12 02:14:03 2018 +0000
+
+ net/virtio: fill desc limit
+
+ We shall fill desc limit accordingly, or APIs, such as
+ rte_eth_dev_adjust_nb_rx_tx_desc, will not give correct desc
+ information.
+
+ Signed-off-by: Jianfeng Tan <henry.tjf@antfin.com>
+
+diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
+index dbfa6865c..d369d5ce8 100644
+--- a/drivers/net/virtio/virtio_ethdev.c
++++ b/drivers/net/virtio/virtio_ethdev.c
+@@ -2172,6 +2172,7 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
+ {
+ uint64_t tso_mask, host_features;
+ struct virtio_hw *hw = dev->data->dev_private;
++ struct virtqueue *vq;
+
+ dev_info->speed_capa = ETH_LINK_SPEED_10G; /* fake value */
+
+@@ -2209,6 +2210,17 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
+ (1ULL << VIRTIO_NET_F_HOST_TSO6);
+ if ((host_features & tso_mask) == tso_mask)
+ dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO;
++
++
++ if (hw->vqs) {
++ vq = hw->vqs[VTNET_SQ_RQ_QUEUE_IDX];
++ dev_info->rx_desc_lim.nb_max = vq->vq_nentries;
++ dev_info->rx_desc_lim.nb_min = 256;
++
++ vq = hw->vqs[VTNET_SQ_TQ_QUEUE_IDX];
++ dev_info->tx_desc_lim.nb_max = vq->vq_nentries;
++ dev_info->tx_desc_lim.nb_min = 256;
++ }
+ }
+
+ /*