40 #define I40E_RSS_HKEY_LEN 52
42 #if RTE_VERSION < RTE_VERSION_NUM(20, 0, 0, 0)
43 static int i40eDeviceEnableSymHash(
44 int port_id,
const char *port_name, uint32_t ftype,
enum rte_eth_hash_function
function)
46 struct rte_eth_hash_filter_info info;
50 memset(&info, 0,
sizeof(info));
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
54 retval = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_HASH);
55 #pragma GCC diagnostic pop
57 SCLogError(
"RTE_ETH_FILTER_HASH not supported on port: %s", port_name);
61 info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG;
62 info.info.global_conf.hash_func =
function;
64 idx = ftype / UINT64_BIT;
65 offset = ftype % UINT64_BIT;
66 info.info.global_conf.valid_bit_mask[idx] |= (1ULL <<
offset);
67 info.info.global_conf.sym_hash_enable_mask[idx] |= (1ULL <<
offset);
69 #pragma GCC diagnostic push
70 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
71 retval = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_SET, &info);
72 #pragma GCC diagnostic pop
75 SCLogError(
"Cannot set global hash configurations on port %s", port_name);
82 static int i40eDeviceSetSymHash(
int port_id,
const char *port_name,
int enable)
85 struct rte_eth_hash_filter_info info;
87 memset(&info, 0,
sizeof(info));
89 #pragma GCC diagnostic push
90 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
91 ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_HASH);
92 #pragma GCC diagnostic pop
95 SCLogError(
"RTE_ETH_FILTER_HASH not supported on port: %s", port_name);
99 info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT;
100 info.info.enable = enable;
101 #pragma GCC diagnostic push
102 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
103 ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, RTE_ETH_FILTER_SET, &info);
104 #pragma GCC diagnostic pop
107 SCLogError(
"Cannot set symmetric hash enable per port on port %s", port_name);
114 static int i40eDeviceApplyRSSFilter(
int port_id,
const char *port_name)
120 retval |= i40eDeviceEnableSymHash(
121 port_id, port_name, RTE_ETH_FLOW_FRAG_IPV4, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
122 retval |= i40eDeviceEnableSymHash(
123 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV4_TCP, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
124 retval |= i40eDeviceEnableSymHash(
125 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV4_UDP, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
126 retval |= i40eDeviceEnableSymHash(
127 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV4_SCTP, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
128 retval |= i40eDeviceEnableSymHash(
129 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV4_OTHER, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
131 retval |= i40eDeviceEnableSymHash(
132 port_id, port_name, RTE_ETH_FLOW_FRAG_IPV6, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
133 retval |= i40eDeviceEnableSymHash(
134 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV6_TCP, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
135 retval |= i40eDeviceEnableSymHash(
136 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV6_UDP, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
137 retval |= i40eDeviceEnableSymHash(
138 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV6_SCTP, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
139 retval |= i40eDeviceEnableSymHash(
140 port_id, port_name, RTE_ETH_FLOW_NONFRAG_IPV6_OTHER, RTE_ETH_HASH_FUNCTION_TOEPLITZ);
142 retval |= i40eDeviceSetSymHash(port_id, port_name, 1);
146 static int32_t i40eDeviceSetRSSWithFilter(
int port_id,
const char *port_name)
148 int32_t ret = BondingIsBond(port_id);
153 i40eDeviceApplyRSSFilter(port_id, port_name);
154 }
else if (ret == 0) {
155 uint16_t bonded_devs[RTE_MAX_ETHPORTS];
156 ret = BondingMemberDevicesGet(port_id, bonded_devs, RTE_MAX_ETHPORTS);
157 for (
int i = 0; i < ret; i++) {
158 i40eDeviceApplyRSSFilter(bonded_devs[i], port_name);
161 FatalError(
"Unknown return value from BondingIsBond()");
169 static int i40eDeviceSetRSSFlowQueues(
170 int port_id,
const char *port_name,
struct rte_eth_rss_conf rss_conf,
int nb_rx_queues)
172 struct rte_flow_action_rss rss_action_conf = { 0 };
173 struct rte_flow_attr attr = { 0 };
174 struct rte_flow_item pattern[] = { { 0 }, { 0 }, { 0 }, { 0 } };
175 struct rte_flow_action action[] = { { 0 }, { 0 } };
176 struct rte_flow *flow;
177 struct rte_flow_error flow_error = { 0 };
178 uint16_t queues[RTE_MAX_QUEUES_PER_PORT];
180 for (
int i = 0; i < nb_rx_queues; ++i)
183 rss_action_conf.func = RTE_ETH_HASH_FUNCTION_DEFAULT;
184 rss_action_conf.level = 0;
185 rss_action_conf.types = 0;
186 rss_action_conf.key_len = 0;
187 rss_action_conf.key = NULL;
189 if (nb_rx_queues < 1) {
190 FatalError(
"The number of queues for RSS configuration must be "
191 "configured with a positive number");
194 rss_action_conf.queue_num = nb_rx_queues;
195 rss_action_conf.queue = queues;
198 pattern[0].type = RTE_FLOW_ITEM_TYPE_END;
199 action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
200 action[0].conf = &rss_action_conf;
201 action[1].type = RTE_FLOW_ACTION_TYPE_END;
203 flow = rte_flow_create(port_id, &attr, pattern, action, &flow_error);
205 SCLogError(
"Error when creating rte_flow rule on %s: %s", port_name, flow_error.message);
206 int ret = rte_flow_validate(port_id, &attr, pattern, action, &flow_error);
207 SCLogError(
"Error on rte_flow validation for port %s: %s errmsg: %s", port_name,
208 rte_strerror(-ret), flow_error.message);
211 SCLogInfo(
"RTE_FLOW queue region created for port %s", port_name);
216 static int i40eDeviceCreateRSSFlow(
int port_id,
const char *port_name,
217 struct rte_eth_rss_conf rss_conf, uint64_t rss_type,
struct rte_flow_item *pattern)
219 struct rte_flow_action_rss rss_action_conf = { 0 };
220 struct rte_flow_attr attr = { 0 };
221 struct rte_flow_action action[] = { { 0 }, { 0 } };
222 struct rte_flow *flow;
223 struct rte_flow_error flow_error = { 0 };
225 rss_action_conf.func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ;
226 rss_action_conf.level = 0;
227 rss_action_conf.types = rss_type;
228 rss_action_conf.key_len = rss_conf.rss_key_len;
229 rss_action_conf.key = rss_conf.rss_key;
230 rss_action_conf.queue_num = 0;
231 rss_action_conf.queue = NULL;
234 action[0].type = RTE_FLOW_ACTION_TYPE_RSS;
235 action[0].conf = &rss_action_conf;
236 action[1].type = RTE_FLOW_ACTION_TYPE_END;
238 flow = rte_flow_create(port_id, &attr, pattern, action, &flow_error);
240 SCLogError(
"Error when creating rte_flow rule on %s: %s", port_name, flow_error.message);
241 int ret = rte_flow_validate(port_id, &attr, pattern, action, &flow_error);
242 SCLogError(
"Error on rte_flow validation for port %s: %s errmsg: %s", port_name,
243 rte_strerror(-ret), flow_error.message);
246 SCLogInfo(
"RTE_FLOW flow rule created for port %s", port_name);
252 static int i40eDeviceSetRSSFlowIPv4(
253 int port_id,
const char *port_name,
struct rte_eth_rss_conf rss_conf)
256 struct rte_flow_item pattern[] = { { 0 }, { 0 }, { 0 }, { 0 } };
258 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
259 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
260 pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
261 ret |= i40eDeviceCreateRSSFlow(
262 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV4_OTHER, pattern);
263 memset(pattern, 0,
sizeof(pattern));
265 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
266 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
267 pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
268 pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
269 ret |= i40eDeviceCreateRSSFlow(
270 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV4_UDP, pattern);
271 memset(pattern, 0,
sizeof(pattern));
273 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
274 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
275 pattern[2].type = RTE_FLOW_ITEM_TYPE_TCP;
276 pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
277 ret |= i40eDeviceCreateRSSFlow(
278 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV4_TCP, pattern);
279 memset(pattern, 0,
sizeof(pattern));
281 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
282 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
283 pattern[2].type = RTE_FLOW_ITEM_TYPE_SCTP;
284 pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
285 ret |= i40eDeviceCreateRSSFlow(
286 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV4_SCTP, pattern);
287 memset(pattern, 0,
sizeof(pattern));
289 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
290 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4;
291 pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
292 ret |= i40eDeviceCreateRSSFlow(port_id, port_name, rss_conf, RTE_ETH_RSS_FRAG_IPV4, pattern);
297 static int i40eDeviceSetRSSFlowIPv6(
298 int port_id,
const char *port_name,
struct rte_eth_rss_conf rss_conf)
301 struct rte_flow_item pattern[] = { { 0 }, { 0 }, { 0 }, { 0 } };
303 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
304 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
305 pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
306 ret |= i40eDeviceCreateRSSFlow(
307 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV6_OTHER, pattern);
308 memset(pattern, 0,
sizeof(pattern));
310 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
311 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
312 pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
313 pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
314 ret |= i40eDeviceCreateRSSFlow(
315 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV6_UDP, pattern);
316 memset(pattern, 0,
sizeof(pattern));
318 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
319 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
320 pattern[2].type = RTE_FLOW_ITEM_TYPE_TCP;
321 pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
322 ret |= i40eDeviceCreateRSSFlow(
323 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV6_TCP, pattern);
324 memset(pattern, 0,
sizeof(pattern));
326 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
327 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
328 pattern[2].type = RTE_FLOW_ITEM_TYPE_SCTP;
329 pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
330 ret |= i40eDeviceCreateRSSFlow(
331 port_id, port_name, rss_conf, RTE_ETH_RSS_NONFRAG_IPV6_SCTP, pattern);
332 memset(pattern, 0,
sizeof(pattern));
334 pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH;
335 pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6;
336 pattern[2].type = RTE_FLOW_ITEM_TYPE_END;
337 ret |= i40eDeviceCreateRSSFlow(port_id, port_name, rss_conf, RTE_ETH_RSS_FRAG_IPV6, pattern);
342 static int i40eDeviceSetRSSWithFlows(
int port_id,
const char *port_name,
int nb_rx_queues)
345 uint8_t rss_key[I40E_RSS_HKEY_LEN];
346 struct rte_flow_error flush_error = { 0 };
347 struct rte_eth_rss_conf rss_conf = {
349 .rss_key_len = I40E_RSS_HKEY_LEN,
352 retval = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
354 SCLogError(
"Unable to get RSS hash configuration of port %s", port_name);
359 retval |= i40eDeviceSetRSSFlowQueues(port_id, port_name, rss_conf, nb_rx_queues);
360 retval |= i40eDeviceSetRSSFlowIPv4(port_id, port_name, rss_conf);
361 retval |= i40eDeviceSetRSSFlowIPv6(port_id, port_name, rss_conf);
363 retval = rte_flow_flush(port_id, &flush_error);
365 SCLogError(
"Unable to flush rte_flow rules of %s: %s Flush error msg: %s", port_name,
366 rte_strerror(-retval), flush_error.message);
376 int i40eDeviceSetRSS(
int port_id,
int nb_rx_queues)
380 char port_name[RTE_ETH_NAME_MAX_LEN];
382 retval = rte_eth_dev_get_name_by_port(port_id, port_name);
384 SCLogError(
"Failed to convert port id %d to the interface name: %s", port_id,
389 #if RTE_VERSION >= RTE_VERSION_NUM(20, 0, 0, 0)
390 i40eDeviceSetRSSWithFlows(port_id, port_name, nb_rx_queues);
392 i40eDeviceSetRSSWithFilter(port_id, port_name);
397 void i40eDeviceSetRSSConf(
struct rte_eth_rss_conf *rss_conf)
399 #if RTE_VERSION >= RTE_VERSION_NUM(20, 0, 0, 0)
400 rss_conf->rss_hf = RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_NONFRAG_IPV4_OTHER |
401 RTE_ETH_RSS_FRAG_IPV6 | RTE_ETH_RSS_NONFRAG_IPV6_OTHER;
402 rss_conf->rss_key = NULL;
403 rss_conf->rss_key_len = 0;
406 RTE_ETH_RSS_FRAG_IPV4 | RTE_ETH_RSS_NONFRAG_IPV4_TCP | RTE_ETH_RSS_NONFRAG_IPV4_UDP |
407 RTE_ETH_RSS_NONFRAG_IPV4_SCTP | RTE_ETH_RSS_NONFRAG_IPV4_OTHER | RTE_ETH_RSS_FRAG_IPV6 |
408 RTE_ETH_RSS_NONFRAG_IPV6_TCP | RTE_ETH_RSS_NONFRAG_IPV6_UDP |
409 RTE_ETH_RSS_NONFRAG_IPV6_SCTP | RTE_ETH_RSS_NONFRAG_IPV6_OTHER | RTE_ETH_RSS_SCTP;