From: Dariusz Sosnowski <dsosnow...@nvidia.com>

This patch adds validation step for action templates and validates if
RTE_FLOW_ACTION_TYPE_MODIFY_FIELD actions' fields are properly masked.

Signed-off-by: Dariusz Sosnowski <dsosnow...@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c | 132 ++++++++++++++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index b89d2cc44f..1f98e1248a 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -2047,6 +2047,136 @@ flow_hw_table_destroy(struct rte_eth_dev *dev,
        return 0;
 }
 
+static int
+flow_hw_validate_action_modify_field(const struct rte_flow_action *action,
+                                    const struct rte_flow_action *mask,
+                                    struct rte_flow_error *error)
+{
+       const struct rte_flow_action_modify_field *action_conf =
+               action->conf;
+       const struct rte_flow_action_modify_field *mask_conf =
+               mask->conf;
+
+       if (action_conf->operation != mask_conf->operation)
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "modify_field operation mask and template are 
not equal");
+       if (action_conf->dst.field != mask_conf->dst.field)
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "destination field mask and template are not 
equal");
+       if (action_conf->dst.field == RTE_FLOW_FIELD_POINTER ||
+           action_conf->dst.field == RTE_FLOW_FIELD_VALUE)
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "immediate value and pointer cannot be used as 
destination");
+       if (mask_conf->dst.level != UINT32_MAX)
+               return rte_flow_error_set(error, EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ACTION, action,
+                       "destination encapsulation level must be fully masked");
+       if (mask_conf->dst.offset != UINT32_MAX)
+               return rte_flow_error_set(error, EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ACTION, action,
+                       "destination offset level must be fully masked");
+       if (action_conf->src.field != mask_conf->src.field)
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "destination field mask and template are not 
equal");
+       if (action_conf->src.field != RTE_FLOW_FIELD_POINTER &&
+           action_conf->src.field != RTE_FLOW_FIELD_VALUE) {
+               if (mask_conf->src.level != UINT32_MAX)
+                       return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "source encapsulation level must be fully 
masked");
+               if (mask_conf->src.offset != UINT32_MAX)
+                       return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "source offset level must be fully masked");
+       }
+       if (mask_conf->width != UINT32_MAX)
+               return rte_flow_error_set(error, EINVAL,
+                               RTE_FLOW_ERROR_TYPE_ACTION, action,
+                               "modify_field width field must be fully 
masked");
+       return 0;
+}
+
+static int
+flow_hw_action_validate(const struct rte_flow_action actions[],
+                       const struct rte_flow_action masks[],
+                       struct rte_flow_error *error)
+{
+       int i;
+       bool actions_end = false;
+       int ret;
+
+       for (i = 0; !actions_end; ++i) {
+               const struct rte_flow_action *action = &actions[i];
+               const struct rte_flow_action *mask = &masks[i];
+
+               if (action->type != mask->type)
+                       return rte_flow_error_set(error, ENOTSUP,
+                                                 RTE_FLOW_ERROR_TYPE_ACTION,
+                                                 action,
+                                                 "mask type does not match 
action type");
+               switch (action->type) {
+               case RTE_FLOW_ACTION_TYPE_VOID:
+                       break;
+               case RTE_FLOW_ACTION_TYPE_INDIRECT:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_MARK:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_DROP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_JUMP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_QUEUE:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_RSS:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+                       /* TODO: Validation logic */
+                       break;
+               case RTE_FLOW_ACTION_TYPE_MODIFY_FIELD:
+                       ret = flow_hw_validate_action_modify_field(action,
+                                                                       mask,
+                                                                       error);
+                       if (ret < 0)
+                               return ret;
+                       break;
+               case RTE_FLOW_ACTION_TYPE_END:
+                       actions_end = true;
+                       break;
+               default:
+                       return rte_flow_error_set(error, ENOTSUP,
+                                                 RTE_FLOW_ERROR_TYPE_ACTION,
+                                                 action,
+                                                 "action not supported in 
template API");
+               }
+       }
+       return 0;
+}
+
 /**
  * Create flow action template.
  *
@@ -2075,6 +2205,8 @@ flow_hw_actions_template_create(struct rte_eth_dev *dev,
        int len, act_len, mask_len, i;
        struct rte_flow_actions_template *at;
 
+       if (flow_hw_action_validate(actions, masks, error))
+               return NULL;
        act_len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS,
                                NULL, 0, actions, error);
        if (act_len <= 0)
-- 
2.25.1

Reply via email to