diff --git a/Makefile.am b/Makefile.am index 859f7eb5a..2ab1909eb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -180,6 +180,7 @@ ipfixprobe_input_src+=\ input/dpdk/dpdkMbuf.cpp \ input/dpdk/dpdkDevice.hpp \ input/dpdk/dpdkDevice.cpp \ + input/dpdk/dpdkCompat.hpp \ input/dpdk.cpp \ input/dpdk.h \ input/dpdk-ring.cpp \ diff --git a/input/dpdk/dpdkCompat.hpp b/input/dpdk/dpdkCompat.hpp new file mode 100644 index 000000000..c3ea14163 --- /dev/null +++ b/input/dpdk/dpdkCompat.hpp @@ -0,0 +1,95 @@ +/** + * \file + * \brief Compatible definitions for DPDK versions. + * \author Pavel Siska + * \date 2024 + */ +/* + * Copyright (C) 2024 CESNET + * + * LICENSE TERMS + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of the Company nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + */ + +#include +#include + +#if RTE_VERSION < RTE_VERSION_NUM(22, 0, 0, 0) +#define RTE_ETH_MQ_RX_RSS ETH_MQ_RX_RSS +#endif + +#if RTE_VERSION < RTE_VERSION_NUM(21, 11, 0, 0) +#define RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE DEV_TX_OFFLOAD_MBUF_FAST_FREE + +#define RTE_ETH_RX_OFFLOAD_CHECKSUM DEV_RX_OFFLOAD_CHECKSUM + +#define RTE_ETH_RX_OFFLOAD_VLAN_STRIP DEV_RX_OFFLOAD_VLAN_STRIP +#define RTE_ETH_RX_OFFLOAD_IPV4_CKSUM DEV_RX_OFFLOAD_IPV4_CKSUM +#define RTE_ETH_RX_OFFLOAD_UDP_CKSUM DEV_RX_OFFLOAD_UDP_CKSUM +#define RTE_ETH_RX_OFFLOAD_TCP_CKSUM DEV_RX_OFFLOAD_TCP_CKSUM +#define RTE_ETH_RX_OFFLOAD_TCP_LRO DEV_RX_OFFLOAD_TCP_LRO +#define RTE_ETH_RX_OFFLOAD_QINQ_STRIP DEV_RX_OFFLOAD_QINQ_STRIP +#define RTE_ETH_RX_OFFLOAD_OUTER_IPV4_CKSUM DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM +#define RTE_ETH_RX_OFFLOAD_MACSEC_STRIP DEV_RX_OFFLOAD_MACSEC_STRIP +#define RTE_ETH_RX_OFFLOAD_HEADER_SPLIT DEV_RX_OFFLOAD_HEADER_SPLIT +#define RTE_ETH_RX_OFFLOAD_VLAN_FILTER DEV_RX_OFFLOAD_VLAN_FILTER +#define RTE_ETH_RX_OFFLOAD_VLAN_EXTEND DEV_RX_OFFLOAD_VLAN_EXTEND +#define RTE_ETH_RX_OFFLOAD_SCATTER DEV_RX_OFFLOAD_SCATTER +#define RTE_ETH_RX_OFFLOAD_TIMESTAMP DEV_RX_OFFLOAD_TIMESTAMP +#define RTE_ETH_RX_OFFLOAD_SECURITY DEV_RX_OFFLOAD_SECURITY +#define RTE_ETH_RX_OFFLOAD_KEEP_CRC DEV_RX_OFFLOAD_KEEP_CRC +#define RTE_ETH_RX_OFFLOAD_SCTP_CKSUM DEV_RX_OFFLOAD_SCTP_CKSUM +#define RTE_ETH_RX_OFFLOAD_OUTER_UDP_CKSUM DEV_RX_OFFLOAD_OUTER_UDP_CKSUM +#define RTE_ETH_RX_OFFLOAD_RSS_HASH DEV_RX_OFFLOAD_RSS_HASH + +#define RTE_ETH_MQ_TX_NONE ETH_MQ_TX_NONE + +#define RTE_ETH_MQ_RX_NONE ETH_MQ_RX_NONE + +#define RTE_ETH_RSS_IP ETH_RSS_IP +#define RTE_ETH_RSS_UDP ETH_RSS_UDP +#define RTE_ETH_RSS_TCP ETH_RSS_TCP +#define RTE_ETH_RSS_SCTP ETH_RSS_SCTP +#define RTE_ETH_RSS_TUNNEL ETH_RSS_TUNNEL + +#define RTE_ETH_RSS_L3_SRC_ONLY ETH_RSS_L3_SRC_ONLY +#define RTE_ETH_RSS_L3_DST_ONLY ETH_RSS_L3_DST_ONLY +#define RTE_ETH_RSS_L4_SRC_ONLY ETH_RSS_L4_SRC_ONLY +#define RTE_ETH_RSS_L4_DST_ONLY ETH_RSS_L4_DST_ONLY + +#define RTE_ETH_RSS_IPV4 ETH_RSS_IPV4 +#define RTE_ETH_RSS_FRAG_IPV4 ETH_RSS_FRAG_IPV4 +#define RTE_ETH_RSS_NONFRAG_IPV4_TCP ETH_RSS_NONFRAG_IPV4_TCP +#define RTE_ETH_RSS_NONFRAG_IPV4_UDP ETH_RSS_NONFRAG_IPV4_UDP +#define RTE_ETH_RSS_NONFRAG_IPV4_SCTP ETH_RSS_NONFRAG_IPV4_SCTP +#define RTE_ETH_RSS_NONFRAG_IPV4_OTHER ETH_RSS_NONFRAG_IPV4_OTHER +#define RTE_ETH_RSS_IPV6 ETH_RSS_IPV6 +#define RTE_ETH_RSS_FRAG_IPV6 ETH_RSS_FRAG_IPV6 +#define RTE_ETH_RSS_NONFRAG_IPV6_TCP ETH_RSS_NONFRAG_IPV6_TCP +#define RTE_ETH_RSS_NONFRAG_IPV6_UDP ETH_RSS_NONFRAG_IPV6_UDP +#define RTE_ETH_RSS_NONFRAG_IPV6_SCTP ETH_RSS_NONFRAG_IPV6_SCTP +#define RTE_ETH_RSS_NONFRAG_IPV6_OTHER ETH_RSS_NONFRAG_IPV6_OTHER +#define RTE_ETH_RSS_L2_PAYLOAD ETH_RSS_L2_PAYLOAD +#define RTE_ETH_RSS_IPV6_EX ETH_RSS_IPV6_EX +#define RTE_ETH_RSS_IPV6_TCP_EX ETH_RSS_IPV6_TCP_EX +#define RTE_ETH_RSS_IPV6_UDP_EX ETH_RSS_IPV6_UDP_EX +#define RTE_ETH_RSS_PORT ETH_RSS_PORT +#define RTE_ETH_RSS_VXLAN ETH_RSS_VXLAN +#define RTE_ETH_RSS_NVGRE ETH_RSS_NVGRE +#define RTE_ETH_RSS_GTPU ETH_RSS_GTPU + +#define RTE_BIT64(nr) (UINT64_C(1) << (nr)) + +#endif \ No newline at end of file diff --git a/input/dpdk/dpdkDevice.cpp b/input/dpdk/dpdkDevice.cpp index 117ddf3fe..cf3a6df5b 100644 --- a/input/dpdk/dpdkDevice.cpp +++ b/input/dpdk/dpdkDevice.cpp @@ -148,11 +148,7 @@ rte_eth_conf DpdkDevice::createPortConfig() #endif if (m_supportedRSS) { -#if RTE_VERSION >= RTE_VERSION_NUM(21, 11, 0, 0) portConfig.rxmode.mq_mode = RTE_ETH_MQ_RX_RSS; -#else - portConfig.rxmode.mq_mode = ETH_MQ_RX_RSS; -#endif } else { portConfig.rxmode.mq_mode = RTE_ETH_MQ_RX_NONE; } @@ -219,25 +215,36 @@ void DpdkDevice::configureRSS() return; } - constexpr size_t RSS_KEY_LEN = 40; - // biflow hash key - static uint8_t rssKey[RSS_KEY_LEN] - = {0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, - 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A}; + rte_eth_dev_info rteDevInfo; + if (rte_eth_dev_info_get(m_portID, &rteDevInfo)) { + throw PluginError("DpdkDevice::configureRSS() has failed. Unable to get rte dev info"); + } - struct rte_eth_rss_conf rssConfig - = {.rss_key = rssKey, - .rss_key_len = RSS_KEY_LEN, -#if RTE_VERSION >= RTE_VERSION_NUM(21, 11, 0, 0) - .rss_hf = RTE_ETH_RSS_IP, -#else - .rss_hf = ETH_RSS_IP, -#endif - }; + const uint8_t rssHashKeySize = rteDevInfo.hash_key_size; + + m_hashKey.resize(rssHashKeySize); + std::generate( + m_hashKey.begin(), + m_hashKey.end(), + [idx = static_cast(0)]() mutable { + static const std::array hashKey = {0x6D, 0x5A}; + return hashKey[idx++ % sizeof(hashKey)]; + }); + + const uint64_t rssOffloads = rteDevInfo.flow_type_rss_offloads & RTE_ETH_RSS_IP; + if (rssOffloads != RTE_ETH_RSS_IP) { + std::cerr << "RTE_ETH_RSS_IP is not supported by the card. Used subset: " << rssOffloads << std::endl; + } + + struct rte_eth_rss_conf rssConfig = {}; + rssConfig.rss_key = m_hashKey.data(); + rssConfig.rss_key_len = rssHashKeySize; + rssConfig.rss_hf = rssOffloads; - if (rte_eth_dev_rss_hash_update(m_portID, &rssConfig)) { - std::cerr << "Setting RSS hash for port " << m_portID << "." << std::endl; + int ret = rte_eth_dev_rss_hash_update(m_portID, &rssConfig); + if (ret < 0) { + std::cerr << "Setting RSS {" << rssOffloads << "} for port " << m_portID << " failed. Errno:" << ret << std::endl; + throw PluginError("DpdkDevice::configureRSS() has failed."); } } diff --git a/input/dpdk/dpdkDevice.hpp b/input/dpdk/dpdkDevice.hpp index e8b895cf6..ef7d90ff0 100644 --- a/input/dpdk/dpdkDevice.hpp +++ b/input/dpdk/dpdkDevice.hpp @@ -26,6 +26,7 @@ #pragma once #include "dpdkMbuf.hpp" +#include "dpdkCompat.hpp" #include #include @@ -84,7 +85,8 @@ class DpdkDevice { void registerRxTimestamp(); std::vector m_memPools; - uint16_t m_portID; + std::vector m_hashKey; + uint16_t m_portID; uint16_t m_rxQueueCount; uint16_t m_txQueueCount; uint16_t m_mBufsCount;