]> git.itanic.dy.fi Git - linux-stable/commitdiff
net/mlx5: DR, Support SW created encap actions for FW table
authorYevgeny Kliteynik <kliteyn@nvidia.com>
Sun, 11 Jun 2023 22:05:48 +0000 (01:05 +0300)
committerSaeed Mahameed <saeedm@nvidia.com>
Fri, 16 Jun 2023 19:59:19 +0000 (12:59 -0700)
In some cases, steering might need to use SW-created action in
FW table, which results in wrong packet reformat being used:

  mlx5_core 0000:81:00.1: mlx5_cmd_check:756:(pid 1154):
      SET_FLOW_TABLE_ENTRY(0×936) op_mod(0×0) failed,
      status bad resource(0×5), syndrome (0xf2ff71)

This patch adds support for usage of SW-created packet reformat (encap)
actions in FW tables, and adds clear error flow for attempt to use
SW-created modify header on FW tables.

Fixes: 6a48faeeca10 ("net/mlx5: Add direct rule fs_cmd implementation")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Erez Shitrit <erezsh@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.h
drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h

index 144e59480686447de7c74d60f28b5efa9066dce6..ec83e6483d1a2acb5b33f44cd514ed96e0efb3da 100644 (file)
@@ -511,10 +511,11 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
        struct mlx5_flow_rule *dst;
        void *in_flow_context, *vlan;
        void *in_match_value;
+       int reformat_id = 0;
        unsigned int inlen;
        int dst_cnt_size;
+       u32 *in, action;
        void *in_dests;
-       u32 *in;
        int err;
 
        if (mlx5_set_extended_dest(dev, fte, &extended_dest))
@@ -553,22 +554,42 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
 
        MLX5_SET(flow_context, in_flow_context, extended_destination,
                 extended_dest);
-       if (extended_dest) {
-               u32 action;
 
-               action = fte->action.action &
-                       ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
-               MLX5_SET(flow_context, in_flow_context, action, action);
-       } else {
-               MLX5_SET(flow_context, in_flow_context, action,
-                        fte->action.action);
-               if (fte->action.pkt_reformat)
-                       MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
-                                fte->action.pkt_reformat->id);
+       action = fte->action.action;
+       if (extended_dest)
+               action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
+
+       MLX5_SET(flow_context, in_flow_context, action, action);
+
+       if (!extended_dest && fte->action.pkt_reformat) {
+               struct mlx5_pkt_reformat *pkt_reformat = fte->action.pkt_reformat;
+
+               if (pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_SW) {
+                       reformat_id = mlx5_fs_dr_action_get_pkt_reformat_id(pkt_reformat);
+                       if (reformat_id < 0) {
+                               mlx5_core_err(dev,
+                                             "Unsupported SW-owned pkt_reformat type (%d) in FW-owned table\n",
+                                             pkt_reformat->reformat_type);
+                               err = reformat_id;
+                               goto err_out;
+                       }
+               } else {
+                       reformat_id = fte->action.pkt_reformat->id;
+               }
        }
-       if (fte->action.modify_hdr)
+
+       MLX5_SET(flow_context, in_flow_context, packet_reformat_id, (u32)reformat_id);
+
+       if (fte->action.modify_hdr) {
+               if (fte->action.modify_hdr->owner == MLX5_FLOW_RESOURCE_OWNER_SW) {
+                       mlx5_core_err(dev, "Can't use SW-owned modify_hdr in FW-owned table\n");
+                       err = -EOPNOTSUPP;
+                       goto err_out;
+               }
+
                MLX5_SET(flow_context, in_flow_context, modify_header_id,
                         fte->action.modify_hdr->id);
+       }
 
        MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type,
                 fte->action.crypto.type);
@@ -885,6 +906,8 @@ static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
 
        pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out,
                                    out, packet_reformat_id);
+       pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
+
        kfree(in);
        return err;
 }
@@ -969,6 +992,7 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
        err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
 
        modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id);
+       modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
        kfree(in);
        return err;
 }
index f137a0611b77b41a7c733b60b1321af60b70c0f3..b043190e50a86d4a95c143215ed7cfc82bfc2440 100644 (file)
@@ -54,8 +54,14 @@ struct mlx5_flow_definer {
        u32 id;
 };
 
