diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/spdk/dpdk/lib/librte_net | |
parent | Initial commit. (diff) | |
download | ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/spdk/dpdk/lib/librte_net')
24 files changed, 3371 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 000000000..aa1d6fed5 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/Makefile @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2010-2014 Intel Corporation + +include $(RTE_SDK)/mk/rte.vars.mk + +LIB = librte_net.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lrte_mbuf -lrte_eal -lrte_mempool + +EXPORT_MAP := rte_net_version.map +SRCS-$(CONFIG_RTE_LIBRTE_NET) := rte_net.c +SRCS-$(CONFIG_RTE_LIBRTE_NET) += rte_net_crc.c +SRCS-$(CONFIG_RTE_LIBRTE_NET) += rte_ether.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 rte_mpls.h rte_higig.h +SYMLINK-$(CONFIG_RTE_LIBRTE_NET)-include += rte_gtp.h rte_vxlan.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 000000000..f799349b3 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/meson.build @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation + +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_vxlan.h', + 'rte_gre.h', + 'rte_gtp.h', + 'rte_net.h', + 'rte_net_crc.h', + 'rte_mpls.h', + 'rte_higig.h') + +sources = files('rte_arp.c', 'rte_ether.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 000000000..63fa1d4a1 --- /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 000000000..1c7b7a548 --- /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; +}; + +static struct crc_pclmulqdq_ctx crc32_eth_pclmulqdq __rte_aligned(16); +static 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 000000000..784b7f48f --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_arp.c @@ -0,0 +1,51 @@ +/* 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_net_make_rarp_packet(struct rte_mempool *mpool, + const struct rte_ether_addr *mac) +{ + struct rte_ether_hdr *eth_hdr; + struct rte_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 rte_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, RTE_ETHER_ADDR_LEN); + rte_ether_addr_copy(mac, ð_hdr->s_addr); + eth_hdr->ether_type = htons(RTE_ETHER_TYPE_RARP); + + /* RARP header. */ + rarp = (struct rte_arp_hdr *)(eth_hdr + 1); + rarp->arp_hardware = htons(RTE_ARP_HRD_ETHER); + rarp->arp_protocol = htons(RTE_ETHER_TYPE_IPV4); + rarp->arp_hlen = RTE_ETHER_ADDR_LEN; + rarp->arp_plen = 4; + rarp->arp_opcode = htons(RTE_ARP_OP_REVREQUEST); + + rte_ether_addr_copy(mac, &rarp->arp_data.arp_sha); + rte_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 000000000..feb0eb3e4 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_arp.h @@ -0,0 +1,75 @@ +/* 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 rte_arp_ipv4 { + struct rte_ether_addr arp_sha; /**< sender hardware address */ + uint32_t arp_sip; /**< sender IP address */ + struct rte_ether_addr arp_tha; /**< target hardware address */ + uint32_t arp_tip; /**< target IP address */ +} __rte_packed __rte_aligned(2); + +/** + * ARP header. + */ +struct rte_arp_hdr { + uint16_t arp_hardware; /* format of hardware address */ +#define RTE_ARP_HRD_ETHER 1 /* ARP Ethernet address format */ + + uint16_t arp_protocol; /* format of protocol address */ + uint8_t arp_hlen; /* length of hardware address */ + uint8_t arp_plen; /* length of protocol address */ + uint16_t arp_opcode; /* ARP opcode (command) */ +#define RTE_ARP_OP_REQUEST 1 /* request to resolve address */ +#define RTE_ARP_OP_REPLY 2 /* response to previous request */ +#define RTE_ARP_OP_REVREQUEST 3 /* request proto addr given hardware */ +#define RTE_ARP_OP_REVREPLY 4 /* response giving protocol address */ +#define RTE_ARP_OP_INVREQUEST 8 /* request to identify peer */ +#define RTE_ARP_OP_INVREPLY 9 /* response identifying peer */ + + struct rte_arp_ipv4 arp_data; +} __rte_packed __rte_aligned(2); + +/** + * @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 + */ +__rte_experimental +struct rte_mbuf * +rte_net_make_rarp_packet(struct rte_mempool *mpool, + const struct rte_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 000000000..464c513e2 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_esp.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2016 Mellanox Technologies, Ltd + */ + +#ifndef _RTE_ESP_H_ +#define _RTE_ESP_H_ + +/** + * @file + * + * ESP-related defines + */ + +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ESP Header + */ +struct rte_esp_hdr { + rte_be32_t spi; /**< Security Parameters Index */ + rte_be32_t seq; /**< packet sequence number */ +} __rte_packed; + +/** + * ESP Trailer + */ +struct rte_esp_tail { + uint8_t pad_len; /**< number of pad bytes (0-255) */ + uint8_t next_proto; /**< IPv4 or IPv6 or next layer header */ +} __rte_packed; + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_ESP_H_ */ diff --git a/src/spdk/dpdk/lib/librte_net/rte_ether.c b/src/spdk/dpdk/lib/librte_net/rte_ether.c new file mode 100644 index 000000000..ced65ed9f --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_ether.c @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include <stdbool.h> + +#include <rte_ether.h> +#include <rte_errno.h> + +void +rte_eth_random_addr(uint8_t *addr) +{ + uint64_t rand = rte_rand(); + uint8_t *p = (uint8_t *)&rand; + + rte_memcpy(addr, p, RTE_ETHER_ADDR_LEN); + addr[0] &= (uint8_t)~RTE_ETHER_GROUP_ADDR; /* clear multicast bit */ + addr[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR; /* set local assignment bit */ +} + +void +rte_ether_format_addr(char *buf, uint16_t size, + const struct rte_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]); +} + +static int8_t get_xdigit(char ch) +{ + if (ch >= '0' && ch <= '9') + return ch - '0'; + if (ch >= 'a' && ch <= 'f') + return ch - 'a' + 10; + if (ch >= 'A' && ch <= 'F') + return ch - 'A' + 10; + return -1; +} + +/* Convert 00:11:22:33:44:55 to ethernet address */ +static bool get_ether_addr6(const char *s0, struct rte_ether_addr *ea) +{ + const char *s = s0; + int i; + + for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) { + int8_t x; + + x = get_xdigit(*s++); + if (x < 0) + return false; + + ea->addr_bytes[i] = x << 4; + x = get_xdigit(*s++); + if (x < 0) + return false; + ea->addr_bytes[i] |= x; + + if (i < RTE_ETHER_ADDR_LEN - 1 && + *s++ != ':') + return false; + } + + /* return true if at end of string */ + return *s == '\0'; +} + +/* Convert 0011:2233:4455 to ethernet address */ +static bool get_ether_addr3(const char *s, struct rte_ether_addr *ea) +{ + int i, j; + + for (i = 0; i < RTE_ETHER_ADDR_LEN; i += 2) { + uint16_t w = 0; + + for (j = 0; j < 4; j++) { + int8_t x; + + x = get_xdigit(*s++); + if (x < 0) + return false; + w = (w << 4) | x; + } + ea->addr_bytes[i] = w >> 8; + ea->addr_bytes[i + 1] = w & 0xff; + + if (i < RTE_ETHER_ADDR_LEN - 2 && + *s++ != ':') + return false; + } + + return *s == '\0'; +} + +/* + * Like ether_aton_r but can handle either + * XX:XX:XX:XX:XX:XX or XXXX:XXXX:XXXX + * and is more restrictive. + */ +int +rte_ether_unformat_addr(const char *s, struct rte_ether_addr *ea) +{ + if (get_ether_addr6(s, ea)) + return 0; + if (get_ether_addr3(s, ea)) + return 0; + + rte_errno = EINVAL; + return -1; +} 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 000000000..0ae4e75b6 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_ether.h @@ -0,0 +1,386 @@ +/* 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 RTE_ETHER_ADDR_LEN 6 /**< Length of Ethernet address. */ +#define RTE_ETHER_TYPE_LEN 2 /**< Length of Ethernet type field. */ +#define RTE_ETHER_CRC_LEN 4 /**< Length of Ethernet CRC. */ +#define RTE_ETHER_HDR_LEN \ + (RTE_ETHER_ADDR_LEN * 2 + \ + RTE_ETHER_TYPE_LEN) /**< Length of Ethernet header. */ +#define RTE_ETHER_MIN_LEN 64 /**< Minimum frame len, including CRC. */ +#define RTE_ETHER_MAX_LEN 1518 /**< Maximum frame len, including CRC. */ +#define RTE_ETHER_MTU \ + (RTE_ETHER_MAX_LEN - RTE_ETHER_HDR_LEN - \ + RTE_ETHER_CRC_LEN) /**< Ethernet MTU. */ + +#define RTE_ETHER_MAX_VLAN_FRAME_LEN \ + (RTE_ETHER_MAX_LEN + 4) + /**< Maximum VLAN frame length, including CRC. */ + +#define RTE_ETHER_MAX_JUMBO_FRAME_LEN \ + 0x3F00 /**< Maximum Jumbo frame length, including CRC. */ + +#define RTE_ETHER_MAX_VLAN_ID 4095 /**< Maximum VLAN ID. */ + +#define RTE_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 rte_ether_addr { + uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; /**< Addr bytes in tx order */ +} __rte_aligned(2); + +#define RTE_ETHER_LOCAL_ADMIN_ADDR 0x02 /**< Locally assigned Eth. address. */ +#define RTE_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 rte_is_same_ether_addr(const struct rte_ether_addr *ea1, + const struct rte_ether_addr *ea2) +{ + const uint16_t *w1 = (const uint16_t *)ea1; + const uint16_t *w2 = (const uint16_t *)ea2; + + return ((w1[0] ^ w2[0]) | (w1[1] ^ w2[1]) | (w1[2] ^ w2[2])) == 0; +} + +/** + * 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 rte_is_zero_ether_addr(const struct rte_ether_addr *ea) +{ + const uint16_t *w = (const uint16_t *)ea; + + return (w[0] | w[1] | w[2]) == 0; +} + +/** + * 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 rte_is_unicast_ether_addr(const struct rte_ether_addr *ea) +{ + return (ea->addr_bytes[0] & RTE_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 rte_is_multicast_ether_addr(const struct rte_ether_addr *ea) +{ + return ea->addr_bytes[0] & RTE_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 rte_is_broadcast_ether_addr(const struct rte_ether_addr *ea) +{ + const uint16_t *ea_words = (const 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 rte_is_universal_ether_addr(const struct rte_ether_addr *ea) +{ + return (ea->addr_bytes[0] & RTE_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 rte_is_local_admin_ether_addr(const struct rte_ether_addr *ea) +{ + return (ea->addr_bytes[0] & RTE_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 rte_is_valid_assigned_ether_addr(const struct rte_ether_addr *ea) +{ + return rte_is_unicast_ether_addr(ea) && (!rte_is_zero_ether_addr(ea)); +} + +/** + * Generate a random Ethernet address that is locally administered + * and not multicast. + * @param addr + * A pointer to Ethernet address. + */ +void +rte_eth_random_addr(uint8_t *addr); + +/** + * 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 rte_ether_addr_copy(const struct rte_ether_addr *ea_from, + struct rte_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 RTE_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. + */ +void +rte_ether_format_addr(char *buf, uint16_t size, + const struct rte_ether_addr *eth_addr); +/** + * Convert string with Ethernet address to an ether_addr. + * + * @param str + * A pointer to buffer contains the formatted MAC address. + * The supported formats are: + * XX:XX:XX:XX:XX:XX or XXXX:XXXX:XXXX + * where XX is a hex digit: 0-9, a-f, or A-F. + * @param eth_addr + * A pointer to a ether_addr structure. + * @return + * 0 if successful + * -1 and sets rte_errno if invalid string + */ +__rte_experimental +int +rte_ether_unformat_addr(const char *str, struct rte_ether_addr *eth_addr); + +/** + * Ethernet header: Contains the destination address, source address + * and frame type. + */ +struct rte_ether_hdr { + struct rte_ether_addr d_addr; /**< Destination address. */ + struct rte_ether_addr s_addr; /**< Source address. */ + uint16_t ether_type; /**< Frame type. */ +} __rte_aligned(2); + +/** + * Ethernet VLAN Header. + * Contains the 16-bit VLAN Tag Control Identifier and the Ethernet type + * of the encapsulated frame. + */ +struct rte_vlan_hdr { + uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */ + uint16_t eth_proto;/**< Ethernet type of encapsulated frame. */ +} __rte_packed; + + + +/* Ethernet frame types */ +#define RTE_ETHER_TYPE_IPV4 0x0800 /**< IPv4 Protocol. */ +#define RTE_ETHER_TYPE_IPV6 0x86DD /**< IPv6 Protocol. */ +#define RTE_ETHER_TYPE_ARP 0x0806 /**< Arp Protocol. */ +#define RTE_ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */ +#define RTE_ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ +#define RTE_ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */ +#define RTE_ETHER_TYPE_PPPOE_DISCOVERY 0x8863 /**< PPPoE Discovery Stage. */ +#define RTE_ETHER_TYPE_PPPOE_SESSION 0x8864 /**< PPPoE Session Stage. */ +#define RTE_ETHER_TYPE_ETAG 0x893F /**< IEEE 802.1BR E-Tag. */ +#define RTE_ETHER_TYPE_1588 0x88F7 + /**< IEEE 802.1AS 1588 Precise Time Protocol. */ +#define RTE_ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). */ +#define RTE_ETHER_TYPE_TEB 0x6558 /**< Transparent Ethernet Bridging. */ +#define RTE_ETHER_TYPE_LLDP 0x88CC /**< LLDP Protocol. */ +#define RTE_ETHER_TYPE_MPLS 0x8847 /**< MPLS ethertype. */ +#define RTE_ETHER_TYPE_MPLSM 0x8848 /**< MPLS multicast ethertype. */ + +/** + * 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 rte_ether_hdr *eh + = rte_pktmbuf_mtod(m, struct rte_ether_hdr *); + struct rte_vlan_hdr *vh; + + if (eh->ether_type != rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) + return -1; + + vh = (struct rte_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 rte_vlan_hdr)), + eh, 2 * RTE_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 rte_ether_hdr *oh, *nh; + struct rte_vlan_hdr *vh; + + /* Can't insert header if mbuf is shared */ + if (!RTE_MBUF_DIRECT(*m) || rte_mbuf_refcnt_read(*m) > 1) + return -EINVAL; + + oh = rte_pktmbuf_mtod(*m, struct rte_ether_hdr *); + nh = (struct rte_ether_hdr *) + rte_pktmbuf_prepend(*m, sizeof(struct rte_vlan_hdr)); + if (nh == NULL) + return -ENOSPC; + + memmove(nh, oh, 2 * RTE_ETHER_ADDR_LEN); + nh->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); + + vh = (struct rte_vlan_hdr *) (nh + 1); + vh->vlan_tci = rte_cpu_to_be_16((*m)->vlan_tci); + + (*m)->ol_flags &= ~(PKT_RX_VLAN_STRIPPED | PKT_TX_VLAN); + + if ((*m)->ol_flags & PKT_TX_TUNNEL_MASK) + (*m)->outer_l2_len += sizeof(struct rte_vlan_hdr); + else + (*m)->l2_len += sizeof(struct rte_vlan_hdr); + + 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 000000000..ac3ddaada --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_gre.h @@ -0,0 +1,44 @@ +/* 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 + */ +__extension__ +struct rte_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 */ +} __rte_packed; + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_GRE_H_ */ diff --git a/src/spdk/dpdk/lib/librte_net/rte_gtp.h b/src/spdk/dpdk/lib/librte_net/rte_gtp.h new file mode 100644 index 000000000..104384cc5 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_gtp.h @@ -0,0 +1,51 @@ +/* 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_GTP_H_ +#define _RTE_GTP_H_ + +/** + * @file + * + * GTP-related defines + */ + +#include <stdint.h> +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Simplified GTP protocol header. + * Contains 8-bit header info, 8-bit message type, + * 16-bit payload length after mandatory header, 32-bit TEID. + * No optional fields and next extension header. + */ +struct rte_gtp_hdr { + uint8_t gtp_hdr_info; /**< GTP header info */ + uint8_t msg_type; /**< GTP message type */ + uint16_t plen; /**< Total payload length */ + uint32_t teid; /**< Tunnel endpoint ID */ +} __rte_packed; + +/** GTP header length */ +#define RTE_ETHER_GTP_HLEN \ + (sizeof(struct rte_udp_hdr) + sizeof(struct rte_gtp_hdr)) +/* GTP next protocal type */ +#define RTE_GTP_TYPE_IPV4 0x40 /**< GTP next protocal type IPv4 */ +#define RTE_GTP_TYPE_IPV6 0x60 /**< GTP next protocal type IPv6 */ +/* GTP destination port number */ +#define RTE_GTPC_UDP_PORT 2123 /**< GTP-C UDP destination port */ +#define RTE_GTPU_UDP_PORT 2152 /**< GTP-U UDP destination port */ + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_GTP_H_ */ diff --git a/src/spdk/dpdk/lib/librte_net/rte_higig.h b/src/spdk/dpdk/lib/librte_net/rte_higig.h new file mode 100644 index 000000000..b9cdfefed --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_higig.h @@ -0,0 +1,145 @@ + +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2019 Marvell International Ltd. + */ + +#ifndef _RTE_HIGIG_H_ +#define _RTE_HIGIG_H_ + +#include <stdint.h> +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * higig2 frc header. + */ +struct rte_higig2_frc { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t ksop:8; + uint32_t tc:4; + uint32_t mcst:1; + uint32_t resv:3; + uint32_t dst_modid:8; + uint32_t dst_pid:8; + uint32_t src_modid:8; + uint32_t src_pid:8; + uint32_t lbid:8; + uint32_t ppd_type:3; + uint32_t resv1:3; + uint32_t dp:2; +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t ksop:8; + uint32_t resv:3; + uint32_t mcst:1; + uint32_t tc:4; + uint32_t dst_modid:8; + uint32_t dst_pid:8; + uint32_t src_modid:8; + uint32_t src_pid:8; + uint32_t lbid:8; + uint32_t dp:2; + uint32_t resv1:3; + uint32_t ppd_type:3; +#endif +}; + + +/** + * + * higig2 ppt type0 header + */ +struct rte_higig2_ppt_type0 { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint32_t mirror:1; + uint32_t mirror_done:1; + uint32_t mirror_only:1; + uint32_t ingress_tagged:1; + uint32_t dst_tgid:3; + uint32_t dst_t:1; + uint32_t vc_label2:4; + uint32_t label_present:1; + uint32_t l3:1; + uint32_t res:2; + uint32_t vc_label1:8; + uint32_t vc_label0:8; + uint32_t vid_high:8; + uint32_t vid_low:8; + uint32_t opc:3; + uint32_t res1:2; + uint32_t srce_t:1; + uint32_t pf:2; + uint32_t res2:5; + uint32_t hdr_ext_length:3; +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint32_t dst_t:1; + uint32_t dst_tgid:3; + uint32_t ingress_tagged:1; + uint32_t mirror_only:1; + uint32_t mirror_done:1; + uint32_t mirror:1; + uint32_t res:2; + uint32_t l3:1; + uint32_t label_present:1; + uint32_t vc_label2:4; + uint32_t vc_label1:8; + uint32_t vc_label0:8; + uint32_t vid_high:8; + uint32_t vid_low:8; + uint32_t pf:2; + uint32_t srce_t:1; + uint32_t res1:2; + uint32_t opc:3; + uint32_t hdr_ext_length:3; + uint32_t res2:5; +#endif +}; + + +/** + * + * higig2 ppt type1 header. + */ +__extension__ +struct rte_higig2_ppt_type1 { + uint16_t classification; + uint16_t resv; + uint16_t vid; +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + uint16_t opcode:3; + uint16_t resv1:2; + uint16_t src_t:1; + uint16_t pfm:2; + uint16_t resv2:5; + uint16_t hdr_ext_len:3; +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint16_t pfm:2; + uint16_t src_t:1; + uint16_t resv1:2; + uint16_t opcode:3; + uint16_t hdr_ext_len:3; + uint16_t resv2:5; +#endif +}; + +/** + * + * higig2 header + */ +RTE_STD_C11 +struct rte_higig2_hdr { + struct rte_higig2_frc fcr; + union { + struct rte_higig2_ppt_type0 ppt0; + struct rte_higig2_ppt_type1 ppt1; + }; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_HIGIG_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 000000000..4429e8e29 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_icmp.h @@ -0,0 +1,44 @@ +/* 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> + +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * ICMP Header + */ +struct rte_icmp_hdr { + uint8_t icmp_type; /* ICMP packet type. */ + uint8_t icmp_code; /* ICMP packet code. */ + rte_be16_t icmp_cksum; /* ICMP packet checksum. */ + rte_be16_t icmp_ident; /* ICMP packet identifier. */ + rte_be16_t icmp_seq_nb; /* ICMP packet sequence number. */ +} __rte_packed; + +/* ICMP packet types */ +#define RTE_IP_ICMP_ECHO_REPLY 0 +#define RTE_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 000000000..4c4437a54 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_ip.h @@ -0,0 +1,501 @@ +/* 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 <sys/types.h> +#include <netinet/in.h> +#include <netinet/ip.h> + +#include <rte_byteorder.h> +#include <rte_mbuf.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * IPv4 Header + */ +struct rte_ipv4_hdr { + uint8_t version_ihl; /**< version and header length */ + uint8_t type_of_service; /**< type of service */ + rte_be16_t total_length; /**< length of packet */ + rte_be16_t packet_id; /**< packet ID */ + rte_be16_t fragment_offset; /**< fragmentation offset */ + uint8_t time_to_live; /**< time to live */ + uint8_t next_proto_id; /**< protocol ID */ + rte_be16_t hdr_checksum; /**< header checksum */ + rte_be32_t src_addr; /**< source address */ + rte_be32_t dst_addr; /**< destination address */ +} __rte_packed; + +/** Create IPv4 address */ +#define RTE_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 RTE_IPV4_MAX_PKT_LEN 65535 + +/** Internet header length mask for version_ihl field */ +#define RTE_IPV4_HDR_IHL_MASK (0x0f) +/** + * Internet header length field multiplier (IHL field specifies overall header + * length in number of 4-byte words) + */ +#define RTE_IPV4_IHL_MULTIPLIER (4) + +/* Type of Service fields */ +#define RTE_IPV4_HDR_DSCP_MASK (0xfc) +#define RTE_IPV4_HDR_ECN_MASK (0x03) +#define RTE_IPV4_HDR_ECN_CE RTE_IPV4_HDR_ECN_MASK + +/* Fragment Offset * Flags. */ +#define RTE_IPV4_HDR_DF_SHIFT 14 +#define RTE_IPV4_HDR_MF_SHIFT 13 +#define RTE_IPV4_HDR_FO_SHIFT 3 + +#define RTE_IPV4_HDR_DF_FLAG (1 << RTE_IPV4_HDR_DF_SHIFT) +#define RTE_IPV4_HDR_MF_FLAG (1 << RTE_IPV4_HDR_MF_SHIFT) + +#define RTE_IPV4_HDR_OFFSET_MASK ((1 << RTE_IPV4_HDR_MF_SHIFT) - 1) + +#define RTE_IPV4_HDR_OFFSET_UNITS 8 + +/* + * IPv4 address types + */ +#define RTE_IPV4_ANY ((uint32_t)0x00000000) /**< 0.0.0.0 */ +#define RTE_IPV4_LOOPBACK ((uint32_t)0x7f000001) /**< 127.0.0.1 */ +#define RTE_IPV4_BROADCAST ((uint32_t)0xe0000000) /**< 224.0.0.0 */ +#define RTE_IPV4_ALLHOSTS_GROUP ((uint32_t)0xe0000001) /**< 224.0.0.1 */ +#define RTE_IPV4_ALLRTRS_GROUP ((uint32_t)0xe0000002) /**< 224.0.0.2 */ +#define RTE_IPV4_MAX_LOCAL_GROUP ((uint32_t)0xe00000ff) /**< 224.0.0.255 */ + +/* + * IPv4 Multicast-related macros + */ +#define RTE_IPV4_MIN_MCAST \ + RTE_IPV4(224, 0, 0, 0) /**< Minimal IPv4-multicast address */ +#define RTE_IPV4_MAX_MCAST \ + RTE_IPV4(239, 255, 255, 255) /**< Maximum IPv4 multicast address */ + +#define RTE_IS_IPV4_MCAST(x) \ + ((x) >= RTE_IPV4_MIN_MCAST && (x) <= RTE_IPV4_MAX_MCAST) + /**< check if IPv4 address is multicast */ + +/* IPv4 default fields values */ +#define RTE_IPV4_MIN_IHL (0x5) +#define RTE_IPV4_VHL_DEF ((IPVERSION << 4) | RTE_IPV4_MIN_IHL) + +/** + * @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 rte_ipv4_hdr *ipv4_hdr) +{ + uint16_t cksum; + cksum = rte_raw_cksum(ipv4_hdr, sizeof(struct rte_ipv4_hdr)); + return (cksum == 0xffff) ? cksum : (uint16_t)~cksum; +} + +/** + * 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 rte_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 rte_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 + * or 0 on error + */ +static inline uint16_t +rte_ipv4_udptcp_cksum(const struct rte_ipv4_hdr *ipv4_hdr, const void *l4_hdr) +{ + uint32_t cksum; + uint32_t l3_len, l4_len; + + l3_len = rte_be_to_cpu_16(ipv4_hdr->total_length); + if (l3_len < sizeof(struct rte_ipv4_hdr)) + return 0; + + l4_len = l3_len - sizeof(struct rte_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 rte_ipv6_hdr { + rte_be32_t vtc_flow; /**< IP version, traffic class & flow label. */ + rte_be16_t payload_len; /**< IP packet length - includes header size */ + 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). */ +} __rte_packed; + +/* IPv6 vtc_flow: IPv / TC / flow_label */ +#define RTE_IPV6_HDR_FL_SHIFT 0 +#define RTE_IPV6_HDR_TC_SHIFT 20 +#define RTE_IPV6_HDR_FL_MASK ((1u << RTE_IPV6_HDR_TC_SHIFT) - 1) +#define RTE_IPV6_HDR_TC_MASK (0xff << RTE_IPV6_HDR_TC_SHIFT) +#define RTE_IPV6_HDR_DSCP_MASK (0xfc << RTE_IPV6_HDR_TC_SHIFT) +#define RTE_IPV6_HDR_ECN_MASK (0x03 << RTE_IPV6_HDR_TC_SHIFT) +#define RTE_IPV6_HDR_ECN_CE RTE_IPV6_HDR_ECN_MASK + +#define RTE_IPV6_MIN_MTU 1280 /**< Minimum MTU for IPv6, see RFC 8200. */ + +/** + * 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 rte_ipv6_hdr *ipv6_hdr, uint64_t ol_flags) +{ + uint32_t sum; + struct { + rte_be32_t len; /* L4 length. */ + rte_be32_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 rte_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; +} + +/* IPv6 fragmentation header size */ +#define RTE_IPV6_FRAG_HDR_SIZE 8 + +/** + * Parse next IPv6 header extension + * + * This function checks if proto number is an IPv6 extensions and parses its + * data if so, providing information on next header and extension length. + * + * @param p + * Pointer to an extension raw data. + * @param proto + * Protocol number extracted from the "next header" field from + * the IPv6 header or the previous extension. + * @param ext_len + * Extension data length. + * @return + * next protocol number if proto is an IPv6 extension, -EINVAL otherwise + */ +__rte_experimental +static inline int +rte_ipv6_get_next_ext(const uint8_t *p, int proto, size_t *ext_len) +{ + int next_proto; + + switch (proto) { + case IPPROTO_AH: + next_proto = *p++; + *ext_len = (*p + 2) * sizeof(uint32_t); + break; + + case IPPROTO_HOPOPTS: + case IPPROTO_ROUTING: + case IPPROTO_DSTOPTS: + next_proto = *p++; + *ext_len = (*p + 1) * sizeof(uint64_t); + break; + + case IPPROTO_FRAGMENT: + next_proto = *p; + *ext_len = RTE_IPV6_FRAG_HDR_SIZE; + break; + + default: + return -EINVAL; + } + + return next_proto; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_IP_H_ */ diff --git a/src/spdk/dpdk/lib/librte_net/rte_mpls.h b/src/spdk/dpdk/lib/librte_net/rte_mpls.h new file mode 100644 index 000000000..db91707e6 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_mpls.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2016 6WIND S.A. + */ + +#ifndef _RTE_MPLS_H_ +#define _RTE_MPLS_H_ + +/** + * @file + * + * MPLS-related defines + */ + +#include <stdint.h> +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * MPLS header. + */ +struct rte_mpls_hdr { + uint16_t tag_msb; /**< Label(msb). */ +#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN + uint8_t tag_lsb:4; /**< Label(lsb). */ + uint8_t tc:3; /**< Traffic class. */ + uint8_t bs:1; /**< Bottom of stack. */ +#else + uint8_t bs:1; /**< Bottom of stack. */ + uint8_t tc:3; /**< Traffic class. */ + uint8_t tag_lsb:4; /**< label(lsb) */ +#endif + uint8_t ttl; /**< Time to live. */ +} __rte_packed; + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_MPLS_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 000000000..6f45b1339 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_net.c @@ -0,0 +1,515 @@ +/* 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_mpls.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 rte_gre_hdr *gh; + struct rte_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(RTE_ETHER_TYPE_TEB)) + return RTE_PTYPE_TUNNEL_NVGRE; + else + return RTE_PTYPE_TUNNEL_GRE; + } + case IPPROTO_IPIP: + *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); + return RTE_PTYPE_TUNNEL_IP; + case IPPROTO_IPV6: + *proto = rte_cpu_to_be_16(RTE_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 rte_ipv4_hdr *hdr) +{ + return (hdr->version_ihl & 0xf) * 4; +} + +/* parse ipv6 extended headers, update offset and return next proto */ +int +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 rte_ether_hdr *eh; + struct rte_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(RTE_ETHER_TYPE_IPV4)) + goto l3; /* fast path if packet is IPv4 */ + + if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) { + const struct rte_vlan_hdr *vh; + struct rte_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(RTE_ETHER_TYPE_QINQ)) { + const struct rte_vlan_hdr *vh; + struct rte_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; + } else if ((proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLS)) || + (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_MPLSM))) { + unsigned int i; + const struct rte_mpls_hdr *mh; + struct rte_mpls_hdr mh_copy; + +#define MAX_MPLS_HDR 5 + for (i = 0; i < MAX_MPLS_HDR; i++) { + mh = rte_pktmbuf_read(m, off + (i * sizeof(*mh)), + sizeof(*mh), &mh_copy); + if (unlikely(mh == NULL)) + return pkt_type; + } + if (i == MAX_MPLS_HDR) + return pkt_type; + pkt_type = RTE_PTYPE_L2_ETHER_MPLS; + hdr_lens->l2_len += (sizeof(*mh) * i); + return pkt_type; + } + +l3: + if ((layers & RTE_PTYPE_L3_MASK) == 0) + return pkt_type; + + if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { + const struct rte_ipv4_hdr *ip4h; + struct rte_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( + RTE_IPV4_HDR_OFFSET_MASK | RTE_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(RTE_ETHER_TYPE_IPV6)) { + const struct rte_ipv6_hdr *ip6h; + struct rte_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 rte_udp_hdr); + return pkt_type; + } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) { + const struct rte_tcp_hdr *th; + struct rte_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 rte_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(RTE_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(RTE_ETHER_TYPE_VLAN)) { + const struct rte_vlan_hdr *vh; + struct rte_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(RTE_ETHER_TYPE_QINQ)) { + const struct rte_vlan_hdr *vh; + struct rte_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(RTE_ETHER_TYPE_IPV4)) { + const struct rte_ipv4_hdr *ip4h; + struct rte_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(RTE_IPV4_HDR_OFFSET_MASK | + RTE_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(RTE_ETHER_TYPE_IPV6)) { + const struct rte_ipv6_hdr *ip6h; + struct rte_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 rte_udp_hdr); + } else if ((pkt_type & RTE_PTYPE_INNER_L4_MASK) == + RTE_PTYPE_INNER_L4_TCP) { + const struct rte_tcp_hdr *th; + struct rte_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 rte_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 000000000..1560ecfa4 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_net.h @@ -0,0 +1,223 @@ +/* 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. + */ +__rte_experimental +int +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) +{ + /* Initialise ipv4_hdr to avoid false positive compiler warnings. */ + struct rte_ipv4_hdr *ipv4_hdr = NULL; + struct rte_ipv6_hdr *ipv6_hdr; + struct rte_tcp_hdr *tcp_hdr; + struct rte_udp_hdr *udp_hdr; + uint64_t inner_l3_offset = m->l2_len; + +#ifdef RTE_LIBRTE_ETHDEV_DEBUG + /* + * Does packet set any of available offloads? + * Mainly it is required to avoid fragmented headers check if + * no offloads are requested. + */ + if (!(ol_flags & PKT_TX_OFFLOAD_MASK)) + return 0; +#endif + + if (ol_flags & (PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IPV6)) + inner_l3_offset += m->outer_l2_len + m->outer_l3_len; + +#ifdef RTE_LIBRTE_ETHDEV_DEBUG + /* + * Check if headers are fragmented. + * The check could be less strict depending on which offloads are + * requested and headers to be used, but let's keep it simple. + */ + if (unlikely(rte_pktmbuf_data_len(m) < + inner_l3_offset + m->l3_len + m->l4_len)) + return -ENOTSUP; +#endif + + if (ol_flags & PKT_TX_IPV4) { + ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, + inner_l3_offset); + + if (ol_flags & PKT_TX_IP_CKSUM) + ipv4_hdr->hdr_checksum = 0; + } + + if ((ol_flags & PKT_TX_L4_MASK) == PKT_TX_UDP_CKSUM) { + if (ol_flags & PKT_TX_IPV4) { + udp_hdr = (struct rte_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 rte_ipv6_hdr *, inner_l3_offset); + /* non-TSO udp */ + udp_hdr = rte_pktmbuf_mtod_offset(m, + struct rte_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_L4_MASK) == PKT_TX_TCP_CKSUM || + (ol_flags & PKT_TX_TCP_SEG)) { + if (ol_flags & PKT_TX_IPV4) { + /* non-TSO tcp or TSO */ + tcp_hdr = (struct rte_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 rte_ipv6_hdr *, inner_l3_offset); + /* non-TSO tcp or TSO */ + tcp_hdr = rte_pktmbuf_mtod_offset(m, + struct rte_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 000000000..9fd4794a9 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_net_crc.c @@ -0,0 +1,202 @@ +/* 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 polynomials */ +#define CRC32_ETH_POLYNOMIAL 0x04c11db7UL +#define CRC16_CCITT_POLYNOMIAL 0x1021U + +#define CRC_LUT_SIZE 256 + +/* 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 & (1U << i)) != 0) + res |= (uint32_t)(1U << (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 000000000..16e85ca97 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_net_crc.h @@ -0,0 +1,65 @@ +/* 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 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 000000000..8a4e75a3a --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_net_version.map @@ -0,0 +1,19 @@ +DPDK_20.0 { + global: + + rte_eth_random_addr; + rte_ether_format_addr; + rte_net_crc_calc; + rte_net_crc_set_alg; + rte_net_get_ptype; + + local: *; +}; + +EXPERIMENTAL { + global: + + rte_net_make_rarp_packet; + rte_net_skip_ip6_ext; + rte_ether_unformat_addr; +}; 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 000000000..965682dc2 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_sctp.h @@ -0,0 +1,39 @@ +/* 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> + +#include <rte_byteorder.h> + +/** + * SCTP Header + */ +struct rte_sctp_hdr { + rte_be16_t src_port; /**< Source port. */ + rte_be16_t dst_port; /**< Destin port. */ + rte_be32_t tag; /**< Validation tag. */ + rte_be32_t cksum; /**< Checksum. */ +} __rte_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 000000000..506ac4e8c --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_tcp.h @@ -0,0 +1,56 @@ +/* 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> + +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * TCP Header + */ +struct rte_tcp_hdr { + rte_be16_t src_port; /**< TCP source port. */ + rte_be16_t dst_port; /**< TCP destination port. */ + rte_be32_t sent_seq; /**< TX data sequence number. */ + rte_be32_t recv_ack; /**< RX data acknowledgment sequence number. */ + uint8_t data_off; /**< Data offset. */ + uint8_t tcp_flags; /**< TCP flags */ + rte_be16_t rx_win; /**< RX flow control window. */ + rte_be16_t cksum; /**< TCP checksum. */ + rte_be16_t tcp_urp; /**< TCP urgent pointer, if any. */ +} __rte_packed; + +/** + * TCP Flags + */ +#define RTE_TCP_CWR_FLAG 0x80 /**< Congestion Window Reduced */ +#define RTE_TCP_ECE_FLAG 0x40 /**< ECN-Echo */ +#define RTE_TCP_URG_FLAG 0x20 /**< Urgent Pointer field significant */ +#define RTE_TCP_ACK_FLAG 0x10 /**< Acknowledgment field significant */ +#define RTE_TCP_PSH_FLAG 0x08 /**< Push Function */ +#define RTE_TCP_RST_FLAG 0x04 /**< Reset the connection */ +#define RTE_TCP_SYN_FLAG 0x02 /**< Synchronize sequence numbers */ +#define RTE_TCP_FIN_FLAG 0x01 /**< No more data from sender */ + +#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 000000000..6135494c4 --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_udp.h @@ -0,0 +1,39 @@ +/* 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> + +#include <rte_byteorder.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * UDP Header + */ +struct rte_udp_hdr { + rte_be16_t src_port; /**< UDP source port. */ + rte_be16_t dst_port; /**< UDP destination port. */ + rte_be16_t dgram_len; /**< UDP datagram length */ + rte_be16_t dgram_cksum; /**< UDP datagram checksum */ +} __rte_packed; + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_UDP_H_ */ diff --git a/src/spdk/dpdk/lib/librte_net/rte_vxlan.h b/src/spdk/dpdk/lib/librte_net/rte_vxlan.h new file mode 100644 index 000000000..c23c10c9e --- /dev/null +++ b/src/spdk/dpdk/lib/librte_net/rte_vxlan.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018-2019 Intel Corporation + */ + +#ifndef _RTE_VXLAN_H_ +#define _RTE_VXLAN_H_ + +/** + * @file + * + * VXLAN-related definitions + */ + +#include <stdint.h> + +#include <rte_udp.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +/** VXLAN default port. */ +#define RTE_VXLAN_DEFAULT_PORT 4789 + +/** + * VXLAN protocol header. + * Contains the 8-bit flag, 24-bit VXLAN Network Identifier and + * Reserved fields (24 bits and 8 bits) + */ +struct rte_vxlan_hdr { + uint32_t vx_flags; /**< flag (8) + Reserved (24). */ + uint32_t vx_vni; /**< VNI (24) + Reserved (8). */ +} __rte_packed; + +/** VXLAN tunnel header length. */ +#define RTE_ETHER_VXLAN_HLEN \ + (sizeof(struct rte_udp_hdr) + sizeof(struct rte_vxlan_hdr)) + + +/** + * 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 rte_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). */ +} __rte_packed; + +/** VXLAN-GPE tunnel header length. */ +#define RTE_ETHER_VXLAN_GPE_HLEN (sizeof(struct rte_udp_hdr) + \ + sizeof(struct rte_vxlan_gpe_hdr)) + +/* VXLAN-GPE next protocol types */ +#define RTE_VXLAN_GPE_TYPE_IPV4 1 /**< IPv4 Protocol. */ +#define RTE_VXLAN_GPE_TYPE_IPV6 2 /**< IPv6 Protocol. */ +#define RTE_VXLAN_GPE_TYPE_ETH 3 /**< Ethernet Protocol. */ +#define RTE_VXLAN_GPE_TYPE_NSH 4 /**< NSH Protocol. */ +#define RTE_VXLAN_GPE_TYPE_MPLS 5 /**< MPLS Protocol. */ +#define RTE_VXLAN_GPE_TYPE_GBP 6 /**< GBP Protocol. */ +#define RTE_VXLAN_GPE_TYPE_VBNG 7 /**< vBNG Protocol. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_VXLAN_H_ */ |