summaryrefslogtreecommitdiffstats
path: root/src/spdk/dpdk/lib/librte_net
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdk/dpdk/lib/librte_net')
-rw-r--r--src/spdk/dpdk/lib/librte_net/Makefile25
-rw-r--r--src/spdk/dpdk/lib/librte_net/meson.build19
-rw-r--r--src/spdk/dpdk/lib/librte_net/net_crc_neon.h269
-rw-r--r--src/spdk/dpdk/lib/librte_net/net_crc_sse.h334
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_arp.c50
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_arp.h74
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_esp.h32
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_ether.h418
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_gre.h43
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_icmp.h42
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_ip.h428
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_net.c496
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_net.h203
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_net_crc.c196
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_net_crc.h71
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_net_version.map21
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_sctp.h37
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_tcp.h42
-rw-r--r--src/spdk/dpdk/lib/librte_net/rte_udp.h37
19 files changed, 2837 insertions, 0 deletions
diff --git a/src/spdk/dpdk/lib/librte_net/Makefile b/src/spdk/dpdk/lib/librte_net/Makefile
new file mode 100644
index 00000000..85e403f4
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/Makefile
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2010-2014 Intel Corporation
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+LIB = librte_net.a
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+LDLIBS += -lrte_mbuf -lrte_eal -lrte_mempool
+
+EXPORT_MAP := rte_net_version.map
+LIBABIVER := 1
+
+SRCS-$(CONFIG_RTE_LIBRTE_NET) := rte_net.c
+SRCS-$(CONFIG_RTE_LIBRTE_NET) += rte_net_crc.c
+SRCS-$(CONFIG_RTE_LIBRTE_NET) += rte_arp.c
+
+# install includes
+SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include := rte_ip.h rte_tcp.h rte_udp.h rte_esp.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_sctp.h rte_icmp.h rte_arp.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_ether.h rte_gre.h rte_net.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_net_crc.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/src/spdk/dpdk/lib/librte_net/meson.build b/src/spdk/dpdk/lib/librte_net/meson.build
new file mode 100644
index 00000000..d3ea1feb
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/meson.build
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation
+
+version = 1
+allow_experimental_apis = true
+headers = files('rte_ip.h',
+ 'rte_tcp.h',
+ 'rte_udp.h',
+ 'rte_esp.h',
+ 'rte_sctp.h',
+ 'rte_icmp.h',
+ 'rte_arp.h',
+ 'rte_ether.h',
+ 'rte_gre.h',
+ 'rte_net.h',
+ 'rte_net_crc.h')
+
+sources = files('rte_arp.c', 'rte_net.c', 'rte_net_crc.c')
+deps += ['mbuf']
diff --git a/src/spdk/dpdk/lib/librte_net/net_crc_neon.h b/src/spdk/dpdk/lib/librte_net/net_crc_neon.h
new file mode 100644
index 00000000..63fa1d4a
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/net_crc_neon.h
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Cavium, Inc
+ */
+
+#ifndef _NET_CRC_NEON_H_
+#define _NET_CRC_NEON_H_
+
+#include <rte_branch_prediction.h>
+#include <rte_net_crc.h>
+#include <rte_vect.h>
+#include <rte_cpuflags.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** PMULL CRC computation context structure */
+struct crc_pmull_ctx {
+ uint64x2_t rk1_rk2;
+ uint64x2_t rk5_rk6;
+ uint64x2_t rk7_rk8;
+};
+
+struct crc_pmull_ctx crc32_eth_pmull __rte_aligned(16);
+struct crc_pmull_ctx crc16_ccitt_pmull __rte_aligned(16);
+
+/**
+ * @brief Performs one folding round
+ *
+ * Logically function operates as follows:
+ * DATA = READ_NEXT_16BYTES();
+ * F1 = LSB8(FOLD)
+ * F2 = MSB8(FOLD)
+ * T1 = CLMUL(F1, RK1)
+ * T2 = CLMUL(F2, RK2)
+ * FOLD = XOR(T1, T2, DATA)
+ *
+ * @param data_block 16 byte data block
+ * @param precomp precomputed rk1 constant
+ * @param fold running 16 byte folded data
+ *
+ * @return New 16 byte folded data
+ */
+static inline uint64x2_t
+crcr32_folding_round(uint64x2_t data_block, uint64x2_t precomp,
+ uint64x2_t fold)
+{
+ uint64x2_t tmp0 = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(fold), 1),
+ vgetq_lane_p64(vreinterpretq_p64_u64(precomp), 0)));
+
+ uint64x2_t tmp1 = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(fold), 0),
+ vgetq_lane_p64(vreinterpretq_p64_u64(precomp), 1)));
+
+ return veorq_u64(tmp1, veorq_u64(data_block, tmp0));
+}
+
+/**
+ * Performs reduction from 128 bits to 64 bits
+ *
+ * @param data128 128 bits data to be reduced
+ * @param precomp rk5 and rk6 precomputed constants
+ *
+ * @return data reduced to 64 bits
+ */
+static inline uint64x2_t
+crcr32_reduce_128_to_64(uint64x2_t data128,
+ uint64x2_t precomp)
+{
+ uint64x2_t tmp0, tmp1, tmp2;
+
+ /* 64b fold */
+ tmp0 = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(data128), 0),
+ vgetq_lane_p64(vreinterpretq_p64_u64(precomp), 0)));
+ tmp1 = vshift_bytes_right(data128, 8);
+ tmp0 = veorq_u64(tmp0, tmp1);
+
+ /* 32b fold */
+ tmp2 = vshift_bytes_left(tmp0, 4);
+ tmp1 = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(tmp2), 0),
+ vgetq_lane_p64(vreinterpretq_p64_u64(precomp), 1)));
+
+ return veorq_u64(tmp1, tmp0);
+}
+
+/**
+ * Performs Barret's reduction from 64 bits to 32 bits
+ *
+ * @param data64 64 bits data to be reduced
+ * @param precomp rk7 precomputed constant
+ *
+ * @return data reduced to 32 bits
+ */
+static inline uint32_t
+crcr32_reduce_64_to_32(uint64x2_t data64,
+ uint64x2_t precomp)
+{
+ static uint32_t mask1[4] __rte_aligned(16) = {
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000
+ };
+ static uint32_t mask2[4] __rte_aligned(16) = {
+ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff
+ };
+ uint64x2_t tmp0, tmp1, tmp2;
+
+ tmp0 = vandq_u64(data64, vld1q_u64((uint64_t *)mask2));
+
+ tmp1 = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(tmp0), 0),
+ vgetq_lane_p64(vreinterpretq_p64_u64(precomp), 0)));
+ tmp1 = veorq_u64(tmp1, tmp0);
+ tmp1 = vandq_u64(tmp1, vld1q_u64((uint64_t *)mask1));
+
+ tmp2 = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(tmp1), 0),
+ vgetq_lane_p64(vreinterpretq_p64_u64(precomp), 1)));
+ tmp2 = veorq_u64(tmp2, tmp1);
+ tmp2 = veorq_u64(tmp2, tmp0);
+
+ return vgetq_lane_u32(vreinterpretq_u32_u64(tmp2), 2);
+}
+
+static inline uint32_t
+crc32_eth_calc_pmull(
+ const uint8_t *data,
+ uint32_t data_len,
+ uint32_t crc,
+ const struct crc_pmull_ctx *params)
+{
+ uint64x2_t temp, fold, k;
+ uint32_t n;
+
+ /* Get CRC init value */
+ temp = vreinterpretq_u64_u32(vsetq_lane_u32(crc, vmovq_n_u32(0), 0));
+
+ /**
+ * Folding all data into single 16 byte data block
+ * Assumes: fold holds first 16 bytes of data
+ */
+ if (unlikely(data_len < 32)) {
+ if (unlikely(data_len == 16)) {
+ /* 16 bytes */
+ fold = vld1q_u64((const uint64_t *)data);
+ fold = veorq_u64(fold, temp);
+ goto reduction_128_64;
+ }
+
+ if (unlikely(data_len < 16)) {
+ /* 0 to 15 bytes */
+ uint8_t buffer[16] __rte_aligned(16);
+
+ memset(buffer, 0, sizeof(buffer));
+ memcpy(buffer, data, data_len);
+
+ fold = vld1q_u64((uint64_t *)buffer);
+ fold = veorq_u64(fold, temp);
+ if (unlikely(data_len < 4)) {
+ fold = vshift_bytes_left(fold, 8 - data_len);
+ goto barret_reduction;
+ }
+ fold = vshift_bytes_left(fold, 16 - data_len);
+ goto reduction_128_64;
+ }
+ /* 17 to 31 bytes */
+ fold = vld1q_u64((const uint64_t *)data);
+ fold = veorq_u64(fold, temp);
+ n = 16;
+ k = params->rk1_rk2;
+ goto partial_bytes;
+ }
+
+ /** At least 32 bytes in the buffer */
+ /** Apply CRC initial value */
+ fold = vld1q_u64((const uint64_t *)data);
+ fold = veorq_u64(fold, temp);
+
+ /** Main folding loop - the last 16 bytes is processed separately */
+ k = params->rk1_rk2;
+ for (n = 16; (n + 16) <= data_len; n += 16) {
+ temp = vld1q_u64((const uint64_t *)&data[n]);
+ fold = crcr32_folding_round(temp, k, fold);
+ }
+
+partial_bytes:
+ if (likely(n < data_len)) {
+ uint64x2_t last16, a, b, mask;
+ uint32_t rem = data_len & 15;
+
+ last16 = vld1q_u64((const uint64_t *)&data[data_len - 16]);
+ a = vshift_bytes_left(fold, 16 - rem);
+ b = vshift_bytes_right(fold, rem);
+ mask = vshift_bytes_left(vdupq_n_u64(-1), 16 - rem);
+ b = vorrq_u64(b, vandq_u64(mask, last16));
+
+ /* k = rk1 & rk2 */
+ temp = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(a), 1),
+ vgetq_lane_p64(vreinterpretq_p64_u64(k), 0)));
+ fold = vreinterpretq_u64_p128(vmull_p64(
+ vgetq_lane_p64(vreinterpretq_p64_u64(a), 0),
+ vgetq_lane_p64(vreinterpretq_p64_u64(k), 1)));
+ fold = veorq_u64(fold, temp);
+ fold = veorq_u64(fold, b);
+ }
+
+ /** Reduction 128 -> 32 Assumes: fold holds 128bit folded data */
+reduction_128_64:
+ k = params->rk5_rk6;
+ fold = crcr32_reduce_128_to_64(fold, k);
+
+barret_reduction:
+ k = params->rk7_rk8;
+ n = crcr32_reduce_64_to_32(fold, k);
+
+ return n;
+}
+
+static inline void
+rte_net_crc_neon_init(void)
+{
+ /* Initialize CRC16 data */
+ uint64_t ccitt_k1_k2[2] = {0x189aeLLU, 0x8e10LLU};
+ uint64_t ccitt_k5_k6[2] = {0x189aeLLU, 0x114aaLLU};
+ uint64_t ccitt_k7_k8[2] = {0x11c581910LLU, 0x10811LLU};
+
+ /* Initialize CRC32 data */
+ uint64_t eth_k1_k2[2] = {0xccaa009eLLU, 0x1751997d0LLU};
+ uint64_t eth_k5_k6[2] = {0xccaa009eLLU, 0x163cd6124LLU};
+ uint64_t eth_k7_k8[2] = {0x1f7011640LLU, 0x1db710641LLU};
+
+ /** Save the params in context structure */
+ crc16_ccitt_pmull.rk1_rk2 = vld1q_u64(ccitt_k1_k2);
+ crc16_ccitt_pmull.rk5_rk6 = vld1q_u64(ccitt_k5_k6);
+ crc16_ccitt_pmull.rk7_rk8 = vld1q_u64(ccitt_k7_k8);
+
+ /** Save the params in context structure */
+ crc32_eth_pmull.rk1_rk2 = vld1q_u64(eth_k1_k2);
+ crc32_eth_pmull.rk5_rk6 = vld1q_u64(eth_k5_k6);
+ crc32_eth_pmull.rk7_rk8 = vld1q_u64(eth_k7_k8);
+}
+
+static inline uint32_t
+rte_crc16_ccitt_neon_handler(const uint8_t *data,
+ uint32_t data_len)
+{
+ return (uint16_t)~crc32_eth_calc_pmull(data,
+ data_len,
+ 0xffff,
+ &crc16_ccitt_pmull);
+}
+
+static inline uint32_t
+rte_crc32_eth_neon_handler(const uint8_t *data,
+ uint32_t data_len)
+{
+ return ~crc32_eth_calc_pmull(data,
+ data_len,
+ 0xffffffffUL,
+ &crc32_eth_pmull);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NET_CRC_NEON_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/net_crc_sse.h b/src/spdk/dpdk/lib/librte_net/net_crc_sse.h
new file mode 100644
index 00000000..da815243
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/net_crc_sse.h
@@ -0,0 +1,334 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _RTE_NET_CRC_SSE_H_
+#define _RTE_NET_CRC_SSE_H_
+
+#include <rte_branch_prediction.h>
+
+#include <x86intrin.h>
+#include <cpuid.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** PCLMULQDQ CRC computation context structure */
+struct crc_pclmulqdq_ctx {
+ __m128i rk1_rk2;
+ __m128i rk5_rk6;
+ __m128i rk7_rk8;
+};
+
+struct crc_pclmulqdq_ctx crc32_eth_pclmulqdq __rte_aligned(16);
+struct crc_pclmulqdq_ctx crc16_ccitt_pclmulqdq __rte_aligned(16);
+/**
+ * @brief Performs one folding round
+ *
+ * Logically function operates as follows:
+ * DATA = READ_NEXT_16BYTES();
+ * F1 = LSB8(FOLD)
+ * F2 = MSB8(FOLD)
+ * T1 = CLMUL(F1, RK1)
+ * T2 = CLMUL(F2, RK2)
+ * FOLD = XOR(T1, T2, DATA)
+ *
+ * @param data_block
+ * 16 byte data block
+ * @param precomp
+ * Precomputed rk1 constant
+ * @param fold
+ * Current16 byte folded data
+ *
+ * @return
+ * New 16 byte folded data
+ */
+static __rte_always_inline __m128i
+crcr32_folding_round(__m128i data_block,
+ __m128i precomp,
+ __m128i fold)
+{
+ __m128i tmp0 = _mm_clmulepi64_si128(fold, precomp, 0x01);
+ __m128i tmp1 = _mm_clmulepi64_si128(fold, precomp, 0x10);
+
+ return _mm_xor_si128(tmp1, _mm_xor_si128(data_block, tmp0));
+}
+
+/**
+ * Performs reduction from 128 bits to 64 bits
+ *
+ * @param data128
+ * 128 bits data to be reduced
+ * @param precomp
+ * precomputed constants rk5, rk6
+ *
+ * @return
+ * 64 bits reduced data
+ */
+
+static __rte_always_inline __m128i
+crcr32_reduce_128_to_64(__m128i data128, __m128i precomp)
+{
+ __m128i tmp0, tmp1, tmp2;
+
+ /* 64b fold */
+ tmp0 = _mm_clmulepi64_si128(data128, precomp, 0x00);
+ tmp1 = _mm_srli_si128(data128, 8);
+ tmp0 = _mm_xor_si128(tmp0, tmp1);
+
+ /* 32b fold */
+ tmp2 = _mm_slli_si128(tmp0, 4);
+ tmp1 = _mm_clmulepi64_si128(tmp2, precomp, 0x10);
+
+ return _mm_xor_si128(tmp1, tmp0);
+}
+
+/**
+ * Performs Barret's reduction from 64 bits to 32 bits
+ *
+ * @param data64
+ * 64 bits data to be reduced
+ * @param precomp
+ * rk7 precomputed constant
+ *
+ * @return
+ * reduced 32 bits data
+ */
+
+static __rte_always_inline uint32_t
+crcr32_reduce_64_to_32(__m128i data64, __m128i precomp)
+{
+ static const uint32_t mask1[4] __rte_aligned(16) = {
+ 0xffffffff, 0xffffffff, 0x00000000, 0x00000000
+ };
+
+ static const uint32_t mask2[4] __rte_aligned(16) = {
+ 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff
+ };
+ __m128i tmp0, tmp1, tmp2;
+
+ tmp0 = _mm_and_si128(data64, _mm_load_si128((const __m128i *)mask2));
+
+ tmp1 = _mm_clmulepi64_si128(tmp0, precomp, 0x00);
+ tmp1 = _mm_xor_si128(tmp1, tmp0);
+ tmp1 = _mm_and_si128(tmp1, _mm_load_si128((const __m128i *)mask1));
+
+ tmp2 = _mm_clmulepi64_si128(tmp1, precomp, 0x10);
+ tmp2 = _mm_xor_si128(tmp2, tmp1);
+ tmp2 = _mm_xor_si128(tmp2, tmp0);
+
+ return _mm_extract_epi32(tmp2, 2);
+}
+
+static const uint8_t crc_xmm_shift_tab[48] __rte_aligned(16) = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+/**
+ * Shifts left 128 bit register by specified number of bytes
+ *
+ * @param reg
+ * 128 bit value
+ * @param num
+ * number of bytes to shift left reg by (0-16)
+ *
+ * @return
+ * reg << (num * 8)
+ */
+
+static __rte_always_inline __m128i
+xmm_shift_left(__m128i reg, const unsigned int num)
+{
+ const __m128i *p = (const __m128i *)(crc_xmm_shift_tab + 16 - num);
+
+ return _mm_shuffle_epi8(reg, _mm_loadu_si128(p));
+}
+
+static __rte_always_inline uint32_t
+crc32_eth_calc_pclmulqdq(
+ const uint8_t *data,
+ uint32_t data_len,
+ uint32_t crc,
+ const struct crc_pclmulqdq_ctx *params)
+{
+ __m128i temp, fold, k;
+ uint32_t n;
+
+ /* Get CRC init value */
+ temp = _mm_insert_epi32(_mm_setzero_si128(), crc, 0);
+
+ /**
+ * Folding all data into single 16 byte data block
+ * Assumes: fold holds first 16 bytes of data
+ */
+
+ if (unlikely(data_len < 32)) {
+ if (unlikely(data_len == 16)) {
+ /* 16 bytes */
+ fold = _mm_loadu_si128((const __m128i *)data);
+ fold = _mm_xor_si128(fold, temp);
+ goto reduction_128_64;
+ }
+
+ if (unlikely(data_len < 16)) {
+ /* 0 to 15 bytes */
+ uint8_t buffer[16] __rte_aligned(16);
+
+ memset(buffer, 0, sizeof(buffer));
+ memcpy(buffer, data, data_len);
+
+ fold = _mm_load_si128((const __m128i *)buffer);
+ fold = _mm_xor_si128(fold, temp);
+ if (unlikely(data_len < 4)) {
+ fold = xmm_shift_left(fold, 8 - data_len);
+ goto barret_reduction;
+ }
+ fold = xmm_shift_left(fold, 16 - data_len);
+ goto reduction_128_64;
+ }
+ /* 17 to 31 bytes */
+ fold = _mm_loadu_si128((const __m128i *)data);
+ fold = _mm_xor_si128(fold, temp);
+ n = 16;
+ k = params->rk1_rk2;
+ goto partial_bytes;
+ }
+
+ /** At least 32 bytes in the buffer */
+ /** Apply CRC initial value */
+ fold = _mm_loadu_si128((const __m128i *)data);
+ fold = _mm_xor_si128(fold, temp);
+
+ /** Main folding loop - the last 16 bytes is processed separately */
+ k = params->rk1_rk2;
+ for (n = 16; (n + 16) <= data_len; n += 16) {
+ temp = _mm_loadu_si128((const __m128i *)&data[n]);
+ fold = crcr32_folding_round(temp, k, fold);
+ }
+
+partial_bytes:
+ if (likely(n < data_len)) {
+
+ const uint32_t mask3[4] __rte_aligned(16) = {
+ 0x80808080, 0x80808080, 0x80808080, 0x80808080
+ };
+
+ const uint8_t shf_table[32] __rte_aligned(16) = {
+ 0x00, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+ };
+
+ __m128i last16, a, b;
+
+ last16 = _mm_loadu_si128((const __m128i *)&data[data_len - 16]);
+
+ temp = _mm_loadu_si128((const __m128i *)
+ &shf_table[data_len & 15]);
+ a = _mm_shuffle_epi8(fold, temp);
+
+ temp = _mm_xor_si128(temp,
+ _mm_load_si128((const __m128i *)mask3));
+ b = _mm_shuffle_epi8(fold, temp);
+ b = _mm_blendv_epi8(b, last16, temp);
+
+ /* k = rk1 & rk2 */
+ temp = _mm_clmulepi64_si128(a, k, 0x01);
+ fold = _mm_clmulepi64_si128(a, k, 0x10);
+
+ fold = _mm_xor_si128(fold, temp);
+ fold = _mm_xor_si128(fold, b);
+ }
+
+ /** Reduction 128 -> 32 Assumes: fold holds 128bit folded data */
+reduction_128_64:
+ k = params->rk5_rk6;
+ fold = crcr32_reduce_128_to_64(fold, k);
+
+barret_reduction:
+ k = params->rk7_rk8;
+ n = crcr32_reduce_64_to_32(fold, k);
+
+ return n;
+}
+
+
+static inline void
+rte_net_crc_sse42_init(void)
+{
+ uint64_t k1, k2, k5, k6;
+ uint64_t p = 0, q = 0;
+
+ /** Initialize CRC16 data */
+ k1 = 0x189aeLLU;
+ k2 = 0x8e10LLU;
+ k5 = 0x189aeLLU;
+ k6 = 0x114aaLLU;
+ q = 0x11c581910LLU;
+ p = 0x10811LLU;
+
+ /** Save the params in context structure */
+ crc16_ccitt_pclmulqdq.rk1_rk2 =
+ _mm_setr_epi64(_mm_cvtsi64_m64(k1), _mm_cvtsi64_m64(k2));
+ crc16_ccitt_pclmulqdq.rk5_rk6 =
+ _mm_setr_epi64(_mm_cvtsi64_m64(k5), _mm_cvtsi64_m64(k6));
+ crc16_ccitt_pclmulqdq.rk7_rk8 =
+ _mm_setr_epi64(_mm_cvtsi64_m64(q), _mm_cvtsi64_m64(p));
+
+ /** Initialize CRC32 data */
+ k1 = 0xccaa009eLLU;
+ k2 = 0x1751997d0LLU;
+ k5 = 0xccaa009eLLU;
+ k6 = 0x163cd6124LLU;
+ q = 0x1f7011640LLU;
+ p = 0x1db710641LLU;
+
+ /** Save the params in context structure */
+ crc32_eth_pclmulqdq.rk1_rk2 =
+ _mm_setr_epi64(_mm_cvtsi64_m64(k1), _mm_cvtsi64_m64(k2));
+ crc32_eth_pclmulqdq.rk5_rk6 =
+ _mm_setr_epi64(_mm_cvtsi64_m64(k5), _mm_cvtsi64_m64(k6));
+ crc32_eth_pclmulqdq.rk7_rk8 =
+ _mm_setr_epi64(_mm_cvtsi64_m64(q), _mm_cvtsi64_m64(p));
+
+ /**
+ * Reset the register as following calculation may
+ * use other data types such as float, double, etc.
+ */
+ _mm_empty();
+
+}
+
+static inline uint32_t
+rte_crc16_ccitt_sse42_handler(const uint8_t *data,
+ uint32_t data_len)
+{
+ /** return 16-bit CRC value */
+ return (uint16_t)~crc32_eth_calc_pclmulqdq(data,
+ data_len,
+ 0xffff,
+ &crc16_ccitt_pclmulqdq);
+}
+
+static inline uint32_t
+rte_crc32_eth_sse42_handler(const uint8_t *data,
+ uint32_t data_len)
+{
+ return ~crc32_eth_calc_pclmulqdq(data,
+ data_len,
+ 0xffffffffUL,
+ &crc32_eth_pclmulqdq);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_NET_CRC_SSE_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_arp.c b/src/spdk/dpdk/lib/librte_net/rte_arp.c
new file mode 100644
index 00000000..f0ed9bd6
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_arp.c
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#include <arpa/inet.h>
+
+#include <rte_arp.h>
+
+#define RARP_PKT_SIZE 64
+struct rte_mbuf * __rte_experimental
+rte_net_make_rarp_packet(struct rte_mempool *mpool,
+ const struct ether_addr *mac)
+{
+ struct ether_hdr *eth_hdr;
+ struct arp_hdr *rarp;
+ struct rte_mbuf *mbuf;
+
+ if (mpool == NULL)
+ return NULL;
+
+ mbuf = rte_pktmbuf_alloc(mpool);
+ if (mbuf == NULL)
+ return NULL;
+
+ eth_hdr = (struct ether_hdr *)rte_pktmbuf_append(mbuf, RARP_PKT_SIZE);
+ if (eth_hdr == NULL) {
+ rte_pktmbuf_free(mbuf);
+ return NULL;
+ }
+
+ /* Ethernet header. */
+ memset(eth_hdr->d_addr.addr_bytes, 0xff, ETHER_ADDR_LEN);
+ ether_addr_copy(mac, &eth_hdr->s_addr);
+ eth_hdr->ether_type = htons(ETHER_TYPE_RARP);
+
+ /* RARP header. */
+ rarp = (struct arp_hdr *)(eth_hdr + 1);
+ rarp->arp_hrd = htons(ARP_HRD_ETHER);
+ rarp->arp_pro = htons(ETHER_TYPE_IPv4);
+ rarp->arp_hln = ETHER_ADDR_LEN;
+ rarp->arp_pln = 4;
+ rarp->arp_op = htons(ARP_OP_REVREQUEST);
+
+ ether_addr_copy(mac, &rarp->arp_data.arp_sha);
+ ether_addr_copy(mac, &rarp->arp_data.arp_tha);
+ memset(&rarp->arp_data.arp_sip, 0x00, 4);
+ memset(&rarp->arp_data.arp_tip, 0x00, 4);
+
+ return mbuf;
+}
diff --git a/src/spdk/dpdk/lib/librte_net/rte_arp.h b/src/spdk/dpdk/lib/librte_net/rte_arp.h
new file mode 100644
index 00000000..139a84ca
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_arp.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2013 6WIND S.A.
+ */
+
+#ifndef _RTE_ARP_H_
+#define _RTE_ARP_H_
+
+/**
+ * @file
+ *
+ * ARP-related defines
+ */
+
+#include <stdint.h>
+#include <rte_ether.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ARP header IPv4 payload.
+ */
+struct arp_ipv4 {
+ struct ether_addr arp_sha; /**< sender hardware address */
+ uint32_t arp_sip; /**< sender IP address */
+ struct ether_addr arp_tha; /**< target hardware address */
+ uint32_t arp_tip; /**< target IP address */
+} __attribute__((__packed__));
+
+/**
+ * ARP header.
+ */
+struct arp_hdr {
+ uint16_t arp_hrd; /* format of hardware address */
+#define ARP_HRD_ETHER 1 /* ARP Ethernet address format */
+
+ uint16_t arp_pro; /* format of protocol address */
+ uint8_t arp_hln; /* length of hardware address */
+ uint8_t arp_pln; /* length of protocol address */
+ uint16_t arp_op; /* ARP opcode (command) */
+#define ARP_OP_REQUEST 1 /* request to resolve address */
+#define ARP_OP_REPLY 2 /* response to previous request */
+#define ARP_OP_REVREQUEST 3 /* request proto addr given hardware */
+#define ARP_OP_REVREPLY 4 /* response giving protocol address */
+#define ARP_OP_INVREQUEST 8 /* request to identify peer */
+#define ARP_OP_INVREPLY 9 /* response identifying peer */
+
+ struct arp_ipv4 arp_data;
+} __attribute__((__packed__));
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Make a RARP packet based on MAC addr.
+ *
+ * @param mpool
+ * Pointer to the rte_mempool
+ * @param mac
+ * Pointer to the MAC addr
+ *
+ * @return
+ * - RARP packet pointer on success, or NULL on error
+ */
+struct rte_mbuf * __rte_experimental
+rte_net_make_rarp_packet(struct rte_mempool *mpool,
+ const struct ether_addr *mac);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_ARP_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_esp.h b/src/spdk/dpdk/lib/librte_net/rte_esp.h
new file mode 100644
index 00000000..f77ec2eb
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_esp.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016 Mellanox Technologies, Ltd
+ */
+
+#ifndef _RTE_ESP_H_
+#define _RTE_ESP_H_
+
+/**
+ * @file
+ *
+ * ESP-related defines
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ESP Header
+ */
+struct esp_hdr {
+ rte_be32_t spi; /**< Security Parameters Index */
+ rte_be32_t seq; /**< packet sequence number */
+} __attribute__((__packed__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_ESP_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_ether.h b/src/spdk/dpdk/lib/librte_net/rte_ether.h
new file mode 100644
index 00000000..bee2b34f
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_ether.h
@@ -0,0 +1,418 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2014 Intel Corporation
+ */
+
+#ifndef _RTE_ETHER_H_
+#define _RTE_ETHER_H_
+
+/**
+ * @file
+ *
+ * Ethernet Helpers in RTE
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_memcpy.h>
+#include <rte_random.h>
+#include <rte_mbuf.h>
+#include <rte_byteorder.h>
+
+#define ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */
+#define ETHER_TYPE_LEN 2 /**< Length of Ethernet type field. */
+#define ETHER_CRC_LEN 4 /**< Length of Ethernet CRC. */
+#define ETHER_HDR_LEN \
+ (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) /**< Length of Ethernet header. */
+#define ETHER_MIN_LEN 64 /**< Minimum frame len, including CRC. */
+#define ETHER_MAX_LEN 1518 /**< Maximum frame len, including CRC. */
+#define ETHER_MTU \
+ (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) /**< Ethernet MTU. */
+
+#define ETHER_MAX_VLAN_FRAME_LEN \
+ (ETHER_MAX_LEN + 4) /**< Maximum VLAN frame length, including CRC. */
+
+#define ETHER_MAX_JUMBO_FRAME_LEN \
+ 0x3F00 /**< Maximum Jumbo frame length, including CRC. */
+
+#define ETHER_MAX_VLAN_ID 4095 /**< Maximum VLAN ID. */
+
+#define ETHER_MIN_MTU 68 /**< Minimum MTU for IPv4 packets, see RFC 791. */
+
+/**
+ * Ethernet address:
+ * A universally administered address is uniquely assigned to a device by its
+ * manufacturer. The first three octets (in transmission order) contain the
+ * Organizationally Unique Identifier (OUI). The following three (MAC-48 and
+ * EUI-48) octets are assigned by that organization with the only constraint
+ * of uniqueness.
+ * A locally administered address is assigned to a device by a network
+ * administrator and does not contain OUIs.
+ * See http://standards.ieee.org/regauth/groupmac/tutorial.html
+ */
+struct ether_addr {
+ uint8_t addr_bytes[ETHER_ADDR_LEN]; /**< Addr bytes in tx order */
+} __attribute__((__packed__));
+
+#define ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */
+#define ETHER_GROUP_ADDR 0x01 /**< Multicast or broadcast Eth. address. */
+
+/**
+ * Check if two Ethernet addresses are the same.
+ *
+ * @param ea1
+ * A pointer to the first ether_addr structure containing
+ * the ethernet address.
+ * @param ea2
+ * A pointer to the second ether_addr structure containing
+ * the ethernet address.
+ *
+ * @return
+ * True (1) if the given two ethernet address are the same;
+ * False (0) otherwise.
+ */
+static inline int is_same_ether_addr(const struct ether_addr *ea1,
+ const struct ether_addr *ea2)
+{
+ int i;
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ if (ea1->addr_bytes[i] != ea2->addr_bytes[i])
+ return 0;
+ return 1;
+}
+
+/**
+ * Check if an Ethernet address is filled with zeros.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is filled with zeros;
+ * false (0) otherwise.
+ */
+static inline int is_zero_ether_addr(const struct ether_addr *ea)
+{
+ int i;
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ if (ea->addr_bytes[i] != 0x00)
+ return 0;
+ return 1;
+}
+
+/**
+ * Check if an Ethernet address is a unicast address.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is a unicast address;
+ * false (0) otherwise.
+ */
+static inline int is_unicast_ether_addr(const struct ether_addr *ea)
+{
+ return (ea->addr_bytes[0] & ETHER_GROUP_ADDR) == 0;
+}
+
+/**
+ * Check if an Ethernet address is a multicast address.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is a multicast address;
+ * false (0) otherwise.
+ */
+static inline int is_multicast_ether_addr(const struct ether_addr *ea)
+{
+ return ea->addr_bytes[0] & ETHER_GROUP_ADDR;
+}
+
+/**
+ * Check if an Ethernet address is a broadcast address.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is a broadcast address;
+ * false (0) otherwise.
+ */
+static inline int is_broadcast_ether_addr(const struct ether_addr *ea)
+{
+ const unaligned_uint16_t *ea_words = (const unaligned_uint16_t *)ea;
+
+ return (ea_words[0] == 0xFFFF && ea_words[1] == 0xFFFF &&
+ ea_words[2] == 0xFFFF);
+}
+
+/**
+ * Check if an Ethernet address is a universally assigned address.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is a universally assigned address;
+ * false (0) otherwise.
+ */
+static inline int is_universal_ether_addr(const struct ether_addr *ea)
+{
+ return (ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) == 0;
+}
+
+/**
+ * Check if an Ethernet address is a locally assigned address.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is a locally assigned address;
+ * false (0) otherwise.
+ */
+static inline int is_local_admin_ether_addr(const struct ether_addr *ea)
+{
+ return (ea->addr_bytes[0] & ETHER_LOCAL_ADMIN_ADDR) != 0;
+}
+
+/**
+ * Check if an Ethernet address is a valid address. Checks that the address is a
+ * unicast address and is not filled with zeros.
+ *
+ * @param ea
+ * A pointer to a ether_addr structure containing the ethernet address
+ * to check.
+ * @return
+ * True (1) if the given ethernet address is valid;
+ * false (0) otherwise.
+ */
+static inline int is_valid_assigned_ether_addr(const struct ether_addr *ea)
+{
+ return is_unicast_ether_addr(ea) && (!is_zero_ether_addr(ea));
+}
+
+/**
+ * Generate a random Ethernet address that is locally administered
+ * and not multicast.
+ * @param addr
+ * A pointer to Ethernet address.
+ */
+static inline void eth_random_addr(uint8_t *addr)
+{
+ uint64_t rand = rte_rand();
+ uint8_t *p = (uint8_t *)&rand;
+
+ rte_memcpy(addr, p, ETHER_ADDR_LEN);
+ addr[0] &= (uint8_t)~ETHER_GROUP_ADDR; /* clear multicast bit */
+ addr[0] |= ETHER_LOCAL_ADMIN_ADDR; /* set local assignment bit */
+}
+
+/**
+ * Fast copy an Ethernet address.
+ *
+ * @param ea_from
+ * A pointer to a ether_addr structure holding the Ethernet address to copy.
+ * @param ea_to
+ * A pointer to a ether_addr structure where to copy the Ethernet address.
+ */
+static inline void ether_addr_copy(const struct ether_addr *ea_from,
+ struct ether_addr *ea_to)
+{
+#ifdef __INTEL_COMPILER
+ uint16_t *from_words = (uint16_t *)(ea_from->addr_bytes);
+ uint16_t *to_words = (uint16_t *)(ea_to->addr_bytes);
+
+ to_words[0] = from_words[0];
+ to_words[1] = from_words[1];
+ to_words[2] = from_words[2];
+#else
+ /*
+ * Use the common way, because of a strange gcc warning.
+ */
+ *ea_to = *ea_from;
+#endif
+}
+
+#define ETHER_ADDR_FMT_SIZE 18
+/**
+ * Format 48bits Ethernet address in pattern xx:xx:xx:xx:xx:xx.
+ *
+ * @param buf
+ * A pointer to buffer contains the formatted MAC address.
+ * @param size
+ * The format buffer size.
+ * @param eth_addr
+ * A pointer to a ether_addr structure.
+ */
+static inline void
+ether_format_addr(char *buf, uint16_t size,
+ const struct ether_addr *eth_addr)
+{
+ snprintf(buf, size, "%02X:%02X:%02X:%02X:%02X:%02X",
+ eth_addr->addr_bytes[0],
+ eth_addr->addr_bytes[1],
+ eth_addr->addr_bytes[2],
+ eth_addr->addr_bytes[3],
+ eth_addr->addr_bytes[4],
+ eth_addr->addr_bytes[5]);
+}
+
+/**
+ * Ethernet header: Contains the destination address, source address
+ * and frame type.
+ */
+struct ether_hdr {
+ struct ether_addr d_addr; /**< Destination address. */
+ struct ether_addr s_addr; /**< Source address. */
+ uint16_t ether_type; /**< Frame type. */
+} __attribute__((__packed__));
+
+/**
+ * Ethernet VLAN Header.
+ * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type
+ * of the encapsulated frame.
+ */
+struct vlan_hdr {
+ uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */
+ uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */
+} __attribute__((__packed__));
+
+/**
+ * VXLAN protocol header.
+ * Contains the 8-bit flag, 24-bit VXLAN Network Identifier and
+ * Reserved fields (24 bits and 8 bits)
+ */
+struct vxlan_hdr {
+ uint32_t vx_flags; /**< flag (8) + Reserved (24). */
+ uint32_t vx_vni; /**< VNI (24) + Reserved (8). */
+} __attribute__((__packed__));
+
+/* Ethernet frame types */
+#define ETHER_TYPE_IPv4 0x0800 /**< IPv4 Protocol. */
+#define ETHER_TYPE_IPv6 0x86DD /**< IPv6 Protocol. */
+#define ETHER_TYPE_ARP 0x0806 /**< Arp Protocol. */
+#define ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */
+#define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */
+#define ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */
+#define ETHER_TYPE_ETAG 0x893F /**< IEEE 802.1BR E-Tag. */
+#define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time Protocol. */
+#define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */
+#define ETHER_TYPE_TEB 0x6558 /**< Transparent Ethernet Bridging. */
+#define ETHER_TYPE_LLDP 0x88CC /**< LLDP Protocol. */
+
+#define ETHER_VXLAN_HLEN (sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr))
+/**< VXLAN tunnel header length. */
+
+/**
+ * VXLAN-GPE protocol header (draft-ietf-nvo3-vxlan-gpe-05).
+ * Contains the 8-bit flag, 8-bit next-protocol, 24-bit VXLAN Network
+ * Identifier and Reserved fields (16 bits and 8 bits).
+ */
+struct vxlan_gpe_hdr {
+ uint8_t vx_flags; /**< flag (8). */
+ uint8_t reserved[2]; /**< Reserved (16). */
+ uint8_t proto; /**< next-protocol (8). */
+ uint32_t vx_vni; /**< VNI (24) + Reserved (8). */
+} __attribute__((__packed__));
+
+/* VXLAN-GPE next protocol types */
+#define VXLAN_GPE_TYPE_IPV4 1 /**< IPv4 Protocol. */
+#define VXLAN_GPE_TYPE_IPV6 2 /**< IPv6 Protocol. */
+#define VXLAN_GPE_TYPE_ETH 3 /**< Ethernet Protocol. */
+#define VXLAN_GPE_TYPE_NSH 4 /**< NSH Protocol. */
+#define VXLAN_GPE_TYPE_MPLS 5 /**< MPLS Protocol. */
+#define VXLAN_GPE_TYPE_GBP 6 /**< GBP Protocol. */
+#define VXLAN_GPE_TYPE_VBNG 7 /**< vBNG Protocol. */
+
+#define ETHER_VXLAN_GPE_HLEN (sizeof(struct udp_hdr) + \
+ sizeof(struct vxlan_gpe_hdr))
+/**< VXLAN-GPE tunnel header length. */
+
+/**
+ * Extract VLAN tag information into mbuf
+ *
+ * Software version of VLAN stripping
+ *
+ * @param m
+ * The packet mbuf.
+ * @return
+ * - 0: Success
+ * - 1: not a vlan packet
+ */
+static inline int rte_vlan_strip(struct rte_mbuf *m)
+{
+ struct ether_hdr *eh
+ = rte_pktmbuf_mtod(m, struct ether_hdr *);
+ struct vlan_hdr *vh;
+
+ if (eh->ether_type != rte_cpu_to_be_16(ETHER_TYPE_VLAN))
+ return -1;
+
+ vh = (struct vlan_hdr *)(eh + 1);
+ m->ol_flags |= PKT_RX_VLAN | PKT_RX_VLAN_STRIPPED;
+ m->vlan_tci = rte_be_to_cpu_16(vh->vlan_tci);
+
+ /* Copy ether header over rather than moving whole packet */
+ memmove(rte_pktmbuf_adj(m, sizeof(struct vlan_hdr)),
+ eh, 2 * ETHER_ADDR_LEN);
+
+ return 0;
+}
+
+/**
+ * Insert VLAN tag into mbuf.
+ *
+ * Software version of VLAN unstripping
+ *
+ * @param m
+ * The packet mbuf.
+ * @return
+ * - 0: On success
+ * -EPERM: mbuf is is shared overwriting would be unsafe
+ * -ENOSPC: not enough headroom in mbuf
+ */
+static inline int rte_vlan_insert(struct rte_mbuf **m)
+{
+ struct ether_hdr *oh, *nh;
+ struct vlan_hdr *vh;
+
+ /* Can't insert header if mbuf is shared */
+ if (rte_mbuf_refcnt_read(*m) > 1) {
+ struct rte_mbuf *copy;
+
+ copy = rte_pktmbuf_clone(*m, (*m)->pool);
+ if (unlikely(copy == NULL))
+ return -ENOMEM;
+ rte_pktmbuf_free(*m);
+ *m = copy;
+ }
+
+ oh = rte_pktmbuf_mtod(*m, struct ether_hdr *);
+ nh = (struct ether_hdr *)
+ rte_pktmbuf_prepend(*m, sizeof(struct vlan_hdr));
+ if (nh == NULL)
+ return -ENOSPC;
+
+ memmove(nh, oh, 2 * ETHER_ADDR_LEN);
+ nh->ether_type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
+
+ vh = (struct vlan_hdr *) (nh + 1);
+ vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci);
+
+ (*m)->ol_flags &= ~PKT_RX_VLAN_STRIPPED;
+
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_ETHER_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_gre.h b/src/spdk/dpdk/lib/librte_net/rte_gre.h
new file mode 100644
index 00000000..69499bb8
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_gre.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016 6WIND S.A.
+ */
+
+#ifndef _RTE_GRE_H_
+#define _RTE_GRE_H_
+
+#include <stdint.h>
+#include <rte_byteorder.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * GRE Header
+ */
+struct gre_hdr {
+#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
+ uint16_t res2:4; /**< Reserved */
+ uint16_t s:1; /**< Sequence Number Present bit */
+ uint16_t k:1; /**< Key Present bit */
+ uint16_t res1:1; /**< Reserved */
+ uint16_t c:1; /**< Checksum Present bit */
+ uint16_t ver:3; /**< Version Number */
+ uint16_t res3:5; /**< Reserved */
+#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+ uint16_t c:1; /**< Checksum Present bit */
+ uint16_t res1:1; /**< Reserved */
+ uint16_t k:1; /**< Key Present bit */
+ uint16_t s:1; /**< Sequence Number Present bit */
+ uint16_t res2:4; /**< Reserved */
+ uint16_t res3:5; /**< Reserved */
+ uint16_t ver:3; /**< Version Number */
+#endif
+ uint16_t proto; /**< Protocol Type */
+} __attribute__((__packed__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_GRE_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_icmp.h b/src/spdk/dpdk/lib/librte_net/rte_icmp.h
new file mode 100644
index 00000000..053b5f6a
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_icmp.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California.
+ * Copyright(c) 2013 6WIND S.A.
+ * All rights reserved.
+ */
+
+#ifndef _RTE_ICMP_H_
+#define _RTE_ICMP_H_
+
+/**
+ * @file
+ *
+ * ICMP-related defines
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * ICMP Header
+ */
+struct icmp_hdr {
+ uint8_t icmp_type; /* ICMP packet type. */
+ uint8_t icmp_code; /* ICMP packet code. */
+ uint16_t icmp_cksum; /* ICMP packet checksum. */
+ uint16_t icmp_ident; /* ICMP packet identifier. */
+ uint16_t icmp_seq_nb; /* ICMP packet sequence number. */
+} __attribute__((__packed__));
+
+/* ICMP packet types */
+#define IP_ICMP_ECHO_REPLY 0
+#define IP_ICMP_ECHO_REQUEST 8
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_ICMP_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_ip.h b/src/spdk/dpdk/lib/librte_net/rte_ip.h
new file mode 100644
index 00000000..f2a8904a
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_ip.h
@@ -0,0 +1,428 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California.
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * Copyright(c) 2014 6WIND S.A.
+ * All rights reserved.
+ */
+
+#ifndef _RTE_IP_H_
+#define _RTE_IP_H_
+
+/**
+ * @file
+ *
+ * IP-related defines
+ */
+
+#include <stdint.h>
+#include <netinet/in.h>
+
+#include <rte_byteorder.h>
+#include <rte_mbuf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * IPv4 Header
+ */
+struct ipv4_hdr {
+ uint8_t version_ihl; /**< version and header length */
+ uint8_t type_of_service; /**< type of service */
+ uint16_t total_length; /**< length of packet */
+ uint16_t packet_id; /**< packet ID */
+ uint16_t fragment_offset; /**< fragmentation offset */
+ uint8_t time_to_live; /**< time to live */
+ uint8_t next_proto_id; /**< protocol ID */
+ uint16_t hdr_checksum; /**< header checksum */
+ uint32_t src_addr; /**< source address */
+ uint32_t dst_addr; /**< destination address */
+} __attribute__((__packed__));
+
+/** Create IPv4 address */
+#define IPv4(a,b,c,d) ((uint32_t)(((a) & 0xff) << 24) | \
+ (((b) & 0xff) << 16) | \
+ (((c) & 0xff) << 8) | \
+ ((d) & 0xff))
+
+/** Maximal IPv4 packet length (including a header) */
+#define IPV4_MAX_PKT_LEN 65535
+
+/** Internet header length mask for version_ihl field */
+#define IPV4_HDR_IHL_MASK (0x0f)
+/**
+ * Internet header length field multiplier (IHL field specifies overall header
+ * length in number of 4-byte words)
+ */
+#define IPV4_IHL_MULTIPLIER (4)
+
+/* Fragment Offset * Flags. */
+#define IPV4_HDR_DF_SHIFT 14
+#define IPV4_HDR_MF_SHIFT 13
+#define IPV4_HDR_FO_SHIFT 3
+
+#define IPV4_HDR_DF_FLAG (1 << IPV4_HDR_DF_SHIFT)
+#define IPV4_HDR_MF_FLAG (1 << IPV4_HDR_MF_SHIFT)
+
+#define IPV4_HDR_OFFSET_MASK ((1 << IPV4_HDR_MF_SHIFT) - 1)
+
+#define IPV4_HDR_OFFSET_UNITS 8
+
+/*
+ * IPv4 address types
+ */
+#define IPV4_ANY ((uint32_t)0x00000000) /**< 0.0.0.0 */
+#define IPV4_LOOPBACK ((uint32_t)0x7f000001) /**< 127.0.0.1 */
+#define IPV4_BROADCAST ((uint32_t)0xe0000000) /**< 224.0.0.0 */
+#define IPV4_ALLHOSTS_GROUP ((uint32_t)0xe0000001) /**< 224.0.0.1 */
+#define IPV4_ALLRTRS_GROUP ((uint32_t)0xe0000002) /**< 224.0.0.2 */
+#define IPV4_MAX_LOCAL_GROUP ((uint32_t)0xe00000ff) /**< 224.0.0.255 */
+
+/*
+ * IPv4 Multicast-related macros
+ */
+#define IPV4_MIN_MCAST IPv4(224, 0, 0, 0) /**< Minimal IPv4-multicast address */
+#define IPV4_MAX_MCAST IPv4(239, 255, 255, 255) /**< Maximum IPv4 multicast address */
+
+#define IS_IPV4_MCAST(x) \
+ ((x) >= IPV4_MIN_MCAST && (x) <= IPV4_MAX_MCAST) /**< check if IPv4 address is multicast */
+
+/**
+ * @internal Calculate a sum of all words in the buffer.
+ * Helper routine for the rte_raw_cksum().
+ *
+ * @param buf
+ * Pointer to the buffer.
+ * @param len
+ * Length of the buffer.
+ * @param sum
+ * Initial value of the sum.
+ * @return
+ * sum += Sum of all words in the buffer.
+ */
+static inline uint32_t
+__rte_raw_cksum(const void *buf, size_t len, uint32_t sum)
+{
+ /* workaround gcc strict-aliasing warning */
+ uintptr_t ptr = (uintptr_t)buf;
+ typedef uint16_t __attribute__((__may_alias__)) u16_p;
+ const u16_p *u16_buf = (const u16_p *)ptr;
+
+ while (len >= (sizeof(*u16_buf) * 4)) {
+ sum += u16_buf[0];
+ sum += u16_buf[1];
+ sum += u16_buf[2];
+ sum += u16_buf[3];
+ len -= sizeof(*u16_buf) * 4;
+ u16_buf += 4;
+ }
+ while (len >= sizeof(*u16_buf)) {
+ sum += *u16_buf;
+ len -= sizeof(*u16_buf);
+ u16_buf += 1;
+ }
+
+ /* if length is in odd bytes */
+ if (len == 1)
+ sum += *((const uint8_t *)u16_buf);
+
+ return sum;
+}
+
+/**
+ * @internal Reduce a sum to the non-complemented checksum.
+ * Helper routine for the rte_raw_cksum().
+ *
+ * @param sum
+ * Value of the sum.
+ * @return
+ * The non-complemented checksum.
+ */
+static inline uint16_t
+__rte_raw_cksum_reduce(uint32_t sum)
+{
+ sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
+ sum = ((sum & 0xffff0000) >> 16) + (sum & 0xffff);
+ return (uint16_t)sum;
+}
+
+/**
+ * Process the non-complemented checksum of a buffer.
+ *
+ * @param buf
+ * Pointer to the buffer.
+ * @param len
+ * Length of the buffer.
+ * @return
+ * The non-complemented checksum.
+ */
+static inline uint16_t
+rte_raw_cksum(const void *buf, size_t len)
+{
+ uint32_t sum;
+
+ sum = __rte_raw_cksum(buf, len, 0);
+ return __rte_raw_cksum_reduce(sum);
+}
+
+/**
+ * Compute the raw (non complemented) checksum of a packet.
+ *
+ * @param m
+ * The pointer to the mbuf.
+ * @param off
+ * The offset in bytes to start the checksum.
+ * @param len
+ * The length in bytes of the data to checksum.
+ * @param cksum
+ * A pointer to the checksum, filled on success.
+ * @return
+ * 0 on success, -1 on error (bad length or offset).
+ */
+static inline int
+rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
+ uint16_t *cksum)
+{
+ const struct rte_mbuf *seg;
+ const char *buf;
+ uint32_t sum, tmp;
+ uint32_t seglen, done;
+
+ /* easy case: all data in the first segment */
+ if (off + len <= rte_pktmbuf_data_len(m)) {
+ *cksum = rte_raw_cksum(rte_pktmbuf_mtod_offset(m,
+ const char *, off), len);
+ return 0;
+ }
+
+ if (unlikely(off + len > rte_pktmbuf_pkt_len(m)))
+ return -1; /* invalid params, return a dummy value */
+
+ /* else browse the segment to find offset */
+ seglen = 0;
+ for (seg = m; seg != NULL; seg = seg->next) {
+ seglen = rte_pktmbuf_data_len(seg);
+ if (off < seglen)
+ break;
+ off -= seglen;
+ }
+ seglen -= off;
+ buf = rte_pktmbuf_mtod_offset(seg, const char *, off);
+ if (seglen >= len) {
+ /* all in one segment */
+ *cksum = rte_raw_cksum(buf, len);
+ return 0;
+ }
+
+ /* hard case: process checksum of several segments */
+ sum = 0;
+ done = 0;
+ for (;;) {
+ tmp = __rte_raw_cksum(buf, seglen, 0);
+ if (done & 1)
+ tmp = rte_bswap16((uint16_t)tmp);
+ sum += tmp;
+ done += seglen;
+ if (done == len)
+ break;
+ seg = seg->next;
+ buf = rte_pktmbuf_mtod(seg, const char *);
+ seglen = rte_pktmbuf_data_len(seg);
+ if (seglen > len - done)
+ seglen = len - done;
+ }
+
+ *cksum = __rte_raw_cksum_reduce(sum);
+ return 0;
+}
+
+/**
+ * Process the IPv4 checksum of an IPv4 header.
+ *
+ * The checksum field must be set to 0 by the caller.
+ *
+ * @param ipv4_hdr
+ * The pointer to the contiguous IPv4 header.
+ * @return
+ * The complemented checksum to set in the IP packet.
+ */
+static inline uint16_t
+rte_ipv4_cksum(const struct ipv4_hdr *ipv4_hdr)
+{
+ uint16_t cksum;
+ cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct ipv4_hdr));
+ return (cksum == 0xffff) ? cksum : (uint16_t)~cksum;
+}
+
+/**
+ * Process the pseudo-header checksum of an IPv4 header.
+ *
+ * The checksum field must be set to 0 by the caller.
+ *
+ * Depending on the ol_flags, the pseudo-header checksum expected by the
+ * drivers is not the same. For instance, when TSO is enabled, the IP
+ * payload length must not be included in the packet.
+ *
+ * When ol_flags is 0, it computes the standard pseudo-header checksum.
+ *
+ * @param ipv4_hdr
+ * The pointer to the contiguous IPv4 header.
+ * @param ol_flags
+ * The ol_flags of the associated mbuf.
+ * @return
+ * The non-complemented checksum to set in the L4 header.
+ */
+static inline uint16_t
+rte_ipv4_phdr_cksum(const struct ipv4_hdr *ipv4_hdr, uint64_t ol_flags)
+{
+ struct ipv4_psd_header {
+ uint32_t src_addr; /* IP address of source host. */
+ uint32_t dst_addr; /* IP address of destination host. */
+ uint8_t zero; /* zero. */
+ uint8_t proto; /* L4 protocol type. */
+ uint16_t len; /* L4 length. */
+ } psd_hdr;
+
+ psd_hdr.src_addr = ipv4_hdr->src_addr;
+ psd_hdr.dst_addr = ipv4_hdr->dst_addr;
+ psd_hdr.zero = 0;
+ psd_hdr.proto = ipv4_hdr->next_proto_id;
+ if (ol_flags & PKT_TX_TCP_SEG) {
+ psd_hdr.len = 0;
+ } else {
+ psd_hdr.len = rte_cpu_to_be_16(
+ (uint16_t)(rte_be_to_cpu_16(ipv4_hdr->total_length)
+ - sizeof(struct ipv4_hdr)));
+ }
+ return rte_raw_cksum(&psd_hdr, sizeof(psd_hdr));
+}
+
+/**
+ * Process the IPv4 UDP or TCP checksum.
+ *
+ * The IPv4 header should not contains options. The IP and layer 4
+ * checksum must be set to 0 in the packet by the caller.
+ *
+ * @param ipv4_hdr
+ * The pointer to the contiguous IPv4 header.
+ * @param l4_hdr
+ * The pointer to the beginning of the L4 header.
+ * @return
+ * The complemented checksum to set in the IP packet.
+ */
+static inline uint16_t
+rte_ipv4_udptcp_cksum(const struct ipv4_hdr *ipv4_hdr, const void *l4_hdr)
+{
+ uint32_t cksum;
+ uint32_t l4_len;
+
+ l4_len = (uint32_t)(rte_be_to_cpu_16(ipv4_hdr->total_length) -
+ sizeof(struct ipv4_hdr));
+
+ cksum = rte_raw_cksum(l4_hdr, l4_len);
+ cksum += rte_ipv4_phdr_cksum(ipv4_hdr, 0);
+
+ cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
+ cksum = (~cksum) & 0xffff;
+ if (cksum == 0)
+ cksum = 0xffff;
+
+ return (uint16_t)cksum;
+}
+
+/**
+ * IPv6 Header
+ */
+struct ipv6_hdr {
+ uint32_t vtc_flow; /**< IP version, traffic class & flow label. */
+ uint16_t payload_len; /**< IP packet length - includes sizeof(ip_header). */
+ uint8_t proto; /**< Protocol, next header. */
+ uint8_t hop_limits; /**< Hop limits. */
+ uint8_t src_addr[16]; /**< IP address of source host. */
+ uint8_t dst_addr[16]; /**< IP address of destination host(s). */
+} __attribute__((__packed__));
+
+/* IPv6 vtc_flow: IPv / TC / flow_label */
+#define IPV6_HDR_FL_SHIFT 0
+#define IPV6_HDR_TC_SHIFT 20
+#define IPV6_HDR_FL_MASK ((1u << IPV6_HDR_TC_SHIFT) - 1)
+#define IPV6_HDR_TC_MASK (0xf << IPV6_HDR_TC_SHIFT)
+
+/**
+ * Process the pseudo-header checksum of an IPv6 header.
+ *
+ * Depending on the ol_flags, the pseudo-header checksum expected by the
+ * drivers is not the same. For instance, when TSO is enabled, the IPv6
+ * payload length must not be included in the packet.
+ *
+ * When ol_flags is 0, it computes the standard pseudo-header checksum.
+ *
+ * @param ipv6_hdr
+ * The pointer to the contiguous IPv6 header.
+ * @param ol_flags
+ * The ol_flags of the associated mbuf.
+ * @return
+ * The non-complemented checksum to set in the L4 header.
+ */
+static inline uint16_t
+rte_ipv6_phdr_cksum(const struct ipv6_hdr *ipv6_hdr, uint64_t ol_flags)
+{
+ uint32_t sum;
+ struct {
+ uint32_t len; /* L4 length. */
+ uint32_t proto; /* L4 protocol - top 3 bytes must be zero */
+ } psd_hdr;
+
+ psd_hdr.proto = (uint32_t)(ipv6_hdr->proto << 24);
+ if (ol_flags & PKT_TX_TCP_SEG) {
+ psd_hdr.len = 0;
+ } else {
+ psd_hdr.len = ipv6_hdr->payload_len;
+ }
+
+ sum = __rte_raw_cksum(ipv6_hdr->src_addr,
+ sizeof(ipv6_hdr->src_addr) + sizeof(ipv6_hdr->dst_addr),
+ 0);
+ sum = __rte_raw_cksum(&psd_hdr, sizeof(psd_hdr), sum);
+ return __rte_raw_cksum_reduce(sum);
+}
+
+/**
+ * Process the IPv6 UDP or TCP checksum.
+ *
+ * The IPv4 header should not contains options. The layer 4 checksum
+ * must be set to 0 in the packet by the caller.
+ *
+ * @param ipv6_hdr
+ * The pointer to the contiguous IPv6 header.
+ * @param l4_hdr
+ * The pointer to the beginning of the L4 header.
+ * @return
+ * The complemented checksum to set in the IP packet.
+ */
+static inline uint16_t
+rte_ipv6_udptcp_cksum(const struct ipv6_hdr *ipv6_hdr, const void *l4_hdr)
+{
+ uint32_t cksum;
+ uint32_t l4_len;
+
+ l4_len = rte_be_to_cpu_16(ipv6_hdr->payload_len);
+
+ cksum = rte_raw_cksum(l4_hdr, l4_len);
+ cksum += rte_ipv6_phdr_cksum(ipv6_hdr, 0);
+
+ cksum = ((cksum & 0xffff0000) >> 16) + (cksum & 0xffff);
+ cksum = (~cksum) & 0xffff;
+ if (cksum == 0)
+ cksum = 0xffff;
+
+ return (uint16_t)cksum;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_IP_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_net.c b/src/spdk/dpdk/lib/librte_net/rte_net.c
new file mode 100644
index 00000000..9eb7c743
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_net.c
@@ -0,0 +1,496 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016 6WIND S.A.
+ */
+
+#include <stdint.h>
+
+#include <rte_mbuf.h>
+#include <rte_mbuf_ptype.h>
+#include <rte_byteorder.h>
+#include <rte_ether.h>
+#include <rte_ip.h>
+#include <rte_tcp.h>
+#include <rte_udp.h>
+#include <rte_sctp.h>
+#include <rte_gre.h>
+#include <rte_net.h>
+
+/* get l3 packet type from ip6 next protocol */
+static uint32_t
+ptype_l3_ip6(uint8_t ip6_proto)
+{
+ static const uint32_t ip6_ext_proto_map[256] = {
+ [IPPROTO_HOPOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
+ [IPPROTO_ROUTING] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
+ [IPPROTO_FRAGMENT] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
+ [IPPROTO_ESP] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
+ [IPPROTO_AH] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
+ [IPPROTO_DSTOPTS] = RTE_PTYPE_L3_IPV6_EXT - RTE_PTYPE_L3_IPV6,
+ };
+
+ return RTE_PTYPE_L3_IPV6 + ip6_ext_proto_map[ip6_proto];
+}
+
+/* get l3 packet type from ip version and header length */
+static uint32_t
+ptype_l3_ip(uint8_t ipv_ihl)
+{
+ static const uint32_t ptype_l3_ip_proto_map[256] = {
+ [0x45] = RTE_PTYPE_L3_IPV4,
+ [0x46] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x47] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x48] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x49] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x4A] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x4B] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x4C] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x4D] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x4E] = RTE_PTYPE_L3_IPV4_EXT,
+ [0x4F] = RTE_PTYPE_L3_IPV4_EXT,
+ };
+
+ return ptype_l3_ip_proto_map[ipv_ihl];
+}
+
+/* get l4 packet type from proto */
+static uint32_t
+ptype_l4(uint8_t proto)
+{
+ static const uint32_t ptype_l4_proto[256] = {
+ [IPPROTO_UDP] = RTE_PTYPE_L4_UDP,
+ [IPPROTO_TCP] = RTE_PTYPE_L4_TCP,
+ [IPPROTO_SCTP] = RTE_PTYPE_L4_SCTP,
+ };
+
+ return ptype_l4_proto[proto];
+}
+
+/* get inner l3 packet type from ip6 next protocol */
+static uint32_t
+ptype_inner_l3_ip6(uint8_t ip6_proto)
+{
+ static const uint32_t ptype_inner_ip6_ext_proto_map[256] = {
+ [IPPROTO_HOPOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_ROUTING] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_FRAGMENT] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_ESP] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_AH] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ [IPPROTO_DSTOPTS] = RTE_PTYPE_INNER_L3_IPV6_EXT -
+ RTE_PTYPE_INNER_L3_IPV6,
+ };
+
+ return RTE_PTYPE_INNER_L3_IPV6 +
+ ptype_inner_ip6_ext_proto_map[ip6_proto];
+}
+
+/* get inner l3 packet type from ip version and header length */
+static uint32_t
+ptype_inner_l3_ip(uint8_t ipv_ihl)
+{
+ static const uint32_t ptype_inner_l3_ip_proto_map[256] = {
+ [0x45] = RTE_PTYPE_INNER_L3_IPV4,
+ [0x46] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x47] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x48] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x49] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4A] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4B] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4C] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4D] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4E] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ [0x4F] = RTE_PTYPE_INNER_L3_IPV4_EXT,
+ };
+
+ return ptype_inner_l3_ip_proto_map[ipv_ihl];
+}
+
+/* get inner l4 packet type from proto */
+static uint32_t
+ptype_inner_l4(uint8_t proto)
+{
+ static const uint32_t ptype_inner_l4_proto[256] = {
+ [IPPROTO_UDP] = RTE_PTYPE_INNER_L4_UDP,
+ [IPPROTO_TCP] = RTE_PTYPE_INNER_L4_TCP,
+ [IPPROTO_SCTP] = RTE_PTYPE_INNER_L4_SCTP,
+ };
+
+ return ptype_inner_l4_proto[proto];
+}
+
+/* get the tunnel packet type if any, update proto and off. */
+static uint32_t
+ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m,
+ uint32_t *off)
+{
+ switch (*proto) {
+ case IPPROTO_GRE: {
+ static const uint8_t opt_len[16] = {
+ [0x0] = 4,
+ [0x1] = 8,
+ [0x2] = 8,
+ [0x8] = 8,
+ [0x3] = 12,
+ [0x9] = 12,
+ [0xa] = 12,
+ [0xb] = 16,
+ };
+ const struct gre_hdr *gh;
+ struct gre_hdr gh_copy;
+ uint16_t flags;
+
+ gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy);
+ if (unlikely(gh == NULL))
+ return 0;
+
+ flags = rte_be_to_cpu_16(*(const uint16_t *)gh);
+ flags >>= 12;
+ if (opt_len[flags] == 0)
+ return 0;
+
+ *off += opt_len[flags];
+ *proto = gh->proto;
+ if (*proto == rte_cpu_to_be_16(ETHER_TYPE_TEB))
+ return RTE_PTYPE_TUNNEL_NVGRE;
+ else
+ return RTE_PTYPE_TUNNEL_GRE;
+ }
+ case IPPROTO_IPIP:
+ *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ return RTE_PTYPE_TUNNEL_IP;
+ case IPPROTO_IPV6:
+ *proto = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ return RTE_PTYPE_TUNNEL_IP; /* IP is also valid for IPv6 */
+ default:
+ return 0;
+ }
+}
+
+/* get the ipv4 header length */
+static uint8_t
+ip4_hlen(const struct ipv4_hdr *hdr)
+{
+ return (hdr->version_ihl & 0xf) * 4;
+}
+
+/* parse ipv6 extended headers, update offset and return next proto */
+int __rte_experimental
+rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
+ int *frag)
+{
+ struct ext_hdr {
+ uint8_t next_hdr;
+ uint8_t len;
+ };
+ const struct ext_hdr *xh;
+ struct ext_hdr xh_copy;
+ unsigned int i;
+
+ *frag = 0;
+
+#define MAX_EXT_HDRS 5
+ for (i = 0; i < MAX_EXT_HDRS; i++) {
+ switch (proto) {
+ case IPPROTO_HOPOPTS:
+ case IPPROTO_ROUTING:
+ case IPPROTO_DSTOPTS:
+ xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
+ &xh_copy);
+ if (xh == NULL)
+ return -1;
+ *off += (xh->len + 1) * 8;
+ proto = xh->next_hdr;
+ break;
+ case IPPROTO_FRAGMENT:
+ xh = rte_pktmbuf_read(m, *off, sizeof(*xh),
+ &xh_copy);
+ if (xh == NULL)
+ return -1;
+ *off += 8;
+ proto = xh->next_hdr;
+ *frag = 1;
+ return proto; /* this is always the last ext hdr */
+ case IPPROTO_NONE:
+ return 0;
+ default:
+ return proto;
+ }
+ }
+ return -1;
+}
+
+/* parse mbuf data to get packet type */
+uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
+ struct rte_net_hdr_lens *hdr_lens, uint32_t layers)
+{
+ struct rte_net_hdr_lens local_hdr_lens;
+ const struct ether_hdr *eh;
+ struct ether_hdr eh_copy;
+ uint32_t pkt_type = RTE_PTYPE_L2_ETHER;
+ uint32_t off = 0;
+ uint16_t proto;
+ int ret;
+
+ if (hdr_lens == NULL)
+ hdr_lens = &local_hdr_lens;
+
+ eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
+ if (unlikely(eh == NULL))
+ return 0;
+ proto = eh->ether_type;
+ off = sizeof(*eh);
+ hdr_lens->l2_len = off;
+
+ if ((layers & RTE_PTYPE_L2_MASK) == 0)
+ return 0;
+
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4))
+ goto l3; /* fast path if packet is IPv4 */
+
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) {
+ const struct vlan_hdr *vh;
+ struct vlan_hdr vh_copy;
+
+ pkt_type = RTE_PTYPE_L2_ETHER_VLAN;
+ vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
+ if (unlikely(vh == NULL))
+ return pkt_type;
+ off += sizeof(*vh);
+ hdr_lens->l2_len += sizeof(*vh);
+ proto = vh->eth_proto;
+ } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) {
+ const struct vlan_hdr *vh;
+ struct vlan_hdr vh_copy;
+
+ pkt_type = RTE_PTYPE_L2_ETHER_QINQ;
+ vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
+ &vh_copy);
+ if (unlikely(vh == NULL))
+ return pkt_type;
+ off += 2 * sizeof(*vh);
+ hdr_lens->l2_len += 2 * sizeof(*vh);
+ proto = vh->eth_proto;
+ }
+
+ l3:
+ if ((layers & RTE_PTYPE_L3_MASK) == 0)
+ return pkt_type;
+
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
+ const struct ipv4_hdr *ip4h;
+ struct ipv4_hdr ip4h_copy;
+
+ ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
+ if (unlikely(ip4h == NULL))
+ return pkt_type;
+
+ pkt_type |= ptype_l3_ip(ip4h->version_ihl);
+ hdr_lens->l3_len = ip4_hlen(ip4h);
+ off += hdr_lens->l3_len;
+
+ if ((layers & RTE_PTYPE_L4_MASK) == 0)
+ return pkt_type;
+
+ if (ip4h->fragment_offset & rte_cpu_to_be_16(
+ IPV4_HDR_OFFSET_MASK | IPV4_HDR_MF_FLAG)) {
+ pkt_type |= RTE_PTYPE_L4_FRAG;
+ hdr_lens->l4_len = 0;
+ return pkt_type;
+ }
+ proto = ip4h->next_proto_id;
+ pkt_type |= ptype_l4(proto);
+ } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) {
+ const struct ipv6_hdr *ip6h;
+ struct ipv6_hdr ip6h_copy;
+ int frag = 0;
+
+ ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
+ if (unlikely(ip6h == NULL))
+ return pkt_type;
+
+ proto = ip6h->proto;
+ hdr_lens->l3_len = sizeof(*ip6h);
+ off += hdr_lens->l3_len;
+ pkt_type |= ptype_l3_ip6(proto);
+ if ((pkt_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV6_EXT) {
+ ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
+ if (ret < 0)
+ return pkt_type;
+ proto = ret;
+ hdr_lens->l3_len = off - hdr_lens->l2_len;
+ }
+ if (proto == 0)
+ return pkt_type;
+
+ if ((layers & RTE_PTYPE_L4_MASK) == 0)
+ return pkt_type;
+
+ if (frag) {
+ pkt_type |= RTE_PTYPE_L4_FRAG;
+ hdr_lens->l4_len = 0;
+ return pkt_type;
+ }
+ pkt_type |= ptype_l4(proto);
+ }
+
+ if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) {
+ hdr_lens->l4_len = sizeof(struct udp_hdr);
+ return pkt_type;
+ } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) {
+ const struct tcp_hdr *th;
+ struct tcp_hdr th_copy;
+
+ th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
+ if (unlikely(th == NULL))
+ return pkt_type & (RTE_PTYPE_L2_MASK |
+ RTE_PTYPE_L3_MASK);
+ hdr_lens->l4_len = (th->data_off & 0xf0) >> 2;
+ return pkt_type;
+ } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_SCTP) {
+ hdr_lens->l4_len = sizeof(struct sctp_hdr);
+ return pkt_type;
+ } else {
+ uint32_t prev_off = off;
+
+ hdr_lens->l4_len = 0;
+
+ if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0)
+ return pkt_type;
+
+ pkt_type |= ptype_tunnel(&proto, m, &off);
+ hdr_lens->tunnel_len = off - prev_off;
+ }
+
+ /* same job for inner header: we need to duplicate the code
+ * because the packet types do not have the same value.
+ */
+ if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0)
+ return pkt_type;
+
+ hdr_lens->inner_l2_len = 0;
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_TEB)) {
+ eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy);
+ if (unlikely(eh == NULL))
+ return pkt_type;
+ pkt_type |= RTE_PTYPE_INNER_L2_ETHER;
+ proto = eh->ether_type;
+ off += sizeof(*eh);
+ hdr_lens->inner_l2_len = sizeof(*eh);
+ }
+
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_VLAN)) {
+ const struct vlan_hdr *vh;
+ struct vlan_hdr vh_copy;
+
+ pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
+ pkt_type |= RTE_PTYPE_INNER_L2_ETHER_VLAN;
+ vh = rte_pktmbuf_read(m, off, sizeof(*vh), &vh_copy);
+ if (unlikely(vh == NULL))
+ return pkt_type;
+ off += sizeof(*vh);
+ hdr_lens->inner_l2_len += sizeof(*vh);
+ proto = vh->eth_proto;
+ } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_QINQ)) {
+ const struct vlan_hdr *vh;
+ struct vlan_hdr vh_copy;
+
+ pkt_type &= ~RTE_PTYPE_INNER_L2_MASK;
+ pkt_type |= RTE_PTYPE_INNER_L2_ETHER_QINQ;
+ vh = rte_pktmbuf_read(m, off + sizeof(*vh), sizeof(*vh),
+ &vh_copy);
+ if (unlikely(vh == NULL))
+ return pkt_type;
+ off += 2 * sizeof(*vh);
+ hdr_lens->inner_l2_len += 2 * sizeof(*vh);
+ proto = vh->eth_proto;
+ }
+
+ if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0)
+ return pkt_type;
+
+ if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv4)) {
+ const struct ipv4_hdr *ip4h;
+ struct ipv4_hdr ip4h_copy;
+
+ ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy);
+ if (unlikely(ip4h == NULL))
+ return pkt_type;
+
+ pkt_type |= ptype_inner_l3_ip(ip4h->version_ihl);
+ hdr_lens->inner_l3_len = ip4_hlen(ip4h);
+ off += hdr_lens->inner_l3_len;
+
+ if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
+ return pkt_type;
+ if (ip4h->fragment_offset &
+ rte_cpu_to_be_16(IPV4_HDR_OFFSET_MASK |
+ IPV4_HDR_MF_FLAG)) {
+ pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
+ hdr_lens->inner_l4_len = 0;
+ return pkt_type;
+ }
+ proto = ip4h->next_proto_id;
+ pkt_type |= ptype_inner_l4(proto);
+ } else if (proto == rte_cpu_to_be_16(ETHER_TYPE_IPv6)) {
+ const struct ipv6_hdr *ip6h;
+ struct ipv6_hdr ip6h_copy;
+ int frag = 0;
+
+ ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
+ if (unlikely(ip6h == NULL))
+ return pkt_type;
+
+ proto = ip6h->proto;
+ hdr_lens->inner_l3_len = sizeof(*ip6h);
+ off += hdr_lens->inner_l3_len;
+ pkt_type |= ptype_inner_l3_ip6(proto);
+ if ((pkt_type & RTE_PTYPE_INNER_L3_MASK) ==
+ RTE_PTYPE_INNER_L3_IPV6_EXT) {
+ uint32_t prev_off;
+
+ prev_off = off;
+ ret = rte_net_skip_ip6_ext(proto, m, &off, &frag);
+ if (ret < 0)
+ return pkt_type;
+ proto = ret;
+ hdr_lens->inner_l3_len += off - prev_off;
+ }
+ if (proto == 0)
+ return pkt_type;
+
+ if ((layers & RTE_PTYPE_INNER_L4_MASK) == 0)
+ return pkt_type;
+
+ if (frag) {
+ pkt_type |= RTE_PTYPE_INNER_L4_FRAG;
+ hdr_lens->inner_l4_len = 0;
+ return pkt_type;
+ }
+ pkt_type |= ptype_inner_l4(proto);
+ }
+
+ if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == RTE_PTYPE_INNER_L4_UDP) {
+ hdr_lens->inner_l4_len = sizeof(struct udp_hdr);
+ } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
+ RTE_PTYPE_INNER_L4_TCP) {
+ const struct tcp_hdr *th;
+ struct tcp_hdr th_copy;
+
+ th = rte_pktmbuf_read(m, off, sizeof(*th), &th_copy);
+ if (unlikely(th == NULL))
+ return pkt_type & (RTE_PTYPE_INNER_L2_MASK |
+ RTE_PTYPE_INNER_L3_MASK);
+ hdr_lens->inner_l4_len = (th->data_off & 0xf0) >> 2;
+ } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) ==
+ RTE_PTYPE_INNER_L4_SCTP) {
+ hdr_lens->inner_l4_len = sizeof(struct sctp_hdr);
+ } else {
+ hdr_lens->inner_l4_len = 0;
+ }
+
+ return pkt_type;
+}
diff --git a/src/spdk/dpdk/lib/librte_net/rte_net.h b/src/spdk/dpdk/lib/librte_net/rte_net.h
new file mode 100644
index 00000000..b6ab6e1d
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_net.h
@@ -0,0 +1,203 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2016 6WIND S.A.
+ */
+
+#ifndef _RTE_NET_PTYPE_H_
+#define _RTE_NET_PTYPE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_ip.h>
+#include <rte_udp.h>
+#include <rte_tcp.h>
+#include <rte_sctp.h>
+
+/**
+ * Structure containing header lengths associated to a packet, filled
+ * by rte_net_get_ptype().
+ */
+struct rte_net_hdr_lens {
+ uint8_t l2_len;
+ uint8_t l3_len;
+ uint8_t l4_len;
+ uint8_t tunnel_len;
+ uint8_t inner_l2_len;
+ uint8_t inner_l3_len;
+ uint8_t inner_l4_len;
+};
+
+/**
+ * Skip IPv6 header extensions.
+ *
+ * This function skips all IPv6 extensions, returning size of
+ * complete header including options and final protocol value.
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * @param proto
+ * Protocol field of IPv6 header.
+ * @param m
+ * The packet mbuf to be parsed.
+ * @param off
+ * On input, must contain the offset to the first byte following
+ * IPv6 header, on output, contains offset to the first byte
+ * of next layer (after any IPv6 extension header)
+ * @param frag
+ * Contains 1 in output if packet is an IPv6 fragment.
+ * @return
+ * Protocol that follows IPv6 header.
+ * -1 if an error occurs during mbuf parsing.
+ */
+int __rte_experimental
+rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off,
+ int *frag);
+
+/**
+ * Parse an Ethernet packet to get its packet type.
+ *
+ * This function parses the network headers in mbuf data and return its
+ * packet type.
+ *
+ * If it is provided by the user, it also fills a rte_net_hdr_lens
+ * structure that contains the lengths of the parsed network
+ * headers. Each length field is valid only if the associated packet
+ * type is set. For instance, hdr_lens->l2_len is valid only if
+ * (retval & RTE_PTYPE_L2_MASK) != RTE_PTYPE_UNKNOWN.
+ *
+ * Supported packet types are:
+ * L2: Ether, Vlan, QinQ
+ * L3: IPv4, IPv6
+ * L4: TCP, UDP, SCTP
+ * Tunnels: IPv4, IPv6, Gre, Nvgre
+ *
+ * @param m
+ * The packet mbuf to be parsed.
+ * @param hdr_lens
+ * A pointer to a structure where the header lengths will be returned,
+ * or NULL.
+ * @param layers
+ * List of layers to parse. The function will stop at the first
+ * empty layer. Examples:
+ * - To parse all known layers, use RTE_PTYPE_ALL_MASK.
+ * - To parse only L2 and L3, use RTE_PTYPE_L2_MASK | RTE_PTYPE_L3_MASK
+ * @return
+ * The packet type of the packet.
+ */
+uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
+ struct rte_net_hdr_lens *hdr_lens, uint32_t layers);
+
+/**
+ * Prepare pseudo header checksum
+ *
+ * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in
+ * provided mbufs packet data and based on the requested offload flags.
+ *
+ * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
+ * in packet data,
+ * - for TSO the IP payload length is not included in pseudo header.
+ *
+ * This function expects that used headers are in the first data segment of
+ * mbuf, are not fragmented and can be safely modified.
+ *
+ * @param m
+ * The packet mbuf to be fixed.
+ * @param ol_flags
+ * TX offloads flags to use with this packet.
+ * @return
+ * 0 if checksum is initialized properly
+ */
+static inline int
+rte_net_intel_cksum_flags_prepare(struct rte_mbuf *m, uint64_t ol_flags)
+{
+ struct ipv4_hdr *ipv4_hdr;
+ struct ipv6_hdr *ipv6_hdr;
+ struct tcp_hdr *tcp_hdr;
+ struct udp_hdr *udp_hdr;
+ uint64_t inner_l3_offset = m->l2_len;
+
+ if ((ol_flags & PKT_TX_OUTER_IP_CKSUM) ||
+ (ol_flags & PKT_TX_OUTER_IPV6))
+ inner_l3_offset += m->outer_l2_len + m->outer_l3_len;
+
+ if ((ol_flags & PKT_TX_UDP_CKSUM) == PKT_TX_UDP_CKSUM) {
+ if (ol_flags & PKT_TX_IPV4) {
+ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
+ inner_l3_offset);
+
+ if (ol_flags & PKT_TX_IP_CKSUM)
+ ipv4_hdr->hdr_checksum = 0;
+
+ udp_hdr = (struct udp_hdr *)((char *)ipv4_hdr +
+ m->l3_len);
+ udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
+ ol_flags);
+ } else {
+ ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *,
+ inner_l3_offset);
+ /* non-TSO udp */
+ udp_hdr = rte_pktmbuf_mtod_offset(m, struct udp_hdr *,
+ inner_l3_offset + m->l3_len);
+ udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
+ ol_flags);
+ }
+ } else if ((ol_flags & PKT_TX_TCP_CKSUM) ||
+ (ol_flags & PKT_TX_TCP_SEG)) {
+ if (ol_flags & PKT_TX_IPV4) {
+ ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct ipv4_hdr *,
+ inner_l3_offset);
+
+ if (ol_flags & PKT_TX_IP_CKSUM)
+ ipv4_hdr->hdr_checksum = 0;
+
+ /* non-TSO tcp or TSO */
+ tcp_hdr = (struct tcp_hdr *)((char *)ipv4_hdr +
+ m->l3_len);
+ tcp_hdr->cksum = rte_ipv4_phdr_cksum(ipv4_hdr,
+ ol_flags);
+ } else {
+ ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct ipv6_hdr *,
+ inner_l3_offset);
+ /* non-TSO tcp or TSO */
+ tcp_hdr = rte_pktmbuf_mtod_offset(m, struct tcp_hdr *,
+ inner_l3_offset + m->l3_len);
+ tcp_hdr->cksum = rte_ipv6_phdr_cksum(ipv6_hdr,
+ ol_flags);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Prepare pseudo header checksum
+ *
+ * This function prepares pseudo header checksum for TSO and non-TSO tcp/udp in
+ * provided mbufs packet data.
+ *
+ * - for non-TSO tcp/udp packets full pseudo-header checksum is counted and set
+ * in packet data,
+ * - for TSO the IP payload length is not included in pseudo header.
+ *
+ * This function expects that used headers are in the first data segment of
+ * mbuf, are not fragmented and can be safely modified.
+ *
+ * @param m
+ * The packet mbuf to be fixed.
+ * @return
+ * 0 if checksum is initialized properly
+ */
+static inline int
+rte_net_intel_cksum_prepare(struct rte_mbuf *m)
+{
+ return rte_net_intel_cksum_flags_prepare(m, m->ol_flags);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _RTE_NET_PTYPE_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_net_crc.c b/src/spdk/dpdk/lib/librte_net/rte_net_crc.c
new file mode 100644
index 00000000..73ac3a95
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_net_crc.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include <stddef.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <rte_cpuflags.h>
+#include <rte_common.h>
+#include <rte_net_crc.h>
+
+#if defined(RTE_ARCH_X86_64) && defined(RTE_MACHINE_CPUFLAG_PCLMULQDQ)
+#define X86_64_SSE42_PCLMULQDQ 1
+#elif defined(RTE_ARCH_ARM64) && defined(RTE_MACHINE_CPUFLAG_PMULL)
+#define ARM64_NEON_PMULL 1
+#endif
+
+#ifdef X86_64_SSE42_PCLMULQDQ
+#include <net_crc_sse.h>
+#elif defined ARM64_NEON_PMULL
+#include <net_crc_neon.h>
+#endif
+
+/* crc tables */
+static uint32_t crc32_eth_lut[CRC_LUT_SIZE];
+static uint32_t crc16_ccitt_lut[CRC_LUT_SIZE];
+
+static uint32_t
+rte_crc16_ccitt_handler(const uint8_t *data, uint32_t data_len);
+
+static uint32_t
+rte_crc32_eth_handler(const uint8_t *data, uint32_t data_len);
+
+typedef uint32_t
+(*rte_net_crc_handler)(const uint8_t *data, uint32_t data_len);
+
+static rte_net_crc_handler *handlers;
+
+static rte_net_crc_handler handlers_scalar[] = {
+ [RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_handler,
+ [RTE_NET_CRC32_ETH] = rte_crc32_eth_handler,
+};
+
+#ifdef X86_64_SSE42_PCLMULQDQ
+static rte_net_crc_handler handlers_sse42[] = {
+ [RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_sse42_handler,
+ [RTE_NET_CRC32_ETH] = rte_crc32_eth_sse42_handler,
+};
+#elif defined ARM64_NEON_PMULL
+static rte_net_crc_handler handlers_neon[] = {
+ [RTE_NET_CRC16_CCITT] = rte_crc16_ccitt_neon_handler,
+ [RTE_NET_CRC32_ETH] = rte_crc32_eth_neon_handler,
+};
+#endif
+
+/**
+ * Reflect the bits about the middle
+ *
+ * @param val
+ * value to be reflected
+ *
+ * @return
+ * reflected value
+ */
+static uint32_t
+reflect_32bits(uint32_t val)
+{
+ uint32_t i, res = 0;
+
+ for (i = 0; i < 32; i++)
+ if ((val & (1 << i)) != 0)
+ res |= (uint32_t)(1 << (31 - i));
+
+ return res;
+}
+
+static void
+crc32_eth_init_lut(uint32_t poly,
+ uint32_t *lut)
+{
+ uint32_t i, j;
+
+ for (i = 0; i < CRC_LUT_SIZE; i++) {
+ uint32_t crc = reflect_32bits(i);
+
+ for (j = 0; j < 8; j++) {
+ if (crc & 0x80000000L)
+ crc = (crc << 1) ^ poly;
+ else
+ crc <<= 1;
+ }
+ lut[i] = reflect_32bits(crc);
+ }
+}
+
+static __rte_always_inline uint32_t
+crc32_eth_calc_lut(const uint8_t *data,
+ uint32_t data_len,
+ uint32_t crc,
+ const uint32_t *lut)
+{
+ while (data_len--)
+ crc = lut[(crc ^ *data++) & 0xffL] ^ (crc >> 8);
+
+ return crc;
+}
+
+static void
+rte_net_crc_scalar_init(void)
+{
+ /* 32-bit crc init */
+ crc32_eth_init_lut(CRC32_ETH_POLYNOMIAL, crc32_eth_lut);
+
+ /* 16-bit CRC init */
+ crc32_eth_init_lut(CRC16_CCITT_POLYNOMIAL << 16, crc16_ccitt_lut);
+}
+
+static inline uint32_t
+rte_crc16_ccitt_handler(const uint8_t *data, uint32_t data_len)
+{
+ /* return 16-bit CRC value */
+ return (uint16_t)~crc32_eth_calc_lut(data,
+ data_len,
+ 0xffff,
+ crc16_ccitt_lut);
+}
+
+static inline uint32_t
+rte_crc32_eth_handler(const uint8_t *data, uint32_t data_len)
+{
+ /* return 32-bit CRC value */
+ return ~crc32_eth_calc_lut(data,
+ data_len,
+ 0xffffffffUL,
+ crc32_eth_lut);
+}
+
+void
+rte_net_crc_set_alg(enum rte_net_crc_alg alg)
+{
+ switch (alg) {
+#ifdef X86_64_SSE42_PCLMULQDQ
+ case RTE_NET_CRC_SSE42:
+ handlers = handlers_sse42;
+ break;
+#elif defined ARM64_NEON_PMULL
+ /* fall-through */
+ case RTE_NET_CRC_NEON:
+ if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_PMULL)) {
+ handlers = handlers_neon;
+ break;
+ }
+#endif
+ /* fall-through */
+ case RTE_NET_CRC_SCALAR:
+ /* fall-through */
+ default:
+ handlers = handlers_scalar;
+ break;
+ }
+}
+
+uint32_t
+rte_net_crc_calc(const void *data,
+ uint32_t data_len,
+ enum rte_net_crc_type type)
+{
+ uint32_t ret;
+ rte_net_crc_handler f_handle;
+
+ f_handle = handlers[type];
+ ret = f_handle(data, data_len);
+
+ return ret;
+}
+
+/* Select highest available crc algorithm as default one */
+RTE_INIT(rte_net_crc_init)
+{
+ enum rte_net_crc_alg alg = RTE_NET_CRC_SCALAR;
+
+ rte_net_crc_scalar_init();
+
+#ifdef X86_64_SSE42_PCLMULQDQ
+ alg = RTE_NET_CRC_SSE42;
+ rte_net_crc_sse42_init();
+#elif defined ARM64_NEON_PMULL
+ if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_PMULL)) {
+ alg = RTE_NET_CRC_NEON;
+ rte_net_crc_neon_init();
+ }
+#endif
+
+ rte_net_crc_set_alg(alg);
+}
diff --git a/src/spdk/dpdk/lib/librte_net/rte_net_crc.h b/src/spdk/dpdk/lib/librte_net/rte_net_crc.h
new file mode 100644
index 00000000..8a86f297
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_net_crc.h
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#ifndef _RTE_NET_CRC_H_
+#define _RTE_NET_CRC_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** CRC polynomials */
+#define CRC32_ETH_POLYNOMIAL 0x04c11db7UL
+#define CRC16_CCITT_POLYNOMIAL 0x1021U
+
+#define CRC_LUT_SIZE 256
+
+/** CRC types */
+enum rte_net_crc_type {
+ RTE_NET_CRC16_CCITT = 0,
+ RTE_NET_CRC32_ETH,
+ RTE_NET_CRC_REQS
+};
+
+/** CRC compute algorithm */
+enum rte_net_crc_alg {
+ RTE_NET_CRC_SCALAR = 0,
+ RTE_NET_CRC_SSE42,
+ RTE_NET_CRC_NEON,
+};
+
+/**
+ * This API set the CRC computation algorithm (i.e. scalar version,
+ * x86 64-bit sse4.2 intrinsic version, etc.) and internal data
+ * structure.
+ *
+ * @param alg
+ * This parameter is used to select the CRC implementation version.
+ * - RTE_NET_CRC_SCALAR
+ * - RTE_NET_CRC_SSE42 (Use 64-bit SSE4.2 intrinsic)
+ * - RTE_NET_CRC_NEON (Use ARM Neon intrinsic)
+ */
+void
+rte_net_crc_set_alg(enum rte_net_crc_alg alg);
+
+/**
+ * CRC compute API
+ *
+ * @param data
+ * Pointer to the packet data for CRC computation
+ * @param data_len
+ * Data length for CRC computation
+ * @param type
+ * CRC type (enum rte_net_crc_type)
+ *
+ * @return
+ * CRC value
+ */
+uint32_t
+rte_net_crc_calc(const void *data,
+ uint32_t data_len,
+ enum rte_net_crc_type type);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _RTE_NET_CRC_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_net_version.map b/src/spdk/dpdk/lib/librte_net/rte_net_version.map
new file mode 100644
index 00000000..26c06e7c
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_net_version.map
@@ -0,0 +1,21 @@
+DPDK_16.11 {
+ global:
+ rte_net_get_ptype;
+
+ local: *;
+};
+
+DPDK_17.05 {
+ global:
+
+ rte_net_crc_calc;
+ rte_net_crc_set_alg;
+
+} DPDK_16.11;
+
+EXPERIMENTAL {
+ global:
+
+ rte_net_make_rarp_packet;
+ rte_net_skip_ip6_ext;
+};
diff --git a/src/spdk/dpdk/lib/librte_net/rte_sctp.h b/src/spdk/dpdk/lib/librte_net/rte_sctp.h
new file mode 100644
index 00000000..bfb7165a
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_sctp.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California.
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * All rights reserved.
+ */
+
+/**
+ * @file
+ *
+ * SCTP-related defines
+ */
+
+#ifndef _RTE_SCTP_H_
+#define _RTE_SCTP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/**
+ * SCTP Header
+ */
+struct sctp_hdr {
+ uint16_t src_port; /**< Source port. */
+ uint16_t dst_port; /**< Destin port. */
+ uint32_t tag; /**< Validation tag. */
+ uint32_t cksum; /**< Checksum. */
+} __attribute__((__packed__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_SCTP_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_tcp.h b/src/spdk/dpdk/lib/librte_net/rte_tcp.h
new file mode 100644
index 00000000..91f58987
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_tcp.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California.
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * All rights reserved.
+ */
+
+#ifndef _RTE_TCP_H_
+#define _RTE_TCP_H_
+
+/**
+ * @file
+ *
+ * TCP-related defines
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * TCP Header
+ */
+struct tcp_hdr {
+ uint16_t src_port; /**< TCP source port. */
+ uint16_t dst_port; /**< TCP destination port. */
+ uint32_t sent_seq; /**< TX data sequence number. */
+ uint32_t recv_ack; /**< RX data acknowledgement sequence number. */
+ uint8_t data_off; /**< Data offset. */
+ uint8_t tcp_flags; /**< TCP flags */
+ uint16_t rx_win; /**< RX flow control window. */
+ uint16_t cksum; /**< TCP checksum. */
+ uint16_t tcp_urp; /**< TCP urgent pointer, if any. */
+} __attribute__((__packed__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_TCP_H_ */
diff --git a/src/spdk/dpdk/lib/librte_net/rte_udp.h b/src/spdk/dpdk/lib/librte_net/rte_udp.h
new file mode 100644
index 00000000..ba033955
--- /dev/null
+++ b/src/spdk/dpdk/lib/librte_net/rte_udp.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 1982, 1986, 1990, 1993
+ * The Regents of the University of California.
+ * Copyright(c) 2010-2014 Intel Corporation.
+ * All rights reserved.
+ */
+
+#ifndef _RTE_UDP_H_
+#define _RTE_UDP_H_
+
+/**
+ * @file
+ *
+ * UDP-related defines
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * UDP Header
+ */
+struct udp_hdr {
+ uint16_t src_port; /**< UDP source port. */
+ uint16_t dst_port; /**< UDP destination port. */
+ uint16_t dgram_len; /**< UDP datagram length */
+ uint16_t dgram_cksum; /**< UDP datagram checksum */
+} __attribute__((__packed__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_UDP_H_ */