net/mlx5: Support extended destination format in flow steering command
Update the flow steering command formatting according to the extended destination API. Note that the FW dictates that multi destination FTEs that involve at least one encap must use the extended destination format, while single destination ones must use the legacy format. Using extended destination format requires FW support. Check for its capabilities and return error if not supported. Signed-off-by: Eli Britstein <elibr@mellanox.com> Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com> Reviewed-by: Oz Shlomo <ozsh@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
Родитель
aa39c2c0e4
Коммит
a2c6162b12
|
@ -308,22 +308,68 @@ static int mlx5_cmd_destroy_flow_group(struct mlx5_core_dev *dev,
|
|||
return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
|
||||
}
|
||||
|
||||
static int mlx5_set_extended_dest(struct mlx5_core_dev *dev,
|
||||
struct fs_fte *fte, bool *extended_dest)
|
||||
{
|
||||
int fw_log_max_fdb_encap_uplink =
|
||||
MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink);
|
||||
int num_fwd_destinations = 0;
|
||||
struct mlx5_flow_rule *dst;
|
||||
int num_encap = 0;
|
||||
|
||||
*extended_dest = false;
|
||||
if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(dst, &fte->node.children, node.list) {
|
||||
if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
|
||||
continue;
|
||||
if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_VPORT &&
|
||||
dst->dest_attr.vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID)
|
||||
num_encap++;
|
||||
num_fwd_destinations++;
|
||||
}
|
||||
if (num_fwd_destinations > 1 && num_encap > 0)
|
||||
*extended_dest = true;
|
||||
|
||||
if (*extended_dest && !fw_log_max_fdb_encap_uplink) {
|
||||
mlx5_core_warn(dev, "FW does not support extended destination");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) {
|
||||
mlx5_core_warn(dev, "FW does not support more than %d encaps",
|
||||
1 << fw_log_max_fdb_encap_uplink);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
||||
int opmod, int modify_mask,
|
||||
struct mlx5_flow_table *ft,
|
||||
unsigned group_id,
|
||||
struct fs_fte *fte)
|
||||
{
|
||||
unsigned int inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
|
||||
fte->dests_size * MLX5_ST_SZ_BYTES(dest_format_struct);
|
||||
u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
|
||||
bool extended_dest = false;
|
||||
struct mlx5_flow_rule *dst;
|
||||
void *in_flow_context, *vlan;
|
||||
void *in_match_value;
|
||||
unsigned int inlen;
|
||||
int dst_cnt_size;
|
||||
void *in_dests;
|
||||
u32 *in;
|
||||
int err;
|
||||
|
||||
if (mlx5_set_extended_dest(dev, fte, &extended_dest))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!extended_dest)
|
||||
dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct);
|
||||
else
|
||||
dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format);
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size;
|
||||
in = kvzalloc(inlen, GFP_KERNEL);
|
||||
if (!in)
|
||||
return -ENOMEM;
|
||||
|
@ -343,9 +389,20 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
|||
MLX5_SET(flow_context, in_flow_context, group_id, group_id);
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, flow_tag, fte->action.flow_tag);
|
||||
MLX5_SET(flow_context, in_flow_context, action, fte->action.action);
|
||||
MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
|
||||
fte->action.reformat_id);
|
||||
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);
|
||||
MLX5_SET(flow_context, in_flow_context, packet_reformat_id,
|
||||
fte->action.reformat_id);
|
||||
}
|
||||
MLX5_SET(flow_context, in_flow_context, modify_header_id,
|
||||
fte->action.modify_id);
|
||||
|
||||
|
@ -392,6 +449,15 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
|||
MLX5_SET(dest_format_struct, in_dests,
|
||||
destination_eswitch_owner_vhca_id,
|
||||
dst->dest_attr.vport.vhca_id);
|
||||
if (extended_dest) {
|
||||
MLX5_SET(dest_format_struct, in_dests,
|
||||
packet_reformat,
|
||||
!!(dst->dest_attr.vport.flags &
|
||||
MLX5_FLOW_DEST_VPORT_REFORMAT_ID));
|
||||
MLX5_SET(extended_dest_format, in_dests,
|
||||
packet_reformat_id,
|
||||
dst->dest_attr.vport.reformat_id);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
id = dst->dest_attr.tir_num;
|
||||
|
@ -400,7 +466,7 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
|||
MLX5_SET(dest_format_struct, in_dests, destination_type,
|
||||
type);
|
||||
MLX5_SET(dest_format_struct, in_dests, destination_id, id);
|
||||
in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
|
||||
in_dests += dst_cnt_size;
|
||||
list_size++;
|
||||
}
|
||||
|
||||
|
@ -421,7 +487,7 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
|||
|
||||
MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
|
||||
dst->dest_attr.counter_id);
|
||||
in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
|
||||
in_dests += dst_cnt_size;
|
||||
list_size++;
|
||||
}
|
||||
if (list_size > max_list_size) {
|
||||
|
|
|
@ -88,6 +88,7 @@ struct mlx5_flow_spec {
|
|||
|
||||
enum {
|
||||
MLX5_FLOW_DEST_VPORT_VHCA_ID = BIT(0),
|
||||
MLX5_FLOW_DEST_VPORT_REFORMAT_ID = BIT(1),
|
||||
};
|
||||
|
||||
struct mlx5_flow_destination {
|
||||
|
@ -100,6 +101,7 @@ struct mlx5_flow_destination {
|
|||
struct {
|
||||
u16 num;
|
||||
u16 vhca_id;
|
||||
u32 reformat_id;
|
||||
u8 flags;
|
||||
} vport;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче