[PATCH v2 09/25] net/ixgbe: use common checks in RSS filter
Anatoly Burakov
anatoly.burakov at intel.com
Mon Mar 16 11:52:34 CET 2026
Use the common attr and action parsing infrastructure in RSS filter. As a
result, some checks have become more stringent, in particular:
- the group attribute is now explicitly rejected instead of being ignored
- RSS now explicitly rejects unsupported RSS types at validation
- the priority attribute was previously allowed but rejected values bigger
than 0xFFFF despite not using priority anywhere - it is now rejected
Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
drivers/net/intel/ixgbe/ixgbe_flow.c | 202 +++++++++++----------------
1 file changed, 85 insertions(+), 117 deletions(-)
diff --git a/drivers/net/intel/ixgbe/ixgbe_flow.c b/drivers/net/intel/ixgbe/ixgbe_flow.c
index b718c72125..ff86efe163 100644
--- a/drivers/net/intel/ixgbe/ixgbe_flow.c
+++ b/drivers/net/intel/ixgbe/ixgbe_flow.c
@@ -121,20 +121,6 @@ const struct rte_flow_item *next_no_void_pattern(
}
}
-static inline
-const struct rte_flow_action *next_no_void_action(
- const struct rte_flow_action actions[],
- const struct rte_flow_action *cur)
-{
- const struct rte_flow_action *next =
- cur ? cur + 1 : &actions[0];
- while (1) {
- if (next->type != RTE_FLOW_ACTION_TYPE_VOID)
- return next;
- next++;
- }
-}
-
/*
* All ixgbe engines mostly check the same stuff, so use a common check.
*/
@@ -2607,6 +2593,62 @@ ixgbe_parse_fdir_filter(struct rte_eth_dev *dev,
return ret;
}
+/* Flow actions check specific to RSS filter */
+static int
+ixgbe_flow_actions_check_rss(const struct ci_flow_actions *parsed_actions,
+ const struct ci_flow_actions_check_param *param,
+ struct rte_flow_error *error)
+{
+ const struct rte_flow_action *action = parsed_actions->actions[0];
+ const struct rte_flow_action_rss *rss_act = action->conf;
+ struct rte_eth_dev *dev = param->driver_ctx;
+ const size_t rss_key_len = sizeof(((struct ixgbe_rte_flow_rss_conf *)0)->key);
+ size_t q_idx, q;
+
+ /* check if queue list is not empty */
+ if (rss_act->queue_num == 0) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
+ "RSS queue list is empty");
+ }
+
+ /* check if each RSS queue is valid */
+ for (q_idx = 0; q_idx < rss_act->queue_num; q_idx++) {
+ q = rss_act->queue[q_idx];
+ if (q >= dev->data->nb_rx_queues) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
+ "Invalid RSS queue specified");
+ }
+ }
+
+ /* only support default hash function */
+ if (rss_act->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
+ "Non-default RSS hash functions are not supported");
+ }
+ /* levels aren't supported */
+ if (rss_act->level) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
+ "A nonzero RSS encapsulation level is not supported");
+ }
+ /* check key length */
+ if (rss_act->key_len != 0 && rss_act->key_len != rss_key_len) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
+ "RSS key must be exactly 40 bytes long");
+ }
+ /* filter out unsupported RSS types */
+ if ((rss_act->types & ~IXGBE_RSS_OFFLOAD_ALL) != 0) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss_act,
+ "Invalid RSS type specified");
+ }
+ return 0;
+}
+
static int
ixgbe_parse_rss_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
@@ -2614,109 +2656,35 @@ ixgbe_parse_rss_filter(struct rte_eth_dev *dev,
struct ixgbe_rte_flow_rss_conf *rss_conf,
struct rte_flow_error *error)
{
- const struct rte_flow_action *act;
- const struct rte_flow_action_rss *rss;
- uint16_t n;
-
- /**
- * rss only supports forwarding,
- * check if the first not void action is RSS.
- */
- act = next_no_void_action(actions, NULL);
- if (act->type != RTE_FLOW_ACTION_TYPE_RSS) {
- memset(rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- act, "Not supported action.");
- return -rte_errno;
- }
-
- rss = (const struct rte_flow_action_rss *)act->conf;
-
- if (!rss || !rss->queue_num) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- act,
- "no valid queues");
- return -rte_errno;
- }
-
- for (n = 0; n < rss->queue_num; n++) {
- if (rss->queue[n] >= dev->data->nb_rx_queues) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- act,
- "queue id > max number of queues");
- return -rte_errno;
- }
- }
-
- if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT)
- return rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
- "non-default RSS hash functions are not supported");
- if (rss->level)
- return rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
- "a nonzero RSS encapsulation level is not supported");
- if (rss->key_len && rss->key_len != RTE_DIM(rss_conf->key))
- return rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
- "RSS hash key must be exactly 40 bytes");
- if (rss->queue_num > RTE_DIM(rss_conf->queue))
- return rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, act,
- "too many queues for RSS context");
- if (ixgbe_rss_conf_init(rss_conf, rss))
- return rte_flow_error_set
- (error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, act,
- "RSS context initialization failure");
-
- /* check if the next not void item is END */
- act = next_no_void_action(actions, act);
- if (act->type != RTE_FLOW_ACTION_TYPE_END) {
- memset(rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- act, "Not supported action.");
- return -rte_errno;
- }
-
- /* parse attr */
- /* must be input direction */
- if (!attr->ingress) {
- memset(rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
- attr, "Only support ingress.");
- return -rte_errno;
- }
-
- /* not supported */
- if (attr->egress) {
- memset(rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
- attr, "Not support egress.");
- return -rte_errno;
- }
-
- /* not supported */
- if (attr->transfer) {
- memset(rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
- attr, "No support for transfer.");
- return -rte_errno;
- }
-
- if (attr->priority > 0xFFFF) {
- memset(rss_conf, 0, sizeof(struct ixgbe_rte_flow_rss_conf));
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
- attr, "Error priority.");
- return -rte_errno;
- }
+ struct ci_flow_actions parsed_actions;
+ struct ci_flow_actions_check_param ap_param = {
+ .allowed_types = (const enum rte_flow_action_type[]){
+ /* only rss allowed here */
+ RTE_FLOW_ACTION_TYPE_RSS,
+ RTE_FLOW_ACTION_TYPE_END
+ },
+ .driver_ctx = dev,
+ .check = ixgbe_flow_actions_check_rss,
+ .max_actions = 1,
+ };
+ int ret;
+ const struct rte_flow_action *action;
+
+ /* validate attributes */
+ ret = ci_flow_check_attr(attr, NULL, error);
+ if (ret)
+ return ret;
+
+ /* parse requested actions */
+ ret = ci_flow_check_actions(actions, &ap_param, &parsed_actions, error);
+ if (ret)
+ return ret;
+ action = parsed_actions.actions[0];
+
+ if (ixgbe_rss_conf_init(rss_conf, action->conf))
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "RSS context initialization failure");
return 0;
}
--
2.47.3
More information about the dev
mailing list