[PATCH v2 18/25] net/iavf: use common action checks for FDIR
Anatoly Burakov
anatoly.burakov at intel.com
Mon Mar 16 11:52:43 CET 2026
Use the common flow action checking parsing infrastructure for checking
flow actions for FDIR filter.
Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
drivers/net/intel/iavf/iavf_fdir.c | 359 +++++++++++++----------------
1 file changed, 157 insertions(+), 202 deletions(-)
diff --git a/drivers/net/intel/iavf/iavf_fdir.c b/drivers/net/intel/iavf/iavf_fdir.c
index 7dce5086cf..1f17f8fa24 100644
--- a/drivers/net/intel/iavf/iavf_fdir.c
+++ b/drivers/net/intel/iavf/iavf_fdir.c
@@ -441,204 +441,6 @@ static struct iavf_flow_engine iavf_fdir_engine = {
.type = IAVF_FLOW_ENGINE_FDIR,
};
-static int
-iavf_fdir_parse_action_qregion(struct iavf_adapter *ad,
- struct rte_flow_error *error,
- const struct rte_flow_action *act,
- struct virtchnl_filter_action *filter_action)
-{
- struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
- 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] >= ad->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 <= IAVF_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;
- }
-
- if (rss->queue_num > vf->max_rss_qregion) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, act,
- "The region size cannot be large than the supported max RSS queue region");
- return -rte_errno;
- }
-
- filter_action->act_conf.queue.index = rss->queue[0];
- filter_action->act_conf.queue.region = rte_fls_u32(rss->queue_num) - 1;
-
- return 0;
-}
-
-static int
-iavf_fdir_parse_action(struct iavf_adapter *ad,
- const struct rte_flow_action actions[],
- struct rte_flow_error *error,
- struct iavf_fdir_conf *filter)
-{
- const struct rte_flow_action_queue *act_q;
- const struct rte_flow_action_mark *mark_spec = NULL;
- uint32_t dest_num = 0;
- uint32_t mark_num = 0;
- int ret;
-
- int number = 0;
- struct virtchnl_filter_action *filter_action;
-
- for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
- switch (actions->type) {
- case RTE_FLOW_ACTION_TYPE_VOID:
- break;
-
- case RTE_FLOW_ACTION_TYPE_PASSTHRU:
- dest_num++;
-
- filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
-
- filter_action->type = VIRTCHNL_ACTION_PASSTHRU;
-
- filter->add_fltr.rule_cfg.action_set.count = ++number;
- break;
-
- case RTE_FLOW_ACTION_TYPE_DROP:
- dest_num++;
-
- filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
-
- filter_action->type = VIRTCHNL_ACTION_DROP;
-
- filter->add_fltr.rule_cfg.action_set.count = ++number;
- break;
-
- case RTE_FLOW_ACTION_TYPE_QUEUE:
- dest_num++;
-
- act_q = actions->conf;
- filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
-
- filter_action->type = VIRTCHNL_ACTION_QUEUE;
- filter_action->act_conf.queue.index = act_q->index;
-
- if (filter_action->act_conf.queue.index >=
- ad->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->add_fltr.rule_cfg.action_set.count = ++number;
- break;
-
- case RTE_FLOW_ACTION_TYPE_RSS:
- dest_num++;
-
- filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
-
- filter_action->type = VIRTCHNL_ACTION_Q_REGION;
-
- ret = iavf_fdir_parse_action_qregion(ad,
- error, actions, filter_action);
- if (ret)
- return ret;
-
- filter->add_fltr.rule_cfg.action_set.count = ++number;
- break;
-
- case RTE_FLOW_ACTION_TYPE_MARK:
- mark_num++;
-
- filter->mark_flag = 1;
- mark_spec = actions->conf;
- filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
-
- filter_action->type = VIRTCHNL_ACTION_MARK;
- filter_action->act_conf.mark_id = mark_spec->id;
-
- filter->add_fltr.rule_cfg.action_set.count = ++number;
- break;
-
- default:
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, actions,
- "Invalid action.");
- return -rte_errno;
- }
- }
-
- if (number > VIRTCHNL_MAX_NUM_ACTIONS) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, actions,
- "Action numbers exceed the maximum value");
- 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 (dest_num + mark_num == 0) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, actions,
- "Empty action");
- return -rte_errno;
- }
-
- /* Mark only is equal to mark + passthru. */
- if (dest_num == 0) {
- filter_action = &filter->add_fltr.rule_cfg.action_set.actions[number];
- filter_action->type = VIRTCHNL_ACTION_PASSTHRU;
- filter->add_fltr.rule_cfg.action_set.count = ++number;
- }
-
- return 0;
-}
-
static bool
iavf_fdir_refine_input_set(const uint64_t input_set,
const uint64_t input_set_mask,
@@ -1587,6 +1389,145 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
return 0;
}
+static int
+iavf_fdir_action_check_qregion(struct iavf_adapter *ad,
+ const struct rte_flow_action_rss *rss,
+ struct rte_flow_error *error)
+{
+ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+ 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] >= ad->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 <= IAVF_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:"
+ "1, 2, 4, 8, 16, 32, 64, 128 as long as the total number "
+ "of queues do not exceed the VSI allocation.");
+ }
+
+ if (rss->queue_num > vf->max_rss_qregion) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION_CONF, rss,
+ "The region size cannot be large than the supported max RSS queue region");
+ }
+
+ return 0;
+}
+
+static int
+iavf_fdir_parse_action_check(const struct ci_flow_actions *actions,
+ const struct ci_flow_actions_check_param *param,
+ struct rte_flow_error *error)
+{
+ struct iavf_adapter *ad = param->driver_ctx;
+ struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+ struct iavf_fdir_conf *filter = &vf->fdir.conf;
+ uint32_t dest_num = 0, mark_num = 0;
+ size_t i, number = 0;
+ bool has_drop = false;
+ int ret;
+
+ for (i = 0; i < actions->count; i++) {
+ const struct rte_flow_action *act = actions->actions[i];
+ struct virtchnl_filter_action *filter_action =
+ &filter->add_fltr.rule_cfg.action_set.actions[number];
+
+ switch (act->type) {
+ case RTE_FLOW_ACTION_TYPE_PASSTHRU:
+ dest_num++;
+
+ filter_action->type = VIRTCHNL_ACTION_PASSTHRU;
+ break;
+ case RTE_FLOW_ACTION_TYPE_DROP:
+ dest_num++;
+ has_drop = true;
+
+ filter_action->type = VIRTCHNL_ACTION_DROP;
+ break;
+ case RTE_FLOW_ACTION_TYPE_QUEUE:
+ {
+ const struct rte_flow_action_queue *act_q;
+ dest_num++;
+
+ act_q = act->conf;
+
+ filter_action->type = VIRTCHNL_ACTION_QUEUE;
+
+ if (act_q->index >= ad->dev_data->nb_rx_queues) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "Invalid queue index.");
+ }
+ filter_action->act_conf.queue.index = act_q->index;
+
+ break;
+ }
+ case RTE_FLOW_ACTION_TYPE_RSS:
+ {
+ const struct rte_flow_action_rss *rss = act->conf;
+ dest_num++;
+
+ filter_action->type = VIRTCHNL_ACTION_Q_REGION;
+
+ ret = iavf_fdir_action_check_qregion(ad, rss, error);
+ if (ret)
+ return ret;
+
+ filter_action->act_conf.queue.index = rss->queue[0];
+ filter_action->act_conf.queue.region = rte_fls_u32(rss->queue_num) - 1;
+ break;
+ }
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ {
+ const struct rte_flow_action_mark *mark_spec;
+ mark_num++;
+
+ filter->mark_flag = 1;
+ mark_spec = act->conf;
+
+ filter_action->type = VIRTCHNL_ACTION_MARK;
+ filter_action->act_conf.mark_id = mark_spec->id;
+
+ break;
+ }
+ default:
+ /* cannot happen */
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "Invalid action.");
+ }
+ filter->add_fltr.rule_cfg.action_set.count = ++number;
+ }
+
+ if (dest_num > 1 || mark_num > 1 || (has_drop && mark_num > 1)) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "Unsupported action combination");
+ }
+
+ /* Mark only is equal to mark + passthru. */
+ if (dest_num == 0) {
+ struct virtchnl_filter_action *filter_action =
+ &filter->add_fltr.rule_cfg.action_set.actions[number];
+ filter_action->type = VIRTCHNL_ACTION_PASSTHRU;
+ filter->add_fltr.rule_cfg.action_set.count = ++number;
+ }
+
+ return 0;
+}
+
static int
iavf_fdir_parse(struct iavf_adapter *ad,
struct iavf_pattern_match_item *array,
@@ -1597,6 +1538,20 @@ iavf_fdir_parse(struct iavf_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_END
+ },
+ .max_actions = 2,
+ .check = iavf_fdir_parse_action_check,
+ .driver_ctx = ad
+ };
struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
struct iavf_fdir_conf *filter = &vf->fdir.conf;
struct iavf_pattern_match_item *item = NULL;
@@ -1608,6 +1563,10 @@ iavf_fdir_parse(struct iavf_adapter *ad,
if (ret)
return ret;
+ ret = ci_flow_check_actions(actions, ¶m, &parsed_actions, error);
+ if (ret)
+ return ret;
+
item = iavf_search_pattern_match_item(pattern, array, array_len, error);
if (!item)
return -rte_errno;
@@ -1617,10 +1576,6 @@ iavf_fdir_parse(struct iavf_adapter *ad,
if (ret)
goto error;
- ret = iavf_fdir_parse_action(ad, actions, error, filter);
- if (ret)
- goto error;
-
if (meta)
*meta = filter;
--
2.47.3
More information about the dev
mailing list