mirror of https://github.com/OISF/suricata
dpdk/rss: move and change rss rte_flow functions
Move and adjust the base of RSS configuration from util-dpdk-i40e.c to a new file that can be later utilized by other cards. RSS configuration can be configured via rte_flow rules. This is useful for possible future features such as specific header offload (vxlan, nvgre) also implemented via rte_flow rules, as rte_flow rules can be chained via groups and priorities. i40e uses multiple different rte_flow rules to setup RSS. At first, function DeviceSetRSSFlowQueues() is used to setup rx queues. This rule matches all types of traffic, so the equivalent to dpdk-testpmd pattern would be "pattern end" This rule can not contain hash types (ipv4, ipv6 etc.) nor hash key. The hash function used here is 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 is as follows: "flow create 0 ingress pattern end actions rss queues 0 1 2 3 end func default / end" The other rules configured by i40eDeviceSetRSSFlowIPv4() and i40eDeviceSetRSSFlowIPv6() match specific type of traffic by l4 protocol (none, TCP, UDP, SCTP). For example, pattern to match l3 ipv4 with l4 tcp traffic in dpdk-testpmd syntax would be equivalent of "pattern eth / ipv4 / tcp / end". These rules can not have rx queues configured, but have hash types (l3 src and dst address). This means that the traffic distribution is affected only by l3 addresses, independent of the l4 specifics. Also these pattern matching rules have symmetric 6d5a hash key configured. The length of the key is dependent on DPDK version. The hash function (either RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ or RTE_ETH_HASH_FUNCTION_TOEPLITZ, depending on DPKD version) used in these rules hashes symmetricaly due to the symmetric hash key. The syntax in dpdk-testpmd for rule to match ipv4-tcp traffic with attributes: port index == 0 <hash_key> == 52 bytes long 6d5a symmetric hash key is as follows: "flow create 0 ingress pattern eth / ipv4 / tcp / end actions rss types ipv4-tcp l3-src-only l3-dst-only end queues end key <hash_key> key_len 52 func toeplitz / end" (queues need to be set to NULL) Ticket: 7337pull/12553/head
parent
e47f4f997d
commit
ffe0cf88e4
@ -0,0 +1,169 @@
|
||||
/* Copyright (C) 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
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup dpdk DPDK rte_flow RSS helpers functions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Adam Kiripolsky <adam.kiripolsky@cesnet.cz>
|
||||
*
|
||||
* DPDK rte_flow RSS helper functions
|
||||
*
|
||||
*/
|
||||
|
||||
#include "util-dpdk-rss.h"
|
||||
#include "util-dpdk.h"
|
||||
#include "util-debug.h"
|
||||
|
||||
#ifdef HAVE_DPDK
|
||||
|
||||
uint8_t RSS_HKEY[] = {
|
||||
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, // 40
|
||||
0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, // 52
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Initialize RSS action configuration for
|
||||
* RTE_FLOW RSS rule based on input arguments
|
||||
*
|
||||
* \param rss_conf RSS configuration
|
||||
* \param nb_rx_queues number of rx queues
|
||||
* \param queues array of queue indexes
|
||||
* \param func RSS hash function
|
||||
* \param set_key flag to set RSS hash key and its length
|
||||
* \return struct rte_flow_action_rss RSS action configuration
|
||||
* to be used in a 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)
|
||||
{
|
||||
struct rte_flow_action_rss rss_action_conf = { 0 };
|
||||
rss_action_conf.func = func;
|
||||
rss_action_conf.level = 0;
|
||||
|
||||
if (set_key) {
|
||||
rss_action_conf.key = rss_conf.rss_key;
|
||||
rss_action_conf.key_len = rss_conf.rss_key_len;
|
||||
} else {
|
||||
rss_action_conf.key = NULL;
|
||||
rss_action_conf.key_len = 0;
|
||||
}
|
||||
|
||||
if (nb_rx_queues != 0) {
|
||||
for (int i = 0; i < nb_rx_queues; ++i)
|
||||
queues[i] = i;
|
||||
|
||||
rss_action_conf.queue = queues;
|
||||
} else {
|
||||
rss_action_conf.queue = NULL;
|
||||
}
|
||||
rss_action_conf.queue_num = nb_rx_queues;
|
||||
|
||||
return rss_action_conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* \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
|
||||
* for some drivers (mostly Intel NICs). This function's call must be preceded by
|
||||
* call to function DeviceSetRSSFlowQueues().
|
||||
*
|
||||
* \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
|
||||
* \param rss_type RSS hash type - only this type is used when creating hash with RSS hash function
|
||||
* \param pattern pattern to match incoming traffic
|
||||
* \return int 0 on success, a negative errno value otherwise
|
||||
*/
|
||||
int DPDKCreateRSSFlow(int port_id, const char *port_name, struct rte_flow_action_rss rss_conf,
|
||||
uint64_t rss_type, struct rte_flow_item *pattern)
|
||||
{
|
||||
struct rte_flow_attr attr = { 0 };
|
||||
struct rte_flow_action action[] = { { 0 }, { 0 } };
|
||||
struct rte_flow_error flow_error = { 0 };
|
||||
|
||||
rss_conf.types = rss_type;
|
||||
|
||||
attr.ingress = 1;
|
||||
action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
|
||||
action[0].conf = &rss_conf;
|
||||
action[1].type = RTE_FLOW_ACTION_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 Some drivers (mostly Intel NICs) require specific way of setting RTE_FLOW RSS rules
|
||||
* with one rule that sets up only queues and other rules that specify patterns to match with
|
||||
* queues configured (created with function DeviceCreateRSSFlow() that should follow after
|
||||
* this function's call).
|
||||
*
|
||||
* \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 DPDKSetRSSFlowQueues(int port_id, const char *port_name, struct rte_flow_action_rss rss_conf)
|
||||
{
|
||||
struct rte_flow_attr attr = { 0 };
|
||||
struct rte_flow_item pattern[] = { { 0 } };
|
||||
struct rte_flow_action action[] = { { 0 }, { 0 } };
|
||||
struct rte_flow_error flow_error = { 0 };
|
||||
|
||||
rss_conf.types = 0; // queues region can not be configured with types
|
||||
|
||||
attr.ingress = 1;
|
||||
pattern[0].type = RTE_FLOW_ITEM_TYPE_END;
|
||||
action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
|
||||
action[0].conf = &rss_conf;
|
||||
action[1].type = RTE_FLOW_ACTION_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;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DPDK */
|
||||
/**
|
||||
* @}
|
||||
*/
|
@ -0,0 +1,47 @@
|
||||
/* Copyright (C) 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
|
||||
* Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* version 2 along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Adam Kiripolsky <adam.kiripolsky@cesnet.cz>
|
||||
*/
|
||||
|
||||
#ifndef UTIL_DPDK_RSS
|
||||
#define UTIL_DPDK_RSS
|
||||
|
||||
#include "suricata-common.h"
|
||||
|
||||
#ifdef HAVE_DPDK
|
||||
|
||||
#include "util-dpdk.h"
|
||||
|
||||
#define RSS_HKEY_LEN 40
|
||||
|
||||
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 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,
|
||||
uint64_t rss_type, struct rte_flow_item *pattern);
|
||||
|
||||
#endif /* HAVE_DPDK */
|
||||
|
||||
#endif /* UTIL_DPDK_RSS */
|
Loading…
Reference in New Issue