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