+enum mlx5_flow_resource_owner {
+       MLX5_FLOW_RESOURCE_OWNER_FW,
+       MLX5_FLOW_RESOURCE_OWNER_SW,
+};
+
 struct mlx5_modify_hdr {
        enum mlx5_flow_namespace_type ns_type;
+       enum mlx5_flow_resource_owner owner;
        union {
                struct mlx5_fs_dr_action action;
                u32 id;
@@ -65,6 +71,7 @@ struct mlx5_modify_hdr {
 struct mlx5_pkt_reformat {
        enum mlx5_flow_namespace_type ns_type;
        int reformat_type; /* from mlx5_ifc */
+       enum mlx5_flow_resource_owner owner;
        union {
                struct mlx5_fs_dr_action action;
                u32 id;
index 0eb9a8d7f282fc93e99ab4598a52b950d877f6d0..57e22c5170df68bf7194883bb853782e4bea529b 100644 (file)
@@ -2129,6 +2129,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id,
        return action;
 }
 
+u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action)
+{
+       return action->reformat->id;
+}
+
 int mlx5dr_action_destroy(struct mlx5dr_action *action)
 {
        if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1))
index 984653756779616de63528501cbdab338c025162..cc215beb743673fd6a6a72de7df7712e42b51dc9 100644 (file)
@@ -331,8 +331,16 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
        }
 
        if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
-               bool is_decap = fte->action.pkt_reformat->reformat_type ==
-                       MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
+               bool is_decap;
+
+               if (fte->action.pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_FW) {
+                       err = -EINVAL;
+                       mlx5dr_err(domain, "FW-owned reformat can't be used in SW rule\n");
+                               goto free_actions;
+               }
+
+               is_decap = fte->action.pkt_reformat->reformat_type ==
+                          MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
 
                if (is_decap)
                        actions[num_actions++] =
@@ -661,6 +669,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
                return -EINVAL;
        }
 
+       pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
        pkt_reformat->action.dr_action = action;
 
        return 0;
@@ -691,6 +700,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
                return -EINVAL;
        }
 
+       modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
        modify_hdr->action.dr_action = action;
 
        return 0;
@@ -816,6 +826,19 @@ static u32 mlx5_cmd_dr_get_capabilities(struct mlx5_flow_root_namespace *ns,
        return steering_caps;
 }
 
+int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat)
+{
+       switch (pkt_reformat->reformat_type) {
+       case MLX5_REFORMAT_TYPE_L2_TO_VXLAN:
+       case MLX5_REFORMAT_TYPE_L2_TO_NVGRE:
+       case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
+       case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
+       case MLX5_REFORMAT_TYPE_INSERT_HDR:
+               return mlx5dr_action_get_pkt_reformat_id(pkt_reformat->action.dr_action);
+       }
+       return -EOPNOTSUPP;
+}
+
 bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
 {
        return mlx5dr_is_supported(dev);
index d168622063d559d06b69656190c085411f5f8153..99a3b2eff6b8fdd5c946f71dea7944ea11040777 100644 (file)
@@ -38,6 +38,8 @@ struct mlx5_fs_dr_table {
 
 bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev);
 
+int mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat);
+
 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void);
 
 #else
@@ -47,6 +49,11 @@ static inline const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void)
        return NULL;
 }
 
+static inline u32 mlx5_fs_dr_action_get_pkt_reformat_id(struct mlx5_pkt_reformat *pkt_reformat)
+{
+       return 0;
+}
+
 static inline bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
 {
        return false;
index 9afd268a257381015d347eae469f5407b1132bfd..d1c04f43d86df578e9b000d28708be385a1e7b7e 100644 (file)
@@ -150,6 +150,8 @@ mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn,
 
 int mlx5dr_action_destroy(struct mlx5dr_action *action);
 
+u32 mlx5dr_action_get_pkt_reformat_id(struct mlx5dr_action *action);
+
 int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
                       u8 *dw_selectors, u8 *byte_selectors,
                       u8 *match_mask, u32 *definer_id);