diff mbox series

[net,04/11] net/mlx5e: CT: Use per flow counter when CT flow accounting is enabled

Message ID 20210107202845.470205-5-saeed@kernel.org
State New
Headers show
Series [net,01/11] net/mlx5: Check if lag is supported before creating one | expand

Commit Message

Saeed Mahameed Jan. 7, 2021, 8:28 p.m. UTC
From: Oz Shlomo <ozsh@nvidia.com>

Connection counters may be shared for both directions when the counter
is used for connection aging purposes. However, if TC flow
accounting is enabled then a unique counter is required per direction.

Instantiate a unique counter per direction if the conntrack accounting
extension is enabled. Use a shared counter when the connection accounting
extension is disabled.

Fixes: 1edae2335adf ("net/mlx5e: CT: Use the same counter for both directions")
Signed-off-by: Oz Shlomo <ozsh@nvidia.com>
Reported-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Reviewed-by: Paul Blakey <paulb@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
---
 .../ethernet/mellanox/mlx5/core/en/tc_ct.c    | 77 ++++++++++++-------
 1 file changed, 49 insertions(+), 28 deletions(-)

Comments

Marcelo Ricardo Leitner Jan. 7, 2021, 10:04 p.m. UTC | #1
On Thu, Jan 07, 2021 at 12:28:38PM -0800, Saeed Mahameed wrote:
> From: Oz Shlomo <ozsh@nvidia.com>
> 
> Connection counters may be shared for both directions when the counter
> is used for connection aging purposes. However, if TC flow
> accounting is enabled then a unique counter is required per direction.
> 
> Instantiate a unique counter per direction if the conntrack accounting
> extension is enabled. Use a shared counter when the connection accounting
> extension is disabled.
> 
> Fixes: 1edae2335adf ("net/mlx5e: CT: Use the same counter for both directions")
> Signed-off-by: Oz Shlomo <ozsh@nvidia.com>
> Reported-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

Tested-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Thanks.

> Reviewed-by: Roi Dayan <roid@nvidia.com>
> Reviewed-by: Paul Blakey <paulb@nvidia.com>
> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Jakub Kicinski Jan. 8, 2021, 3:07 a.m. UTC | #2
On Thu,  7 Jan 2021 12:28:38 -0800 Saeed Mahameed wrote:
> +	int ret;

> +

> +	counter = kzalloc(sizeof(*counter), GFP_KERNEL);

> +	if (!counter)

> +		return ERR_PTR(-ENOMEM);

> +

> +	counter->is_shared = false;

> +	counter->counter = mlx5_fc_create(ct_priv->dev, true);

