Use the common flow action checking parsing infrastructure for checking
flow actions for flow director filter.

Signed-off-by: Anatoly Burakov <[email protected]>
---
 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

Reply via email to