From: Vladimir Medvedkin <[email protected]> Use the common flow action checking parsing infrastructure for checking flow actions for FDIR filter.
Signed-off-by: Vladimir Medvedkin <[email protected]> --- drivers/net/intel/ice/ice_fdir_filter.c | 376 +++++++++++++----------- 1 file changed, 204 insertions(+), 172 deletions(-) diff --git a/drivers/net/intel/ice/ice_fdir_filter.c b/drivers/net/intel/ice/ice_fdir_filter.c index 553b20307c..a204aa785b 100644 --- a/drivers/net/intel/ice/ice_fdir_filter.c +++ b/drivers/net/intel/ice/ice_fdir_filter.c @@ -1604,177 +1604,6 @@ static struct ice_flow_engine ice_fdir_engine = { .type = ICE_FLOW_ENGINE_FDIR, }; -static int -ice_fdir_parse_action_qregion(struct ice_pf *pf, - struct rte_flow_error *error, - const struct rte_flow_action *act, - struct ice_fdir_filter_conf *filter) -{ - const struct rte_flow_action_rss *rss = act->conf; - uint32_t i; - - if (act->type != RTE_FLOW_ACTION_TYPE_RSS) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, act, - "Invalid action."); - return -rte_errno; - } - - if (rss->queue_num <= 1) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, act, - "Queue region size can't be 0 or 1."); - return -rte_errno; - } - - /* check if queue index for queue region is continuous */ - for (i = 0; i < rss->queue_num - 1; i++) { - if (rss->queue[i + 1] != rss->queue[i] + 1) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, act, - "Discontinuous queue region"); - return -rte_errno; - } - } - - if (rss->queue[rss->queue_num - 1] >= pf->dev_data->nb_rx_queues) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, act, - "Invalid queue region indexes."); - return -rte_errno; - } - - if (!(rte_is_power_of_2(rss->queue_num) && - (rss->queue_num <= ICE_FDIR_MAX_QREGION_SIZE))) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, act, - "The region size should be any of the following values:" - "1, 2, 4, 8, 16, 32, 64, 128 as long as the total number " - "of queues do not exceed the VSI allocation."); - return -rte_errno; - } - - filter->input.q_index = rss->queue[0]; - filter->input.q_region = rte_fls_u32(rss->queue_num) - 1; - filter->input.dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP; - - return 0; -} - -static int -ice_fdir_parse_action(struct ice_adapter *ad, - const struct rte_flow_action actions[], - struct rte_flow_error *error, - struct ice_fdir_filter_conf *filter) -{ - struct ice_pf *pf = &ad->pf; - const struct rte_flow_action_queue *act_q; - const struct rte_flow_action_mark *mark_spec = NULL; - const struct rte_flow_action_count *act_count; - uint32_t dest_num = 0; - uint32_t mark_num = 0; - uint32_t counter_num = 0; - int ret; - - for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { - switch (actions->type) { - case RTE_FLOW_ACTION_TYPE_VOID: - break; - case RTE_FLOW_ACTION_TYPE_QUEUE: - dest_num++; - - act_q = actions->conf; - filter->input.q_index = act_q->index; - if (filter->input.q_index >= - pf->dev_data->nb_rx_queues) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, - actions, - "Invalid queue for FDIR."); - return -rte_errno; - } - filter->input.dest_ctl = - ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX; - break; - case RTE_FLOW_ACTION_TYPE_DROP: - dest_num++; - - filter->input.dest_ctl = - ICE_FLTR_PRGM_DESC_DEST_DROP_PKT; - break; - case RTE_FLOW_ACTION_TYPE_PASSTHRU: - dest_num++; - - filter->input.dest_ctl = - ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER; - break; - case RTE_FLOW_ACTION_TYPE_RSS: - dest_num++; - - ret = ice_fdir_parse_action_qregion(pf, - error, actions, filter); - if (ret) - return ret; - break; - case RTE_FLOW_ACTION_TYPE_MARK: - mark_num++; - filter->mark_flag = 1; - mark_spec = actions->conf; - filter->input.fltr_id = mark_spec->id; - filter->input.fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ONE; - break; - case RTE_FLOW_ACTION_TYPE_COUNT: - counter_num++; - - act_count = actions->conf; - filter->input.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS; - rte_memcpy(&filter->act_count, act_count, - sizeof(filter->act_count)); - - break; - default: - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, actions, - "Invalid action."); - return -rte_errno; - } - } - - if (dest_num >= 2) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, actions, - "Unsupported action combination"); - return -rte_errno; - } - - if (mark_num >= 2) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, actions, - "Too many mark actions"); - return -rte_errno; - } - - if (counter_num >= 2) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, actions, - "Too many count actions"); - return -rte_errno; - } - - if (dest_num + mark_num + counter_num == 0) { - rte_flow_error_set(error, EINVAL, - RTE_FLOW_ERROR_TYPE_ACTION, actions, - "Empty action"); - return -rte_errno; - } - - /* set default action to PASSTHRU mode, in "mark/count only" case. */ - if (dest_num == 0) - filter->input.dest_ctl = - ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER; - - return 0; -} static int ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad, @@ -2451,6 +2280,189 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad, return 0; } +static int +ice_fdir_parse_action(struct ice_adapter *ad, + const struct ci_flow_actions *actions, + struct rte_flow_error *error) +{ + struct ice_pf *pf = &ad->pf; + struct ice_fdir_filter_conf *filter = &pf->fdir.conf; + bool dest_set = false; + size_t i; + + for (i = 0; i < actions->count; i++) { + const struct rte_flow_action *act = actions->actions[i]; + + switch (act->type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + { + const struct rte_flow_action_queue *act_q = act->conf; + dest_set = true; + + filter->input.q_index = act_q->index; + filter->input.dest_ctl = + ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QINDEX; + break; + } + case RTE_FLOW_ACTION_TYPE_DROP: + dest_set = true; + + filter->input.dest_ctl = + ICE_FLTR_PRGM_DESC_DEST_DROP_PKT; + break; + case RTE_FLOW_ACTION_TYPE_PASSTHRU: + dest_set = true; + + filter->input.dest_ctl = + ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER; + break; + case RTE_FLOW_ACTION_TYPE_RSS: + { + const struct rte_flow_action_rss *rss = act->conf; + dest_set = true; + + filter->input.q_index = rss->queue[0]; + filter->input.q_region = rte_fls_u32(rss->queue_num) - 1; + filter->input.dest_ctl = ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP; + + break; + } + case RTE_FLOW_ACTION_TYPE_MARK: + { + const struct rte_flow_action_mark *mark_spec = act->conf; + filter->mark_flag = 1; + filter->input.fltr_id = mark_spec->id; + filter->input.fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ONE; + break; + } + case RTE_FLOW_ACTION_TYPE_COUNT: + { + const struct rte_flow_action_count *act_count = act->conf; + + filter->input.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS; + rte_memcpy(&filter->act_count, act_count, + sizeof(filter->act_count)); + break; + } + default: + /* Should not happen */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, act, + "Invalid action."); + } + } + + /* set default action to PASSTHRU mode, in "mark/count only" case. */ + if (!dest_set) { + filter->input.dest_ctl = + ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_OTHER; + } + + return 0; +} + +static int +ice_fdir_check_action_qregion(struct ice_pf *pf, + struct rte_flow_error *error, + const struct rte_flow_action_rss *rss) +{ + if (rss->queue_num <= 1) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss, + "Queue region size can't be 0 or 1."); + } + + if (rss->queue[rss->queue_num - 1] >= pf->dev_data->nb_rx_queues) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss, + "Invalid queue region indexes."); + } + + if (!(rte_is_power_of_2(rss->queue_num) && + (rss->queue_num <= ICE_FDIR_MAX_QREGION_SIZE))) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss, + "The region size should be any of the following values:" + "2, 4, 8, 16, 32, 64, 128 as long as the total number " + "of queues do not exceed the VSI allocation."); + } + + return 0; +} + +static int +ice_fdir_check_action(const struct ci_flow_actions *actions, + const struct ci_flow_actions_check_param *param, + struct rte_flow_error *error) +{ + struct ice_adapter *ad = param->driver_ctx; + struct ice_pf *pf = &ad->pf; + uint32_t dest_num = 0; + uint32_t mark_num = 0; + uint32_t counter_num = 0; + size_t i; + int ret; + + for (i = 0; i < actions->count; i++) { + const struct rte_flow_action *act = actions->actions[i]; + + switch (act->type) { + case RTE_FLOW_ACTION_TYPE_QUEUE: + { + const struct rte_flow_action_queue *act_q = act->conf; + dest_num++; + + if (act_q->index >= pf->dev_data->nb_rx_queues) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, + act, + "Invalid queue for FDIR."); + } + break; + } + case RTE_FLOW_ACTION_TYPE_DROP: + dest_num++; + break; + case RTE_FLOW_ACTION_TYPE_PASSTHRU: + dest_num++; + break; + case RTE_FLOW_ACTION_TYPE_RSS: + { + const struct rte_flow_action_rss *rss = act->conf; + + dest_num++; + ret = ice_fdir_check_action_qregion(pf, error, rss); + if (ret) + return ret; + break; + } + case RTE_FLOW_ACTION_TYPE_MARK: + { + mark_num++; + break; + } + case RTE_FLOW_ACTION_TYPE_COUNT: + { + counter_num++; + break; + } + default: + /* Should not happen */ + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, act, + "Invalid action."); + } + } + + if (dest_num > 1 || mark_num > 1 || counter_num > 1) { + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "Unsupported action combination"); + } + + return 0; +} + static int ice_fdir_parse(struct ice_adapter *ad, struct ice_pattern_match_item *array, @@ -2461,6 +2473,21 @@ ice_fdir_parse(struct ice_adapter *ad, void **meta, struct rte_flow_error *error) { + struct ci_flow_actions parsed_actions = {0}; + struct ci_flow_actions_check_param param = { + .allowed_types = (enum rte_flow_action_type[]){ + RTE_FLOW_ACTION_TYPE_PASSTHRU, + RTE_FLOW_ACTION_TYPE_DROP, + RTE_FLOW_ACTION_TYPE_QUEUE, + RTE_FLOW_ACTION_TYPE_RSS, + RTE_FLOW_ACTION_TYPE_MARK, + RTE_FLOW_ACTION_TYPE_COUNT, + RTE_FLOW_ACTION_TYPE_END + }, + .max_actions = 3, + .check = ice_fdir_check_action, + .driver_ctx = ad, + }; struct ice_pf *pf = &ad->pf; struct ice_fdir_filter_conf *filter = &pf->fdir.conf; struct ice_pattern_match_item *item = NULL; @@ -2473,6 +2500,11 @@ ice_fdir_parse(struct ice_adapter *ad, return ret; memset(filter, 0, sizeof(*filter)); + + ret = ci_flow_check_actions(actions, ¶m, &parsed_actions, error); + if (ret) + return ret; + item = ice_search_pattern_match_item(ad, pattern, array, array_len, error); @@ -2500,7 +2532,7 @@ ice_fdir_parse(struct ice_adapter *ad, goto error; } - ret = ice_fdir_parse_action(ad, actions, error, filter); + ret = ice_fdir_parse_action(ad, &parsed_actions, error); if (ret) goto error; -- 2.47.3

