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 <[email protected]>
---
 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 c857eb0227..6d1986f444 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.
  */
@@ -2579,6 +2565,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,
@@ -2586,109 +2628,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

Reply via email to