Commit 87cd0649 authored by Yevgeny Kliteynik's avatar Yevgeny Kliteynik Committed by Saeed Mahameed

net/mlx5: DR, Support SW created encap actions for FW table

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: 6a48faee ("net/mlx5: Add direct rule fs_cmd implementation")
Signed-off-by: default avatarYevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: default avatarErez Shitrit <erezsh@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent fb7be476
...@@ -511,10 +511,11 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, ...@@ -511,10 +511,11 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
struct mlx5_flow_rule *dst; struct mlx5_flow_rule *dst;
void *in_flow_context, *vlan; void *in_flow_context, *vlan;
void *in_match_value; void *in_match_value;
int reformat_id = 0;
unsigned int inlen; unsigned int inlen;
int dst_cnt_size; int dst_cnt_size;
u32 *in, action;
void *in_dests; void *in_dests;
u32 *in;
int err; int err;
if (mlx5_set_extended_dest(dev, fte, &extended_dest)) if (mlx5_set_extended_dest(dev, fte, &extended_dest))
...@@ -553,22 +554,42 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, ...@@ -553,22 +554,42 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
MLX5_SET(flow_context, in_flow_context, extended_destination, MLX5_SET(flow_context, in_flow_context, extended_destination,
extended_dest); extended_dest);
if (extended_dest) {
u32 action;
action = fte->action.action & action = fte->action.action;
~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; if (extended_dest)
MLX5_SET(flow_context, in_flow_context, action, action); action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
} else {
MLX5_SET(flow_context, in_flow_context, action, MLX5_SET(flow_context, in_flow_context, action, action);
fte->action.action);
if (fte->action.pkt_reformat) if (!extended_dest && fte->action.pkt_reformat) {
MLX5_SET(flow_context, in_flow_context, packet_reformat_id, struct mlx5_pkt_reformat *pkt_reformat = fte->action.pkt_reformat;
fte->action.pkt_reformat->id);
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, MLX5_SET(flow_context, in_flow_context, modify_header_id,
fte->action.modify_hdr->id); fte->action.modify_hdr->id);
}
MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type, MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type,
fte->action.crypto.type); fte->action.crypto.type);
...@@ -885,6 +906,8 @@ static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, ...@@ -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, pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out,
out, packet_reformat_id); out, packet_reformat_id);
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
kfree(in); kfree(in);
return err; return err;
} }
...@@ -969,6 +992,7 @@ static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns, ...@@ -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)); 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->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id);
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_FW;
kfree(in); kfree(in);
return err; return err;
} }
......
...@@ -54,8 +54,14 @@ struct mlx5_flow_definer { ...@@ -54,8 +54,14 @@ struct mlx5_flow_definer {
u32 id; u32 id;
}; };
enum mlx5_flow_resource_owner {
MLX5_FLOW_RESOURCE_OWNER_FW,
MLX5_FLOW_RESOURCE_OWNER_SW,
};
struct mlx5_modify_hdr { struct mlx5_modify_hdr {
enum mlx5_flow_namespace_type ns_type; enum mlx5_flow_namespace_type ns_type;
enum mlx5_flow_resource_owner owner;
union { union {
struct mlx5_fs_dr_action action; struct mlx5_fs_dr_action action;
u32 id; u32 id;
...@@ -65,6 +71,7 @@ struct mlx5_modify_hdr { ...@@ -65,6 +71,7 @@ struct mlx5_modify_hdr {
struct mlx5_pkt_reformat { struct mlx5_pkt_reformat {
enum mlx5_flow_namespace_type ns_type; enum mlx5_flow_namespace_type ns_type;
int reformat_type; /* from mlx5_ifc */ int reformat_type; /* from mlx5_ifc */
enum mlx5_flow_resource_owner owner;
union { union {
struct mlx5_fs_dr_action action; struct mlx5_fs_dr_action action;
u32 id; u32 id;
......
...@@ -2129,6 +2129,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id, ...@@ -2129,6 +2129,11 @@ mlx5dr_action_create_aso(struct mlx5dr_domain *dmn, u32 obj_id,
return action; 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) int mlx5dr_action_destroy(struct mlx5dr_action *action)
{ {
if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1)) if (WARN_ON_ONCE(refcount_read(&action->refcount) > 1))
......
...@@ -331,8 +331,16 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, ...@@ -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) { if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) {
bool is_decap = fte->action.pkt_reformat->reformat_type == bool is_decap;
MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
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) if (is_decap)
actions[num_actions++] = actions[num_actions++] =
...@@ -661,6 +669,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns ...@@ -661,6 +669,7 @@ static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns
return -EINVAL; return -EINVAL;
} }
pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
pkt_reformat->action.dr_action = action; pkt_reformat->action.dr_action = action;
return 0; return 0;
...@@ -691,6 +700,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns, ...@@ -691,6 +700,7 @@ static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns,
return -EINVAL; return -EINVAL;
} }
modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_SW;
modify_hdr->action.dr_action = action; modify_hdr->action.dr_action = action;
return 0; return 0;
...@@ -816,6 +826,19 @@ static u32 mlx5_cmd_dr_get_capabilities(struct mlx5_flow_root_namespace *ns, ...@@ -816,6 +826,19 @@ static u32 mlx5_cmd_dr_get_capabilities(struct mlx5_flow_root_namespace *ns,
return steering_caps; 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) bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
{ {
return mlx5dr_is_supported(dev); return mlx5dr_is_supported(dev);
......
...@@ -38,6 +38,8 @@ struct mlx5_fs_dr_table { ...@@ -38,6 +38,8 @@ struct mlx5_fs_dr_table {
bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev); 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); const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void);
#else #else
...@@ -47,6 +49,11 @@ static inline const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void) ...@@ -47,6 +49,11 @@ static inline const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void)
return NULL; 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) static inline bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev)
{ {
return false; return false;
......
...@@ -150,6 +150,8 @@ mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn, ...@@ -150,6 +150,8 @@ mlx5dr_action_create_dest_match_range(struct mlx5dr_domain *dmn,
int mlx5dr_action_destroy(struct mlx5dr_action *action); 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, int mlx5dr_definer_get(struct mlx5dr_domain *dmn, u16 format_id,
u8 *dw_selectors, u8 *byte_selectors, u8 *dw_selectors, u8 *byte_selectors,
u8 *match_mask, u32 *definer_id); u8 *match_mask, u32 *definer_id);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment