Commit 2b68d659 authored by Oz Shlomo's avatar Oz Shlomo Committed by Paolo Abeni
Browse files

net/mlx5e: TC, support per action stats



Extend the action stats callback implementation to update stats for actions
that are associated with hw counters.
Note that the callback may be called from tc action utility or from tc
flower. Both apis expect the driver to return the stats difference from
the last update. As such, query the raw counter value and maintain
the diff from the last api call in the tc layer, instead of the fs_core
layer.

Signed-off-by: default avatarOz Shlomo <ozsh@nvidia.com>
Reviewed-by: default avatarRoi Dayan <roid@nvidia.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent d13674b1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -589,7 +589,7 @@ mlx5e_rep_indr_stats_act(struct mlx5e_rep_priv *rpriv,

	act = mlx5e_tc_act_get(fl_act->id, ns_type);
	if (!act || !act->stats_action)
		return -EOPNOTSUPP;
		return mlx5e_tc_fill_action_stats(priv, fl_act);

	return act->stats_action(priv, fl_act);
}
+44 −0
Original line number Diff line number Diff line
@@ -102,6 +102,9 @@ mlx5e_tc_act_stats_del_flow(struct mlx5e_tc_act_stats_handle *handle,
	struct mlx5e_tc_act_stats *act_stats;
	int i;

	if (!flow_flag_test(flow, USE_ACT_STATS))
		return;

	list_for_each_entry(attr, &flow->attrs, list) {
		for (i = 0; i < attr->tc_act_cookies_count; i++) {
			struct rhashtable *ht = &handle->ht;
@@ -130,6 +133,9 @@ mlx5e_tc_act_stats_add_flow(struct mlx5e_tc_act_stats_handle *handle,
	int err;
	int i;

	if (!flow_flag_test(flow, USE_ACT_STATS))
		return 0;

	list_for_each_entry(attr, &flow->attrs, list) {
		if (attr->counter)
			curr_counter = attr->counter;
@@ -151,3 +157,41 @@ mlx5e_tc_act_stats_add_flow(struct mlx5e_tc_act_stats_handle *handle,
	mlx5e_tc_act_stats_del_flow(handle, flow);
	return err;
}

int
mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
			      struct flow_offload_action *fl_act)
{
	struct rhashtable *ht = &handle->ht;
	struct mlx5e_tc_act_stats *item;
	struct mlx5e_tc_act_stats key;
	u64 pkts, bytes, lastused;
	int err = 0;

	key.tc_act_cookie = fl_act->cookie;

	rcu_read_lock();
	item = rhashtable_lookup(ht, &key, act_counters_ht_params);
	if (!item) {
		rcu_read_unlock();
		err = -ENOENT;
		goto err_out;
	}

	mlx5_fc_query_cached_raw(item->counter,
				 &bytes, &pkts, &lastused);

	flow_stats_update(&fl_act->stats,
			  bytes - item->lastbytes,
			  pkts - item->lastpackets,
			  0, lastused, FLOW_ACTION_HW_STATS_DELAYED);

	item->lastpackets = pkts;
	item->lastbytes = bytes;
	rcu_read_unlock();

	return 0;

err_out:
	return err;
}
+4 −0
Original line number Diff line number Diff line
@@ -20,4 +20,8 @@ void
mlx5e_tc_act_stats_del_flow(struct mlx5e_tc_act_stats_handle *handle,
			    struct mlx5e_tc_flow *flow);

int
mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
			      struct flow_offload_action *fl_act);

#endif /* __MLX5_EN_ACT_STATS_H__ */
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ enum {
	MLX5E_TC_FLOW_FLAG_TUN_RX                = MLX5E_TC_FLOW_BASE + 9,
	MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 10,
	MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 11,
	MLX5E_TC_FLOW_FLAG_USE_ACT_STATS	 = MLX5E_TC_FLOW_BASE + 12,
};

struct mlx5e_tc_flow_parse_attr {
+27 −12
Original line number Diff line number Diff line
@@ -4117,6 +4117,7 @@ parse_branch_ctrl(struct flow_action_entry *act, struct mlx5e_tc_act *tc_act,

	/* branching action requires its own counter */
	attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
	flow_flag_set(flow, USE_ACT_STATS);

	return 0;

@@ -4967,6 +4968,12 @@ int mlx5e_delete_flower(struct net_device *dev, struct mlx5e_priv *priv,
	return err;
}

int mlx5e_tc_fill_action_stats(struct mlx5e_priv *priv,
			       struct flow_offload_action *fl_act)
{
	return mlx5e_tc_act_stats_fill_stats(get_act_stats_handle(priv), fl_act);
}

int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
		       struct flow_cls_offload *f, unsigned long flags)
{
@@ -4993,12 +5000,16 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
	}

	if (mlx5e_is_offloaded_flow(flow) || flow_flag_test(flow, CT)) {
		if (flow_flag_test(flow, USE_ACT_STATS)) {
			f->use_act_stats = true;
		} else {
			counter = mlx5e_tc_get_counter(flow);
			if (!counter)
				goto errout;

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

	/* Under multipath it's possible for one rule to be currently
	 * un-offloaded while the other rule is offloaded.
@@ -5013,6 +5024,9 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
		u64 packets2;
		u64 lastuse2;

		if (flow_flag_test(flow, USE_ACT_STATS)) {
			f->use_act_stats = true;
		} else {
			counter = mlx5e_tc_get_counter(flow->peer_flow);
			if (!counter)
				goto no_peer_counter;
@@ -5022,6 +5036,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
			packets += packets2;
			lastuse = max_t(u64, lastuse, lastuse2);
		}
	}

no_peer_counter:
	mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
Loading