driver_name = BondingDeviceDriverGet(ptv->port_id);
if (strcmp(driver_name, "net_i40e") == 0)
i40eDeviceSetRSS(ptv->port_id, ptv->threads, ptv->livedev->dev);
-
+ else if (strcmp(driver_name, "net_ixgbe") == 0)
+ ixgbeDeviceSetRSS(ptv->port_id, ptv->threads, ptv->livedev->dev);
}
static void DevicePreClosePMDSpecificActions(DPDKThreadVars *ptv, const char *driver_name)
driver_name = BondingDeviceDriverGet(ptv->port_id);
}
- if (strcmp(driver_name, "net_i40e") == 0) {
-#if RTE_VERSION >= RTE_VERSION_NUM(20, 0, 0, 0)
+ if (
+#if RTE_VERSION > RTE_VERSION_NUM(20, 0, 0, 0)
+ strcmp(driver_name, "net_i40e") == 0 ||
+#endif /* RTE_VERSION > RTE_VERSION_NUM(20, 0, 0, 0) */
+ strcmp(driver_name, "net_ixgbe") == 0) {
// Flush the RSS rules that have been inserted in the post start section
struct rte_flow_error flush_error = { 0 };
int32_t retval = rte_flow_flush(ptv->port_id, &flush_error);
SCLogError("%s: unable to flush rte_flow rules: %s Flush error msg: %s",
ptv->livedev->dev, rte_strerror(-retval), flush_error.message);
}
-#endif /* RTE_VERSION >= RTE_VERSION_NUM(20, 0, 0, 0) */
}
}
-/* Copyright (C) 2021 Open Information Security Foundation
+/* Copyright (C) 2021-2025 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
#include "util-dpdk-ixgbe.h"
#include "util-dpdk.h"
+#include "util-debug.h"
+#include "util-dpdk-bonding.h"
+#include "util-dpdk-rss.h"
#ifdef HAVE_DPDK
+#define IXGBE_RSS_HKEY_LEN 40
+
void ixgbeDeviceSetRSSHashFunction(uint64_t *rss_hf)
{
*rss_hf = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_IPV6_EX;
}
+int ixgbeDeviceSetRSS(int port_id, int nb_rx_queues, char *port_name)
+{
+ uint16_t queues[RTE_MAX_QUEUES_PER_PORT];
+ struct rte_flow_error flush_error = { 0 };
+ struct rte_eth_rss_conf rss_conf = {
+ .rss_key = RSS_HKEY,
+ .rss_key_len = IXGBE_RSS_HKEY_LEN,
+ };
+
+ if (nb_rx_queues < 1) {
+ FatalError("The number of queues for RSS configuration must be "
+ "configured with a positive number");
+ }
+
+ struct rte_flow_action_rss rss_action_conf =
+ DPDKInitRSSAction(rss_conf, nb_rx_queues, queues, RTE_ETH_HASH_FUNCTION_DEFAULT, true);
+
+ int retval = DPDKCreateRSSFlowGeneric(port_id, port_name, rss_action_conf);
+ if (retval != 0) {
+ retval = rte_flow_flush(port_id, &flush_error);
+ if (retval != 0) {
+ SCLogError("%s: unable to flush rte_flow rules: %s Flush error msg: %s", port_name,
+ rte_strerror(-retval), flush_error.message);
+ }
+ return retval;
+ }
+
+ return 0;
+}
+
#endif /* HAVE_DPDK */
/**
* @}
-/* Copyright (C) 2021 Open Information Security Foundation
+/* Copyright (C) 2021-2025 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
#ifdef HAVE_DPDK
+int ixgbeDeviceSetRSS(int port_id, int nb_rx_queues, char *port_name);
void ixgbeDeviceSetRSSHashFunction(uint64_t *rss_conf);
#endif /* HAVE_DPDK */
return rss_action_conf;
}
+/**
+ * \brief Creates RTE_FLOW RSS rule used by NIC drivers
+ * to redistribute packets to different queues based
+ * on IP adresses.
+ *
+ * \param port_id The port identifier of the Ethernet device
+ * \param port_name The port name of the Ethernet device
+ * \param rss_conf RSS configuration
+ * \return int 0 on success, a negative errno value otherwise
+ */
+int DPDKCreateRSSFlowGeneric(
+ int port_id, const char *port_name, struct rte_flow_action_rss rss_conf)
+{
+ struct rte_flow_attr attr = { 0 };
+ struct rte_flow_action action[] = { { 0 }, { 0 } };
+ struct rte_flow_error flow_error = { 0 };
+ struct rte_flow_item pattern[] = { { 0 }, { 0 } };
+
+ rss_conf.types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6;
+
+ attr.ingress = 1;
+ action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
+ action[0].conf = &rss_conf;
+ action[1].type = RTE_FLOW_ACTION_TYPE_END;
+
+ pattern[0].type = RTE_FLOW_ITEM_TYPE_END;
+
+ struct rte_flow *flow = rte_flow_create(port_id, &attr, pattern, action, &flow_error);
+ if (flow == NULL) {
+ SCLogError("%s: rte_flow rule creation error: %s", port_name, flow_error.message);
+ int ret = rte_flow_validate(port_id, &attr, pattern, action, &flow_error);
+ SCLogError("%s: rte_flow rule validation error: %s, errmsg: %s", port_name,
+ rte_strerror(-ret), flow_error.message);
+ return ret;
+ } else {
+ SCLogDebug("%s: rte_flow rule created", port_name);
+ }
+
+ return 0;
+}
+
/**
* \brief Create RTE_FLOW RSS rule configured with pattern and rss_type
* but with no rx_queues configured. This is specific way of setting RTE_FLOW RSS rule
struct rte_flow_action_rss DPDKInitRSSAction(struct rte_eth_rss_conf rss_conf, int nb_rx_queues,
uint16_t *queues, enum rte_eth_hash_function func, bool set_key);
-int DeviceCreateRSSFlowGeneric(
+int DPDKCreateRSSFlowGeneric(
int port_id, const char *port_name, struct rte_flow_action_rss rss_conf);
int DPDKSetRSSFlowQueues(int port_id, const char *port_name, struct rte_flow_action_rss rss_conf);
int DPDKCreateRSSFlow(int port_id, const char *port_name, struct rte_flow_action_rss rss_conf,