dpdk/rss: add rte_flow rss support for ixgbe

ixgbe driver requires different configuration of RSS rte_flow
rule than i40e, with just one generic rule matching all traffic.

The generic rule configured by DeviceCreateRSSFlowGeneric() has pattern
equivalent to "pattern eth / end" in dpdk-testpmd syntax. The rule must
have rx queues configured. The rule hashes traffic to different queues
based on ipv4 and ipv6 hash types (ipv4 src dst / ipv6 src dst).
The hash key is 40 bytes long  symmetric hash key. ixgbe does not
support any other hash function than RTE_ETH_HASH_FUNCTION_DEFAULT.

The syntax in dpdk-testpmd for this rule with attributes:
	port index == 0
	used rx queue indices == 0 1 2 3
	<hash_key> == 6d5a symmetric hash key
is as follows:
"flow create 0 ingress pattern eth / end actions rss types ipv4 ipv6
end queues 0 1 2 3 end key <hash_key> key_len 40 func default / end"

Ticket: 7337
pull/12553/head
Adam Kiripolsky 3 months ago committed by Victor Julien
parent ffe0cf88e4
commit 2296b3ba76

@ -196,7 +196,8 @@ static void DevicePostStartPMDSpecificActions(DPDKThreadVars *ptv, const char *d
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)
@ -205,8 +206,11 @@ static void DevicePreClosePMDSpecificActions(DPDKThreadVars *ptv, const char *dr
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);
@ -214,7 +218,6 @@ static void DevicePreClosePMDSpecificActions(DPDKThreadVars *ptv, const char *dr
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) */
}
}

@ -1,4 +1,4 @@
/* 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
@ -32,14 +32,49 @@
#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 */
/**
* @}

@ -1,4 +1,4 @@
/* 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
@ -28,6 +28,7 @@
#ifdef HAVE_DPDK
int ixgbeDeviceSetRSS(int port_id, int nb_rx_queues, char *port_name);
void ixgbeDeviceSetRSSHashFunction(uint64_t *rss_conf);
#endif /* HAVE_DPDK */

@ -83,6 +83,47 @@ struct rte_flow_action_rss DPDKInitRSSAction(struct rte_eth_rss_conf rss_conf, i
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

@ -36,7 +36,7 @@ extern uint8_t RSS_HKEY[];
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,

Loading…
Cancel
Save