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

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
Loading
Loading
Loading
Loading
+37 −13
Original line number Diff line number Diff line
@@ -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;
	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 {
		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);
			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;
}
+7 −0
Original line number Diff line number Diff line
@@ -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;
+5 −0
Original line number Diff line number Diff line
@@ -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))
+25 −2
Original line number Diff line number Diff line
@@ -331,7 +331,15 @@ 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 ==
		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)
@@ -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);
+7 −0
Original line number Diff line number Diff line
@@ -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;
Loading