Skip to content

Commit

Permalink
net/mlx5e: Hardware offloaded flower filter statistics support
Browse files Browse the repository at this point in the history
Introduce support in updating statistics of offloaded TC flower
classifiers. Currently only the DROP action is supported.

Signed-off-by: Amir Vadai <amirva@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Amir Vadai authored and David S. Miller committed May 16, 2016
1 parent 43a335e commit aad7e08
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 7 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2154,6 +2154,8 @@ static int mlx5e_ndo_setup_tc(struct net_device *dev, u32 handle,
return mlx5e_configure_flower(priv, proto, tc->cls_flower);
case TC_CLSFLOWER_DESTROY:
return mlx5e_delete_flower(priv, tc->cls_flower);
case TC_CLSFLOWER_STATS:
return mlx5e_stats_flower(priv, tc->cls_flower);
}
default:
return -EOPNOTSUPP;
Expand Down
71 changes: 64 additions & 7 deletions drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,24 @@ static struct mlx5_flow_rule *mlx5e_tc_add_flow(struct mlx5e_priv *priv,
u32 *match_c, u32 *match_v,
u32 action, u32 flow_tag)
{
struct mlx5_flow_destination dest = {
.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE,
{.ft = priv->fs.vlan.ft.t},
};
struct mlx5_core_dev *dev = priv->mdev;
struct mlx5_flow_destination dest = { 0 };
struct mlx5_fc *counter = NULL;
struct mlx5_flow_rule *rule;
bool table_created = false;

if (action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest.ft = priv->fs.vlan.ft.t;
} else {
counter = mlx5_fc_create(dev, true);
if (IS_ERR(counter))
return ERR_CAST(counter);

dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
dest.counter = counter;
}

if (IS_ERR_OR_NULL(priv->fs.tc.t)) {
priv->fs.tc.t =
mlx5_create_auto_grouped_flow_table(priv->fs.ns,
Expand All @@ -70,7 +81,8 @@ static struct mlx5_flow_rule *mlx5e_tc_add_flow(struct mlx5e_priv *priv,
if (IS_ERR(priv->fs.tc.t)) {
netdev_err(priv->netdev,
"Failed to create tc offload table\n");
return ERR_CAST(priv->fs.tc.t);
rule = ERR_CAST(priv->fs.tc.t);
goto err_create_ft;
}

table_created = true;
Expand All @@ -79,21 +91,35 @@ static struct mlx5_flow_rule *mlx5e_tc_add_flow(struct mlx5e_priv *priv,
rule = mlx5_add_flow_rule(priv->fs.tc.t, MLX5_MATCH_OUTER_HEADERS,
match_c, match_v,
action, flow_tag,
action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST ? &dest : NULL);
&dest);

if (IS_ERR(rule))
goto err_add_rule;

return rule;

if (IS_ERR(rule) && table_created) {
err_add_rule:
if (table_created) {
mlx5_destroy_flow_table(priv->fs.tc.t);
priv->fs.tc.t = NULL;
}
err_create_ft:
mlx5_fc_destroy(dev, counter);

return rule;
}

static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
struct mlx5_flow_rule *rule)
{
struct mlx5_fc *counter = NULL;

counter = mlx5_flow_rule_counter(rule);

mlx5_del_flow_rule(rule);

mlx5_fc_destroy(priv->mdev, counter);

if (!mlx5e_tc_num_filters(priv)) {
mlx5_destroy_flow_table(priv->fs.tc.t);
priv->fs.tc.t = NULL;
Expand Down Expand Up @@ -286,6 +312,9 @@ static int parse_tc_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,

if (is_tcf_gact_shot(a)) {
*action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
if (MLX5_CAP_FLOWTABLE(priv->mdev,
flow_table_properties_nic_receive.flow_counter))
*action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
continue;
}

Expand Down Expand Up @@ -394,6 +423,34 @@ int mlx5e_delete_flower(struct mlx5e_priv *priv,
return 0;
}

int mlx5e_stats_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *f)
{
struct mlx5e_tc_table *tc = &priv->fs.tc;
struct mlx5e_tc_flow *flow;
struct tc_action *a;
struct mlx5_fc *counter;
u64 bytes;
u64 packets;
u64 lastuse;

flow = rhashtable_lookup_fast(&tc->ht, &f->cookie,
tc->ht_params);
if (!flow)
return -EINVAL;

counter = mlx5_flow_rule_counter(flow->rule);
if (!counter)
return 0;

mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);

tc_for_each_action(a, f->exts)
tcf_action_stats_update(a, bytes, packets, lastuse);

return 0;
}

static const struct rhashtable_params mlx5e_tc_flow_ht_params = {
.head_offset = offsetof(struct mlx5e_tc_flow, node),
.key_offset = offsetof(struct mlx5e_tc_flow, cookie),
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, __be16 protocol,
int mlx5e_delete_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *f);

int mlx5e_stats_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *f);

static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv)
{
return atomic_read(&priv->fs.tc.ht.nelems);
Expand Down

0 comments on commit aad7e08

Please sign in to comment.