> +	if (IS_ERR(counter->counter)) {

> +		ct_dbg("Failed to create counter for ct entry");

> +		ret = PTR_ERR(counter->counter);

> +		kfree(counter);

> +		return ERR_PTR(ret);


The err ptr -> ret -> err ptr conversion seems entirely pointless, no?
Saeed Mahameed Jan. 8, 2021, 4:06 a.m. UTC | #3
On Thu, 2021-01-07 at 19:07 -0800, Jakub Kicinski wrote:
> On Thu,  7 Jan 2021 12:28:38 -0800 Saeed Mahameed wrote:

> > +	int ret;

> > +

> > +	counter = kzalloc(sizeof(*counter), GFP_KERNEL);

> > +	if (!counter)

> > +		return ERR_PTR(-ENOMEM);

> > +

> > +	counter->is_shared = false;

> > +	counter->counter = mlx5_fc_create(ct_priv->dev, true);

> > +	if (IS_ERR(counter->counter)) {

> > +		ct_dbg("Failed to create counter for ct entry");

> > +		ret = PTR_ERR(counter->counter);

> > +		kfree(counter);

> > +		return ERR_PTR(ret);

> 

> The err ptr -> ret -> err ptr conversion seems entirely pointless,

> no?

Indeed, will address this in a net-next patch
Saeed Mahameed Jan. 8, 2021, 4:18 a.m. UTC | #4
On Thu, 2021-01-07 at 20:06 -0800, Saeed Mahameed wrote:
> On Thu, 2021-01-07 at 19:07 -0800, Jakub Kicinski wrote:

> > On Thu,  7 Jan 2021 12:28:38 -0800 Saeed Mahameed wrote:

> > > +	int ret;

> > > +

> > > +	counter = kzalloc(sizeof(*counter), GFP_KERNEL);

> > > +	if (!counter)

> > > +		return ERR_PTR(-ENOMEM);

> > > +

> > > +	counter->is_shared = false;

> > > +	counter->counter = mlx5_fc_create(ct_priv->dev, true);

> > > +	if (IS_ERR(counter->counter)) {

> > > +		ct_dbg("Failed to create counter for ct entry");

> > > +		ret = PTR_ERR(counter->counter);

> > > +		kfree(counter);

> > > +		return ERR_PTR(ret);

> > 

> > The err ptr -> ret -> err ptr conversion seems entirely pointless,

> > no?

> Indeed, will address this in a net-next patch

> 


Actually no, because counter is being kfreed so we must return
ERR_PTR(ret).
Jakub Kicinski Jan. 8, 2021, 4:40 a.m. UTC | #5
On Thu, 07 Jan 2021 20:18:36 -0800 Saeed Mahameed wrote:
> On Thu, 2021-01-07 at 20:06 -0800, Saeed Mahameed wrote:

> > On Thu, 2021-01-07 at 19:07 -0800, Jakub Kicinski wrote:  

> > > On Thu,  7 Jan 2021 12:28:38 -0800 Saeed Mahameed wrote:  

> > > > +	int ret;

> > > > +

> > > > +	counter = kzalloc(sizeof(*counter), GFP_KERNEL);

> > > > +	if (!counter)

> > > > +		return ERR_PTR(-ENOMEM);

> > > > +

> > > > +	counter->is_shared = false;

> > > > +	counter->counter = mlx5_fc_create(ct_priv->dev, true);

> > > > +	if (IS_ERR(counter->counter)) {

> > > > +		ct_dbg("Failed to create counter for ct entry");

> > > > +		ret = PTR_ERR(counter->counter);

> > > > +		kfree(counter);

> > > > +		return ERR_PTR(ret);  

> > > 

> > > The err ptr -> ret -> err ptr conversion seems entirely pointless,

> > > no?  

> > Indeed, will address this in a net-next patch

> >   

> 

> Actually no, because counter is being kfreed so we must return

> ERR_PTR(ret).


Ah, good point, just the other one then:

+	shared_counter = mlx5_tc_ct_counter_create(ct_priv);
+	if (IS_ERR(shared_counter)) {
+		ret = PTR_ERR(shared_counter);
 		return ERR_PTR(ret);
 	}
Saeed Mahameed Jan. 8, 2021, 4:56 a.m. UTC | #6
On Thu, 2021-01-07 at 20:40 -0800, Jakub Kicinski wrote:
> On Thu, 07 Jan 2021 20:18:36 -0800 Saeed Mahameed wrote:

> > On Thu, 2021-01-07 at 20:06 -0800, Saeed Mahameed wrote:

> > > On Thu, 2021-01-07 at 19:07 -0800, Jakub Kicinski wrote:  

> > > > On Thu,  7 Jan 2021 12:28:38 -0800 Saeed Mahameed wrote:  

> > > > > +	int ret;

> > > > > +

> > > > > +	counter = kzalloc(sizeof(*counter), GFP_KERNEL);

> > > > > +	if (!counter)

> > > > > +		return ERR_PTR(-ENOMEM);

> > > > > +

> > > > > +	counter->is_shared = false;

> > > > > +	counter->counter = mlx5_fc_create(ct_priv->dev, true);

> > > > > +	if (IS_ERR(counter->counter)) {

> > > > > +		ct_dbg("Failed to create counter for ct

> > > > > entry");

> > > > > +		ret = PTR_ERR(counter->counter);

> > > > > +		kfree(counter);

> > > > > +		return ERR_PTR(ret);  

> > > > 

> > > > The err ptr -> ret -> err ptr conversion seems entirely

> > > > pointless,

> > > > no?  

> > > Indeed, will address this in a net-next patch

> > >   

> > 

> > Actually no, because counter is being kfreed so we must return

> > ERR_PTR(ret).

> 

> Ah, good point, just the other one then:

> 

> +	shared_counter = mlx5_tc_ct_counter_create(ct_priv);

> +	if (IS_ERR(shared_counter)) {

> +		ret = PTR_ERR(shared_counter);

>  		return ERR_PTR(ret);

>  	}

Done, will send to net-next once this is back merged.

Thanks.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
index e521254d886e..072363e73f1c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
@@ -118,16 +118,17 @@  struct mlx5_ct_tuple {
 	u16 zone;
 };
 
-struct mlx5_ct_shared_counter {
+struct mlx5_ct_counter {
 	struct mlx5_fc *counter;
 	refcount_t refcount;
+	bool is_shared;
 };
 
 struct mlx5_ct_entry {
 	struct rhash_head node;
 	struct rhash_head tuple_node;
 	struct rhash_head tuple_nat_node;
-	struct mlx5_ct_shared_counter *shared_counter;
+	struct mlx5_ct_counter *counter;
 	unsigned long cookie;
 	unsigned long restore_cookie;
 	struct mlx5_ct_tuple tuple;
@@ -394,13 +395,14 @@  mlx5_tc_ct_set_tuple_match(struct mlx5e_priv *priv, struct mlx5_flow_spec *spec,
 }
 
 static void
-mlx5_tc_ct_shared_counter_put(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_entry *entry)
+mlx5_tc_ct_counter_put(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_entry *entry)
 {
-	if (!refcount_dec_and_test(&entry->shared_counter->refcount))
+	if (entry->counter->is_shared &&
+	    !refcount_dec_and_test(&entry->counter->refcount))
 		return;
 
-	mlx5_fc_destroy(ct_priv->dev, entry->shared_counter->counter);
-	kfree(entry->shared_counter);
+	mlx5_fc_destroy(ct_priv->dev, entry->counter->counter);
+	kfree(entry->counter);
 }
 
 static void
@@ -699,7 +701,7 @@  mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
 	attr->dest_ft = ct_priv->post_ct;
 	attr->ft = nat ? ct_priv->ct_nat : ct_priv->ct;
 	attr->outer_match_level = MLX5_MATCH_L4;
-	attr->counter = entry->shared_counter->counter;
+	attr->counter = entry->counter->counter;
 	attr->flags |= MLX5_ESW_ATTR_FLAG_NO_IN_PORT;
 
 	mlx5_tc_ct_set_tuple_match(netdev_priv(ct_priv->netdev), spec, flow_rule);
@@ -732,13 +734,34 @@  mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
 	return err;
 }
 
-static struct mlx5_ct_shared_counter *
+static struct mlx5_ct_counter *
+mlx5_tc_ct_counter_create(struct mlx5_tc_ct_priv *ct_priv)
+{
+	struct mlx5_ct_counter *counter;
+	int ret;
+
+	counter = kzalloc(sizeof(*counter), GFP_KERNEL);
+	if (!counter)
+		return ERR_PTR(-ENOMEM);
+
+	counter->is_shared = false;
+	counter->counter = mlx5_fc_create(ct_priv->dev, true);
+	if (IS_ERR(counter->counter)) {
+		ct_dbg("Failed to create counter for ct entry");
+		ret = PTR_ERR(counter->counter);
+		kfree(counter);
+		return ERR_PTR(ret);
+	}
+
+	return counter;
+}
+
+static struct mlx5_ct_counter *
 mlx5_tc_ct_shared_counter_get(struct mlx5_tc_ct_priv *ct_priv,
 			      struct mlx5_ct_entry *entry)
 {
 	struct mlx5_ct_tuple rev_tuple = entry->tuple;
-	struct mlx5_ct_shared_counter *shared_counter;
-	struct mlx5_core_dev *dev = ct_priv->dev;
+	struct mlx5_ct_counter *shared_counter;
 	struct mlx5_ct_entry *rev_entry;
 	__be16 tmp_port;
 	int ret;
@@ -767,25 +790,20 @@  mlx5_tc_ct_shared_counter_get(struct mlx5_tc_ct_priv *ct_priv,
 	rev_entry = rhashtable_lookup_fast(&ct_priv->ct_tuples_ht, &rev_tuple,
 					   tuples_ht_params);
 	if (rev_entry) {
-		if (refcount_inc_not_zero(&rev_entry->shared_counter->refcount)) {
+		if (refcount_inc_not_zero(&rev_entry->counter->refcount)) {
 			mutex_unlock(&ct_priv->shared_counter_lock);
-			return rev_entry->shared_counter;
+			return rev_entry->counter;
 		}
 	}
 	mutex_unlock(&ct_priv->shared_counter_lock);
 
-	shared_counter = kzalloc(sizeof(*shared_counter), GFP_KERNEL);
-	if (!shared_counter)
-		return ERR_PTR(-ENOMEM);
-
-	shared_counter->counter = mlx5_fc_create(dev, true);
-	if (IS_ERR(shared_counter->counter)) {
-		ct_dbg("Failed to create counter for ct entry");
-		ret = PTR_ERR(shared_counter->counter);
-		kfree(shared_counter);
+	shared_counter = mlx5_tc_ct_counter_create(ct_priv);
+	if (IS_ERR(shared_counter)) {
+		ret = PTR_ERR(shared_counter);
 		return ERR_PTR(ret);
 	}
 
+	shared_counter->is_shared = true;
 	refcount_set(&shared_counter->refcount, 1);
 	return shared_counter;
 }
@@ -798,10 +816,13 @@  mlx5_tc_ct_entry_add_rules(struct mlx5_tc_ct_priv *ct_priv,
 {
 	int err;
 
-	entry->shared_counter = mlx5_tc_ct_shared_counter_get(ct_priv, entry);
-	if (IS_ERR(entry->shared_counter)) {
-		err = PTR_ERR(entry->shared_counter);
-		ct_dbg("Failed to create counter for ct entry");
+	if (nf_ct_acct_enabled(dev_net(ct_priv->netdev)))
+		entry->counter = mlx5_tc_ct_counter_create(ct_priv);
+	else
+		entry->counter = mlx5_tc_ct_shared_counter_get(ct_priv, entry);
+
+	if (IS_ERR(entry->counter)) {
+		err = PTR_ERR(entry->counter);
 		return err;
 	}
 
@@ -820,7 +841,7 @@  mlx5_tc_ct_entry_add_rules(struct mlx5_tc_ct_priv *ct_priv,
 err_nat:
 	mlx5_tc_ct_entry_del_rule(ct_priv, entry, false);
 err_orig:
-	mlx5_tc_ct_shared_counter_put(ct_priv, entry);
+	mlx5_tc_ct_counter_put(ct_priv, entry);
 	return err;
 }
 
@@ -918,7 +939,7 @@  mlx5_tc_ct_del_ft_entry(struct mlx5_tc_ct_priv *ct_priv,
 	rhashtable_remove_fast(&ct_priv->ct_tuples_ht, &entry->tuple_node,
 			       tuples_ht_params);
 	mutex_unlock(&ct_priv->shared_counter_lock);
-	mlx5_tc_ct_shared_counter_put(ct_priv, entry);
+	mlx5_tc_ct_counter_put(ct_priv, entry);
 
 }
 
@@ -956,7 +977,7 @@  mlx5_tc_ct_block_flow_offload_stats(struct mlx5_ct_ft *ft,
 	if (!entry)
 		return -ENOENT;
 
-	mlx5_fc_query_cached(entry->shared_counter->counter, &bytes, &packets, &lastuse);
+	mlx5_fc_query_cached(entry->counter->counter, &bytes, &packets, &lastuse);
 	flow_stats_update(&f->stats, bytes, packets, 0, lastuse,
 			  FLOW_ACTION_HW_STATS_DELAYED);