Use the common flow action checking parsing infrastructure for checking
flow actions for flow director tunnel filter. As a result, more stringent
checks are performed against parametersm specifically the following:

- reject NULL conf for VF action (instead of attempt at NULL dereference)
- second action was expected to be QUEUE but if it wasn't it was ignored

Signed-off-by: Anatoly Burakov <[email protected]>
---
 drivers/net/intel/i40e/i40e_flow.c | 104 +++++++++++++----------------
 1 file changed, 48 insertions(+), 56 deletions(-)

diff --git a/drivers/net/intel/i40e/i40e_flow.c 
b/drivers/net/intel/i40e/i40e_flow.c
index d8c8654cfa..dd3bf5822a 100644
--- a/drivers/net/intel/i40e/i40e_flow.c
+++ b/drivers/net/intel/i40e/i40e_flow.c
@@ -1103,15 +1103,6 @@ static struct i40e_valid_pattern 
i40e_supported_patterns[] = {
        { pattern_fdir_ipv6_sctp, i40e_flow_parse_l4_cloud_filter },
 };
 
-#define NEXT_ITEM_OF_ACTION(act, actions, index)                        \
-       do {                                                            \
-               act = actions + index;                                  \
-               while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {        \
-                       index++;                                        \
-                       act = actions + index;                          \
-               }                                                       \
-       } while (0)
-
 /* Find the first VOID or non-VOID item pointer */
 static const struct rte_flow_item *
 i40e_find_first_item(const struct rte_flow_item *item, bool is_void)
@@ -2514,61 +2505,62 @@ i40e_flow_parse_tunnel_action(struct rte_eth_dev *dev,
                              struct i40e_tunnel_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_vf *act_vf;
-       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_PF,
+                       RTE_FLOW_ACTION_TYPE_VF,
+                       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 PF or VF. */
-       NEXT_ITEM_OF_ACTION(act, actions, index);
-       if (act->type != RTE_FLOW_ACTION_TYPE_PF &&
-           act->type != RTE_FLOW_ACTION_TYPE_VF) {
-               rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION,
-                                  act, "Not supported action.");
-               return -rte_errno;
-       }
+       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];
 
-       if (act->type == RTE_FLOW_ACTION_TYPE_VF) {
-               act_vf = act->conf;
-               filter->vf_id = act_vf->id;
+       /* first action must be PF or VF */
+       if (first->type == RTE_FLOW_ACTION_TYPE_VF) {
+               const struct rte_flow_action_vf *vf = first->conf;
+               if (vf->id >= pf->vf_num) {
+                       rte_flow_error_set(error, EINVAL,
+                                       RTE_FLOW_ERROR_TYPE_ACTION, first,
+                                       "Invalid VF ID for tunnel filter");
+                       return -rte_errno;
+               }
+               filter->vf_id = vf->id;
                filter->is_to_vf = 1;
-               if (filter->vf_id >= pf->vf_num) {
-                       rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_ACTION,
-                                  act, "Invalid VF ID for tunnel filter");
-                       return -rte_errno;
-               }
+       } else if (first->type != RTE_FLOW_ACTION_TYPE_PF) {
+               return rte_flow_error_set(error, EINVAL,
+                                         RTE_FLOW_ERROR_TYPE_ACTION, first,
+                                         "Unsupported action");
        }
 
-       /* Check if the next non-void item is QUEUE */
-       index++;
-       NEXT_ITEM_OF_ACTION(act, actions, index);
-       if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
-               act_q = act->conf;
-               filter->queue_id = act_q->index;
-               if ((!filter->is_to_vf) &&
-                   (filter->queue_id >= pf->dev_data->nb_rx_queues)) {
-                       rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_ACTION,
-                                  act, "Invalid queue ID for tunnel filter");
-                       return -rte_errno;
-               } else if (filter->is_to_vf &&
-                          (filter->queue_id >= pf->vf_nb_qps)) {
-                       rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_ACTION,
-                                  act, "Invalid queue ID for tunnel filter");
-                       return -rte_errno;
-               }
-       }
+       /* check if second action is QUEUE */
+       if (second == NULL)
+               return 0;
 
-       /* 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, "Not supported action.");
-               return -rte_errno;
+       act_q = second->conf;
+       /* check queue ID for PF flow */
+       if (!filter->is_to_vf && act_q->index >= pf->dev_data->nb_rx_queues) {
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION_CONF, act_q,
+                               "Invalid queue ID for tunnel filter");
+       }
+       /* check queue ID for VF flow */
+       if (filter->is_to_vf && act_q->index >= pf->vf_nb_qps) {
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION_CONF, act_q,
+                               "Invalid queue ID for tunnel filter");
        }
+       filter->queue_id = act_q->index;
 
        return 0;
 }
-- 
2.47.3

Reply via email to