suricata
util-dpdk-rss.c
Go to the documentation of this file.
1/* Copyright (C) 2025 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \defgroup dpdk DPDK rte_flow RSS helpers functions
20 *
21 * @{
22 */
23
24/**
25 * \file
26 *
27 * \author Adam Kiripolsky <adam.kiripolsky@cesnet.cz>
28 *
29 * DPDK rte_flow RSS helper functions
30 *
31 */
32
33#include "util-dpdk-rss.h"
34#include "util-dpdk.h"
35#include "util-debug.h"
36
37#ifdef HAVE_DPDK
38
39uint8_t RSS_HKEY[] = {
40 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
41 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A,
42 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, // 40
43 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, 0x6D, 0x5A, // 52
44};
45
46/**
47 * \brief Initialize RSS action configuration for
48 * RTE_FLOW RSS rule based on input arguments
49 *
50 * \param rss_conf RSS configuration
51 * \param nb_rx_queues number of rx queues
52 * \param queues array of queue indexes
53 * \param func RSS hash function
54 * \param set_key flag to set RSS hash key and its length
55 * \return struct rte_flow_action_rss RSS action configuration
56 * to be used in a rule
57 */
58struct rte_flow_action_rss DPDKInitRSSAction(struct rte_eth_rss_conf rss_conf, int nb_rx_queues,
59 uint16_t *queues, enum rte_eth_hash_function func, bool set_key)
60{
61 struct rte_flow_action_rss rss_action_conf = { 0 };
62 rss_action_conf.func = func;
63 rss_action_conf.level = 0;
64
65 if (set_key) {
66 rss_action_conf.key = rss_conf.rss_key;
67 rss_action_conf.key_len = rss_conf.rss_key_len;
68 } else {
69 rss_action_conf.key = NULL;
70 rss_action_conf.key_len = 0;
71 }
72
73 if (nb_rx_queues != 0) {
74 for (int i = 0; i < nb_rx_queues; ++i)
75 queues[i] = i;
76
77 rss_action_conf.queue = queues;
78 } else {
79 rss_action_conf.queue = NULL;
80 }
81 rss_action_conf.queue_num = nb_rx_queues;
82
83 return rss_action_conf;
84}
85
86/**
87 * \brief Creates RTE_FLOW RSS rule used by NIC drivers
88 * to redistribute packets to different queues based
89 * on IP adresses.
90 *
91 * \param port_id The port identifier of the Ethernet device
92 * \param port_name The port name of the Ethernet device
93 * \param rss_conf RSS configuration
94 * \return int 0 on success, a negative errno value otherwise
95 */
96int DPDKCreateRSSFlowGeneric(
97 int port_id, const char *port_name, struct rte_flow_action_rss rss_conf)
98{
99 struct rte_flow_attr attr = { 0 };
100 struct rte_flow_action action[] = { { 0 }, { 0 } };
101 struct rte_flow_error flow_error = { 0 };
102 struct rte_flow_item pattern[] = { { 0 }, { 0 } };
103
104 rss_conf.types = RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_IPV6;
105
106 attr.ingress = 1;
107 action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
108 action[0].conf = &rss_conf;
109 action[1].type = RTE_FLOW_ACTION_TYPE_END;
110
111 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
112 pattern[1].type = RTE_FLOW_ITEM_TYPE_END;
113
114 struct rte_flow *flow = rte_flow_create(port_id, &attr, pattern, action, &flow_error);
115 if (flow == NULL) {
116 SCLogError("%s: rte_flow rule creation error: %s", port_name, flow_error.message);
117 int ret = rte_flow_validate(port_id, &attr, pattern, action, &flow_error);
118 SCLogError("%s: rte_flow rule validation error: %s, errmsg: %s", port_name,
119 rte_strerror(-ret), flow_error.message);
120 return ret;
121 } else {
122 SCLogDebug("%s: rte_flow rule created", port_name);
123 }
124
125 return 0;
126}
127
128/**
129 * \brief Create RTE_FLOW RSS rule configured with pattern and rss_type
130 * but with no rx_queues configured. This is specific way of setting RTE_FLOW RSS rule
131 * for some drivers (mostly Intel NICs). This function's call must be preceded by
132 * call to function DeviceSetRSSFlowQueues().
133 *
134 * \param port_id The port identifier of the Ethernet device
135 * \param port_name The port name of the Ethernet device
136 * \param rss_conf RSS configuration
137 * \param rss_type RSS hash type - only this type is used when creating hash with RSS hash function
138 * \param pattern pattern to match incoming traffic
139 * \return int 0 on success, a negative errno value otherwise
140 */
141int DPDKCreateRSSFlow(int port_id, const char *port_name, struct rte_flow_action_rss rss_conf,
142 uint64_t rss_type, struct rte_flow_item *pattern)
143{
144 struct rte_flow_attr attr = { 0 };
145 struct rte_flow_action action[] = { { 0 }, { 0 } };
146 struct rte_flow_error flow_error = { 0 };
147
148 rss_conf.types = rss_type;
149
150 attr.ingress = 1;
151 action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
152 action[0].conf = &rss_conf;
153 action[1].type = RTE_FLOW_ACTION_TYPE_END;
154
155 struct rte_flow *flow = rte_flow_create(port_id, &attr, pattern, action, &flow_error);
156 if (flow == NULL) {
157 SCLogError("%s: rte_flow rule creation error: %s", port_name, flow_error.message);
158 int ret = rte_flow_validate(port_id, &attr, pattern, action, &flow_error);
159 SCLogError("%s: rte_flow rule validation error: %s, errmsg: %s", port_name,
160 rte_strerror(-ret), flow_error.message);
161 return ret;
162 } else {
163 SCLogDebug("%s: rte_flow rule created", port_name);
164 }
165
166 return 0;
167}
168
169/**
170 * \brief Some drivers (mostly Intel NICs) require specific way of setting RTE_FLOW RSS rules
171 * with one rule that sets up only queues and other rules that specify patterns to match with
172 * queues configured (created with function DeviceCreateRSSFlow() that should follow after
173 * this function's call).
174 *
175 * \param port_id The port identifier of the Ethernet device
176 * \param port_name The port name of the Ethernet device
177 * \param rss_conf RSS configuration
178 * \return int 0 on success, a negative errno value otherwise
179 */
180int DPDKSetRSSFlowQueues(int port_id, const char *port_name, struct rte_flow_action_rss rss_conf)
181{
182 struct rte_flow_attr attr = { 0 };
183 struct rte_flow_item pattern[] = { { 0 } };
184 struct rte_flow_action action[] = { { 0 }, { 0 } };
185 struct rte_flow_error flow_error = { 0 };
186
187 rss_conf.types = 0; // queues region can not be configured with types
188
189 attr.ingress = 1;
190 pattern[0].type = RTE_FLOW_ITEM_TYPE_END;
191 action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
192 action[0].conf = &rss_conf;
193 action[1].type = RTE_FLOW_ACTION_TYPE_END;
194
195 struct rte_flow *flow = rte_flow_create(port_id, &attr, pattern, action, &flow_error);
196 if (flow == NULL) {
197 SCLogError("%s: rte_flow rule creation error: %s", port_name, flow_error.message);
198 int ret = rte_flow_validate(port_id, &attr, pattern, action, &flow_error);
199 SCLogError("%s: rte_flow rule validation error: %s, errmsg: %s", port_name,
200 rte_strerror(-ret), flow_error.message);
201 return ret;
202 } else {
203 SCLogDebug("%s: rte_flow rule created", port_name);
204 }
205 return 0;
206}
207
208#endif /* HAVE_DPDK */
209/**
210 * @}
211 */
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267