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 
39 uint8_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  */
58 struct 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  */
96 int 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  */
141 int 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  */
180 int 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  */
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
util-dpdk-rss.h
util-debug.h
util-dpdk.h
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261