[PATCH v1 13/25] net/i40e: use common action checks for FDIR
Anatoly Burakov
anatoly.burakov at intel.com
Wed Feb 11 15:20:30 CET 2026
Use the common flow action checking parsing infrastructure for checking
flow actions for flow director filter.
Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
---
drivers/net/intel/i40e/i40e_flow.c | 139 ++++++++++++++++-------------
1 file changed, 76 insertions(+), 63 deletions(-)
diff --git a/drivers/net/intel/i40e/i40e_flow.c b/drivers/net/intel/i40e/i40e_flow.c
index 0e9880e9ce..d8c8654cfa 100644
--- a/drivers/net/intel/i40e/i40e_flow.c
+++ b/drivers/net/intel/i40e/i40e_flow.c
@@ -2371,28 +2371,49 @@ i40e_flow_parse_fdir_action(struct rte_eth_dev *dev,
struct i40e_fdir_filter_conf *filter)
{
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- const struct rte_flow_action *act;
- const struct rte_flow_action_queue *act_q;
- const struct rte_flow_action_mark *mark_spec = NULL;
- uint32_t index = 0;
+ struct ci_flow_actions parsed_actions = {0};
+ struct ci_flow_actions_check_param ac_param = {
+ .allowed_types = (enum rte_flow_action_type[]) {
+ RTE_FLOW_ACTION_TYPE_QUEUE,
+ RTE_FLOW_ACTION_TYPE_DROP,
+ RTE_FLOW_ACTION_TYPE_PASSTHRU,
+ RTE_FLOW_ACTION_TYPE_MARK,
+ RTE_FLOW_ACTION_TYPE_FLAG,
+ RTE_FLOW_ACTION_TYPE_RSS,
+ RTE_FLOW_ACTION_TYPE_END
+ },
+ .max_actions = 2,
+ };
+ const struct rte_flow_action *first, *second;
+ int ret;
- /* Check if the first non-void action is QUEUE or DROP or PASSTHRU. */
- NEXT_ITEM_OF_ACTION(act, actions, index);
- switch (act->type) {
+ ret = ci_flow_check_actions(actions, &ac_param, &parsed_actions, error);
+ if (ret)
+ return ret;
+ first = parsed_actions.actions[0];
+ /* can be NULL */
+ second = parsed_actions.actions[1];
+
+ switch (first->type) {
case RTE_FLOW_ACTION_TYPE_QUEUE:
- act_q = act->conf;
+ {
+ const struct rte_flow_action_queue *act_q = first->conf;
+ /* check against PF constraints */
+ if (!filter->input.flow_ext.is_vf && act_q->index >= pf->dev_data->nb_rx_queues) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, first,
+ "Invalid queue ID for FDIR");
+ }
+ /* check against VF constraints */
+ if (filter->input.flow_ext.is_vf && act_q->index >= pf->vf_nb_qps) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, first,
+ "Invalid queue ID for FDIR");
+ }
filter->action.rx_queue = act_q->index;
- if ((!filter->input.flow_ext.is_vf &&
- filter->action.rx_queue >= pf->dev_data->nb_rx_queues) ||
- (filter->input.flow_ext.is_vf &&
- filter->action.rx_queue >= pf->vf_nb_qps)) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, act,
- "Invalid queue ID for FDIR.");
- return -rte_errno;
- }
filter->action.behavior = I40E_FDIR_ACCEPT;
break;
+ }
case RTE_FLOW_ACTION_TYPE_DROP:
filter->action.behavior = I40E_FDIR_REJECT;
break;
@@ -2400,69 +2421,61 @@ i40e_flow_parse_fdir_action(struct rte_eth_dev *dev,
filter->action.behavior = I40E_FDIR_PASSTHRU;
break;
case RTE_FLOW_ACTION_TYPE_MARK:
+ {
+ const struct rte_flow_action_mark *act_m = first->conf;
filter->action.behavior = I40E_FDIR_PASSTHRU;
- mark_spec = act->conf;
filter->action.report_status = I40E_FDIR_REPORT_ID;
- filter->soft_id = mark_spec->id;
- break;
+ filter->soft_id = act_m->id;
+ break;
+ }
default:
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, act,
- "Invalid action.");
- return -rte_errno;
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, first,
+ "Invalid first action for FDIR");
}
- /* Check if the next non-void item is MARK or FLAG or END. */
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
- switch (act->type) {
+ /* do we have another? */
+ if (second == NULL)
+ return 0;
+
+ switch (second->type) {
case RTE_FLOW_ACTION_TYPE_MARK:
- if (mark_spec) {
- /* Double MARK actions requested */
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, act,
- "Invalid action.");
- return -rte_errno;
+ {
+ const struct rte_flow_action_mark *act_m = second->conf;
+ /* only one mark action can be specified */
+ if (first->type == RTE_FLOW_ACTION_TYPE_MARK) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, second,
+ "Invalid second action for FDIR");
}
- mark_spec = act->conf;
filter->action.report_status = I40E_FDIR_REPORT_ID;
- filter->soft_id = mark_spec->id;
+ filter->soft_id = act_m->id;
break;
+ }
case RTE_FLOW_ACTION_TYPE_FLAG:
- if (mark_spec) {
- /* MARK + FLAG not supported */
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, act,
- "Invalid action.");
- return -rte_errno;
+ {
+ /* mark + flag is unsupported */
+ if (first->type == RTE_FLOW_ACTION_TYPE_MARK) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, second,
+ "Invalid second action for FDIR");
}
filter->action.report_status = I40E_FDIR_NO_REPORT_STATUS;
break;
+ }
case RTE_FLOW_ACTION_TYPE_RSS:
- if (filter->action.behavior != I40E_FDIR_PASSTHRU) {
- /* RSS filter won't be next if FDIR did not pass thru */
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION, act,
- "Invalid action.");
- return -rte_errno;
+ /* RSS filter only can be after passthru or mark */
+ if (first->type != RTE_FLOW_ACTION_TYPE_PASSTHRU &&
+ first->type != RTE_FLOW_ACTION_TYPE_MARK) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, second,
+ "Invalid second action for FDIR");
}
break;
- case RTE_FLOW_ACTION_TYPE_END:
- return 0;
default:
- rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
- act, "Invalid action.");
- return -rte_errno;
- }
-
- /* Check if the next non-void item is END */
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
- if (act->type != RTE_FLOW_ACTION_TYPE_END) {
- rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- act, "Invalid action.");
- return -rte_errno;
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, second,
+ "Invalid second action for FDIR");
}
return 0;
--
2.47.3
More information about the dev
mailing list