mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-14 15:54:15 +08:00
net/mlx5_core: Introduce flow steering destination of type counter
When adding a flow steering rule with a counter, need to supply a destination of type MLX5_FLOW_DESTINATION_TYPE_COUNTER, with a pointer to a struct mlx5_fc. Also, MLX5_FLOW_CONTEXT_ACTION_COUNT bit should be set in the action. Signed-off-by: Amir Vadai <amirva@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9dc0b289c4
commit
bd5251dbf1
@ -241,17 +241,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->flow_tag);
|
||||
MLX5_SET(flow_context, in_flow_context, action, fte->action);
|
||||
MLX5_SET(flow_context, in_flow_context, destination_list_size,
|
||||
fte->dests_size);
|
||||
in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
|
||||
match_value);
|
||||
memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param));
|
||||
|
||||
in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
|
||||
if (fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
|
||||
in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
|
||||
int list_size = 0;
|
||||
|
||||
list_for_each_entry(dst, &fte->node.children, node.list) {
|
||||
unsigned int id;
|
||||
|
||||
if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
|
||||
continue;
|
||||
|
||||
MLX5_SET(dest_format_struct, in_dests, destination_type,
|
||||
dst->dest_attr.type);
|
||||
if (dst->dest_attr.type ==
|
||||
@ -262,8 +265,31 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
|
||||
}
|
||||
MLX5_SET(dest_format_struct, in_dests, destination_id, id);
|
||||
in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
|
||||
list_size++;
|
||||
}
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, destination_list_size,
|
||||
list_size);
|
||||
}
|
||||
|
||||
if (fte->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
|
||||
int list_size = 0;
|
||||
|
||||
list_for_each_entry(dst, &fte->node.children, node.list) {
|
||||
if (dst->dest_attr.type !=
|
||||
MLX5_FLOW_DESTINATION_TYPE_COUNTER)
|
||||
continue;
|
||||
|
||||
MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
|
||||
dst->dest_attr.counter->id);
|
||||
in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
|
||||
list_size++;
|
||||
}
|
||||
|
||||
MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
|
||||
list_size);
|
||||
}
|
||||
|
||||
memset(out, 0, sizeof(out));
|
||||
err = mlx5_cmd_exec_check_status(dev, in, inlen, out,
|
||||
sizeof(out));
|
||||
@ -283,18 +309,16 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev,
|
||||
int mlx5_cmd_update_fte(struct mlx5_core_dev *dev,
|
||||
struct mlx5_flow_table *ft,
|
||||
unsigned group_id,
|
||||
int modify_mask,
|
||||
struct fs_fte *fte)
|
||||
{
|
||||
int opmod;
|
||||
int modify_mask;
|
||||
int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev,
|
||||
flow_table_properties_nic_receive.
|
||||
flow_modify_en);
|
||||
if (!atomic_mod_cap)
|
||||
return -ENOTSUPP;
|
||||
opmod = 1;
|
||||
modify_mask = 1 <<
|
||||
MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST;
|
||||
|
||||
return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, group_id, fte);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev,
|
||||
int mlx5_cmd_update_fte(struct mlx5_core_dev *dev,
|
||||
struct mlx5_flow_table *ft,
|
||||
unsigned group_id,
|
||||
int modify_mask,
|
||||
struct fs_fte *fte);
|
||||
|
||||
int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,
|
||||
|
@ -344,6 +344,7 @@ static void del_rule(struct fs_node *node)
|
||||
struct mlx5_flow_group *fg;
|
||||
struct fs_fte *fte;
|
||||
u32 *match_value;
|
||||
int modify_mask;
|
||||
struct mlx5_core_dev *dev = get_dev(node);
|
||||
int match_len = MLX5_ST_SZ_BYTES(fte_match_param);
|
||||
int err;
|
||||
@ -367,8 +368,11 @@ static void del_rule(struct fs_node *node)
|
||||
}
|
||||
if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
|
||||
--fte->dests_size) {
|
||||
modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST),
|
||||
err = mlx5_cmd_update_fte(dev, ft,
|
||||
fg->id, fte);
|
||||
fg->id,
|
||||
modify_mask,
|
||||
fte);
|
||||
if (err)
|
||||
pr_warn("%s can't del rule fg id=%d fte_index=%d\n",
|
||||
__func__, fg->id, fte->index);
|
||||
@ -615,6 +619,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
|
||||
struct mlx5_flow_table *ft;
|
||||
struct mlx5_flow_group *fg;
|
||||
struct fs_fte *fte;
|
||||
int modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
|
||||
int err = 0;
|
||||
|
||||
fs_get_obj(fte, rule->node.parent);
|
||||
@ -626,7 +631,9 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
|
||||
|
||||
memcpy(&rule->dest_attr, dest, sizeof(*dest));
|
||||
err = mlx5_cmd_update_fte(get_dev(&ft->node),
|
||||
ft, fg->id, fte);
|
||||
ft, fg->id,
|
||||
modify_mask,
|
||||
fte);
|
||||
unlock_ref_node(&fte->node);
|
||||
|
||||
return err;
|
||||
@ -877,6 +884,7 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte,
|
||||
{
|
||||
struct mlx5_flow_table *ft;
|
||||
struct mlx5_flow_rule *rule;
|
||||
int modify_mask = 0;
|
||||
int err;
|
||||
|
||||
rule = alloc_rule(dest);
|
||||
@ -892,14 +900,20 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte,
|
||||
list_add(&rule->node.list, &fte->node.children);
|
||||
else
|
||||
list_add_tail(&rule->node.list, &fte->node.children);
|
||||
if (dest)
|
||||
if (dest) {
|
||||
fte->dests_size++;
|
||||
|
||||
modify_mask |= dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER ?
|
||||
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS) :
|
||||
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
|
||||
}
|
||||
|
||||
if (fte->dests_size == 1 || !dest)
|
||||
err = mlx5_cmd_create_fte(get_dev(&ft->node),
|
||||
ft, fg->id, fte);
|
||||
else
|
||||
err = mlx5_cmd_update_fte(get_dev(&ft->node),
|
||||
ft, fg->id, fte);
|
||||
ft, fg->id, modify_mask, fte);
|
||||
if (err)
|
||||
goto free_rule;
|
||||
|
||||
@ -1092,10 +1106,40 @@ unlock_fg:
|
||||
return rule;
|
||||
}
|
||||
|
||||
struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule)
|
||||
{
|
||||
struct mlx5_flow_rule *dst;
|
||||
struct fs_fte *fte;
|
||||
|
||||
fs_get_obj(fte, rule->node.parent);
|
||||
|
||||
fs_for_each_dst(dst, fte) {
|
||||
if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
|
||||
return dst->dest_attr.counter;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool counter_is_valid(struct mlx5_fc *counter, u32 action)
|
||||
{
|
||||
if (!(action & MLX5_FLOW_CONTEXT_ACTION_COUNT))
|
||||
return !counter;
|
||||
|
||||
if (!counter)
|
||||
return false;
|
||||
|
||||
/* Hardware support counter for a drop action only */
|
||||
return action == (MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT);
|
||||
}
|
||||
|
||||
static bool dest_is_valid(struct mlx5_flow_destination *dest,
|
||||
u32 action,
|
||||
struct mlx5_flow_table *ft)
|
||||
{
|
||||
if (dest && (dest->type == MLX5_FLOW_DESTINATION_TYPE_COUNTER))
|
||||
return counter_is_valid(dest->counter, action);
|
||||
|
||||
if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
|
||||
return true;
|
||||
|
||||
|
@ -96,6 +96,28 @@ struct mlx5_flow_table {
|
||||
struct list_head fwd_rules;
|
||||
};
|
||||
|
||||
struct mlx5_fc_cache {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 lastuse;
|
||||
};
|
||||
|
||||
struct mlx5_fc {
|
||||
struct list_head list;
|
||||
|
||||
/* last{packets,bytes} members are used when calculating the delta since
|
||||
* last reading
|
||||
*/
|
||||
u64 lastpackets;
|
||||
u64 lastbytes;
|
||||
|
||||
u16 id;
|
||||
bool deleted;
|
||||
bool aging;
|
||||
|
||||
struct mlx5_fc_cache cache ____cacheline_aligned_in_smp;
|
||||
};
|
||||
|
||||
/* Type of children is mlx5_flow_rule */
|
||||
struct fs_fte {
|
||||
struct fs_node node;
|
||||
@ -105,6 +127,7 @@ struct fs_fte {
|
||||
u32 index;
|
||||
u32 action;
|
||||
enum fs_fte_status status;
|
||||
struct mlx5_fc *counter;
|
||||
};
|
||||
|
||||
/* Type of children is mlx5_flow_table/namespace */
|
||||
|
@ -73,6 +73,7 @@ struct mlx5_flow_destination {
|
||||
u32 tir_num;
|
||||
struct mlx5_flow_table *ft;
|
||||
u32 vport_num;
|
||||
struct mlx5_fc *counter;
|
||||
};
|
||||
};
|
||||
|
||||
@ -125,4 +126,5 @@ void mlx5_del_flow_rule(struct mlx5_flow_rule *fr);
|
||||
int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
|
||||
struct mlx5_flow_destination *dest);
|
||||
|
||||
struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule);
|
||||
#endif
|
||||
|
@ -936,6 +936,8 @@ enum mlx5_flow_destination_type {
|
||||
MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0,
|
||||
MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1,
|
||||
MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2,
|
||||
|
||||
MLX5_FLOW_DESTINATION_TYPE_COUNTER = 0x100,
|
||||
};
|
||||
|
||||
struct mlx5_ifc_dest_format_struct_bits {
|
||||
|
Loading…
Reference in New Issue
Block a user