Commit bd5251db authored by Amir Vadai's avatar Amir Vadai Committed by David S. Miller

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: default avatarAmir Vadai <amirva@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9dc0b289
...@@ -241,17 +241,20 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, ...@@ -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, group_id, group_id);
MLX5_SET(flow_context, in_flow_context, flow_tag, fte->flow_tag); 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, 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, in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
match_value); match_value);
memcpy(in_match_value, &fte->val, MLX5_ST_SZ_BYTES(fte_match_param)); 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) { 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) { list_for_each_entry(dst, &fte->node.children, node.list) {
unsigned int id; unsigned int id;
if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
continue;
MLX5_SET(dest_format_struct, in_dests, destination_type, MLX5_SET(dest_format_struct, in_dests, destination_type,
dst->dest_attr.type); dst->dest_attr.type);
if (dst->dest_attr.type == if (dst->dest_attr.type ==
...@@ -262,8 +265,31 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, ...@@ -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); MLX5_SET(dest_format_struct, in_dests, destination_id, id);
in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); 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)); memset(out, 0, sizeof(out));
err = mlx5_cmd_exec_check_status(dev, in, inlen, out, err = mlx5_cmd_exec_check_status(dev, in, inlen, out,
sizeof(out)); sizeof(out));
...@@ -283,18 +309,16 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev, ...@@ -283,18 +309,16 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev,
int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, int mlx5_cmd_update_fte(struct mlx5_core_dev *dev,
struct mlx5_flow_table *ft, struct mlx5_flow_table *ft,
unsigned group_id, unsigned group_id,
int modify_mask,
struct fs_fte *fte) struct fs_fte *fte)
{ {
int opmod; int opmod;
int modify_mask;
int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev,
flow_table_properties_nic_receive. flow_table_properties_nic_receive.
flow_modify_en); flow_modify_en);
if (!atomic_mod_cap) if (!atomic_mod_cap)
return -ENOTSUPP; return -ENOTSUPP;
opmod = 1; 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); 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, ...@@ -62,6 +62,7 @@ int mlx5_cmd_create_fte(struct mlx5_core_dev *dev,
int mlx5_cmd_update_fte(struct mlx5_core_dev *dev, int mlx5_cmd_update_fte(struct mlx5_core_dev *dev,
struct mlx5_flow_table *ft, struct mlx5_flow_table *ft,
unsigned group_id, unsigned group_id,
int modify_mask,
struct fs_fte *fte); struct fs_fte *fte);
int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,
......
...@@ -344,6 +344,7 @@ static void del_rule(struct fs_node *node) ...@@ -344,6 +344,7 @@ static void del_rule(struct fs_node *node)
struct mlx5_flow_group *fg; struct mlx5_flow_group *fg;
struct fs_fte *fte; struct fs_fte *fte;
u32 *match_value; u32 *match_value;
int modify_mask;
struct mlx5_core_dev *dev = get_dev(node); struct mlx5_core_dev *dev = get_dev(node);
int match_len = MLX5_ST_SZ_BYTES(fte_match_param); int match_len = MLX5_ST_SZ_BYTES(fte_match_param);
int err; int err;
...@@ -367,8 +368,11 @@ static void del_rule(struct fs_node *node) ...@@ -367,8 +368,11 @@ static void del_rule(struct fs_node *node)
} }
if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) && if ((fte->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
--fte->dests_size) { --fte->dests_size) {
modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST),
err = mlx5_cmd_update_fte(dev, ft, err = mlx5_cmd_update_fte(dev, ft,
fg->id, fte); fg->id,
modify_mask,
fte);
if (err) if (err)
pr_warn("%s can't del rule fg id=%d fte_index=%d\n", pr_warn("%s can't del rule fg id=%d fte_index=%d\n",
__func__, fg->id, fte->index); __func__, fg->id, fte->index);
...@@ -615,6 +619,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, ...@@ -615,6 +619,7 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
struct mlx5_flow_table *ft; struct mlx5_flow_table *ft;
struct mlx5_flow_group *fg; struct mlx5_flow_group *fg;
struct fs_fte *fte; struct fs_fte *fte;
int modify_mask = BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST);
int err = 0; int err = 0;
fs_get_obj(fte, rule->node.parent); fs_get_obj(fte, rule->node.parent);
...@@ -626,7 +631,9 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, ...@@ -626,7 +631,9 @@ int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
memcpy(&rule->dest_attr, dest, sizeof(*dest)); memcpy(&rule->dest_attr, dest, sizeof(*dest));
err = mlx5_cmd_update_fte(get_dev(&ft->node), err = mlx5_cmd_update_fte(get_dev(&ft->node),
ft, fg->id, fte); ft, fg->id,
modify_mask,
fte);
unlock_ref_node(&fte->node); unlock_ref_node(&fte->node);
return err; return err;
...@@ -877,6 +884,7 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, ...@@ -877,6 +884,7 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte,
{ {
struct mlx5_flow_table *ft; struct mlx5_flow_table *ft;
struct mlx5_flow_rule *rule; struct mlx5_flow_rule *rule;
int modify_mask = 0;
int err; int err;
rule = alloc_rule(dest); rule = alloc_rule(dest);
...@@ -892,14 +900,20 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte, ...@@ -892,14 +900,20 @@ static struct mlx5_flow_rule *add_rule_fte(struct fs_fte *fte,
list_add(&rule->node.list, &fte->node.children); list_add(&rule->node.list, &fte->node.children);
else else
list_add_tail(&rule->node.list, &fte->node.children); list_add_tail(&rule->node.list, &fte->node.children);
if (dest) if (dest) {
fte->dests_size++; 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) if (fte->dests_size == 1 || !dest)
err = mlx5_cmd_create_fte(get_dev(&ft->node), err = mlx5_cmd_create_fte(get_dev(&ft->node),
ft, fg->id, fte); ft, fg->id, fte);
else else
err = mlx5_cmd_update_fte(get_dev(&ft->node), err = mlx5_cmd_update_fte(get_dev(&ft->node),
ft, fg->id, fte); ft, fg->id, modify_mask, fte);
if (err) if (err)
goto free_rule; goto free_rule;
...@@ -1092,10 +1106,40 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg, ...@@ -1092,10 +1106,40 @@ static struct mlx5_flow_rule *add_rule_fg(struct mlx5_flow_group *fg,
return rule; 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, static bool dest_is_valid(struct mlx5_flow_destination *dest,
u32 action, u32 action,
struct mlx5_flow_table *ft) 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)) if (!(action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST))
return true; return true;
......
...@@ -96,6 +96,28 @@ struct mlx5_flow_table { ...@@ -96,6 +96,28 @@ struct mlx5_flow_table {
struct list_head fwd_rules; 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 */ /* Type of children is mlx5_flow_rule */
struct fs_fte { struct fs_fte {
struct fs_node node; struct fs_node node;
...@@ -105,6 +127,7 @@ struct fs_fte { ...@@ -105,6 +127,7 @@ struct fs_fte {
u32 index; u32 index;
u32 action; u32 action;
enum fs_fte_status status; enum fs_fte_status status;
struct mlx5_fc *counter;
}; };
/* Type of children is mlx5_flow_table/namespace */ /* Type of children is mlx5_flow_table/namespace */
......
...@@ -73,6 +73,7 @@ struct mlx5_flow_destination { ...@@ -73,6 +73,7 @@ struct mlx5_flow_destination {
u32 tir_num; u32 tir_num;
struct mlx5_flow_table *ft; struct mlx5_flow_table *ft;
u32 vport_num; u32 vport_num;
struct mlx5_fc *counter;
}; };
}; };
...@@ -125,4 +126,5 @@ void mlx5_del_flow_rule(struct mlx5_flow_rule *fr); ...@@ -125,4 +126,5 @@ void mlx5_del_flow_rule(struct mlx5_flow_rule *fr);
int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule, int mlx5_modify_rule_destination(struct mlx5_flow_rule *rule,
struct mlx5_flow_destination *dest); struct mlx5_flow_destination *dest);
struct mlx5_fc *mlx5_flow_rule_counter(struct mlx5_flow_rule *rule);
#endif #endif
...@@ -936,6 +936,8 @@ enum mlx5_flow_destination_type { ...@@ -936,6 +936,8 @@ enum mlx5_flow_destination_type {
MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0, MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0,
MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1, MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1,
MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2, MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2,
MLX5_FLOW_DESTINATION_TYPE_COUNTER = 0x100,
}; };
struct mlx5_ifc_dest_format_struct_bits { struct mlx5_ifc_dest_format_struct_bits {
......
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