Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b96c22c0 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tc_action-fixes'



Cong Wang says:

====================
net_sched: tc action fixes and updates

This patchset fixes a few regressions caused by the previous
code refactor and more. Thanks to Jamal for catching them!

Note, patch 3/7 and 4/7 are not strictly necessary for this patchset,
I just want to carry them together.

---
v4: adjust an indention for Jamal
    add two more patches

v3: avoid list for fast path, suggested by Jamal

v2: replace flex_array with regular dynamic array
    keep tcf_action_stats_update() in act_api.h
    fix macro typos found by Amir
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f4abf05f b5ac8518
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -8396,12 +8396,14 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter,
			    struct tcf_exts *exts, u64 *action, u8 *queue)
{
	const struct tc_action *a;
	LIST_HEAD(actions);
	int err;

	if (tc_no_actions(exts))
		return -EINVAL;

	tc_for_each_action(a, exts) {
	tcf_exts_to_list(exts, &actions);
	list_for_each_entry(a, &actions, list) {

		/* Drop action */
		if (is_tcf_gact_shot(a)) {
+9 −3
Original line number Diff line number Diff line
@@ -318,6 +318,7 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
				u32 *action, u32 *flow_tag)
{
	const struct tc_action *a;
	LIST_HEAD(actions);

	if (tc_no_actions(exts))
		return -EINVAL;
@@ -325,7 +326,8 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
	*flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
	*action = 0;

	tc_for_each_action(a, exts) {
	tcf_exts_to_list(exts, &actions);
	list_for_each_entry(a, &actions, list) {
		/* Only support a single action per rule */
		if (*action)
			return -EINVAL;
@@ -362,13 +364,15 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
				u32 *action, u32 *dest_vport)
{
	const struct tc_action *a;
	LIST_HEAD(actions);

	if (tc_no_actions(exts))
		return -EINVAL;

	*action = 0;

	tc_for_each_action(a, exts) {
	tcf_exts_to_list(exts, &actions);
	list_for_each_entry(a, &actions, list) {
		/* Only support a single action per rule */
		if (*action)
			return -EINVAL;
@@ -503,6 +507,7 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
	struct mlx5e_tc_flow *flow;
	struct tc_action *a;
	struct mlx5_fc *counter;
	LIST_HEAD(actions);
	u64 bytes;
	u64 packets;
	u64 lastuse;
@@ -518,7 +523,8 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,

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

	tc_for_each_action(a, f->exts)
	tcf_exts_to_list(f->exts, &actions);
	list_for_each_entry(a, &actions, list)
		tcf_action_stats_update(a, bytes, packets, lastuse);

	return 0;
+3 −1
Original line number Diff line number Diff line
@@ -1121,6 +1121,7 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
					  bool ingress)
{
	const struct tc_action *a;
	LIST_HEAD(actions);
	int err;

	if (!tc_single_action(cls->exts)) {
@@ -1128,7 +1129,8 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
		return -ENOTSUPP;
	}

	tc_for_each_action(a, cls->exts) {
	tcf_exts_to_list(cls->exts, &actions);
	list_for_each_entry(a, &actions, list) {
		if (!is_tcf_mirred_mirror(a) || protocol != htons(ETH_P_ALL))
			return -ENOTSUPP;

+5 −18
Original line number Diff line number Diff line
@@ -176,8 +176,8 @@ int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
int tcf_unregister_action(struct tc_action_ops *a,
			  struct pernet_operations *ops);
int tcf_action_destroy(struct list_head *actions, int bind);
int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,
		    struct tcf_result *res);
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
		    int nr_actions, struct tcf_result *res);
int tcf_action_init(struct net *net, struct nlattr *nla,
				  struct nlattr *est, char *n, int ovr,
				  int bind, struct list_head *);
@@ -189,30 +189,17 @@ int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);

#define tc_no_actions(_exts) \
	(list_empty(&(_exts)->actions))

#define tc_for_each_action(_a, _exts) \
	list_for_each_entry(a, &(_exts)->actions, list)

#define tc_single_action(_exts) \
	(list_is_singular(&(_exts)->actions))
#endif /* CONFIG_NET_CLS_ACT */

static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,
					   u64 packets, u64 lastuse)
{
#ifdef CONFIG_NET_CLS_ACT
	if (!a->ops->stats_update)
		return;

	a->ops->stats_update(a, bytes, packets, lastuse);
#endif
}

#else /* CONFIG_NET_CLS_ACT */

#define tc_no_actions(_exts) true
#define tc_for_each_action(_a, _exts) while ((void)(_a), 0)
#define tc_single_action(_exts) false
#define tcf_action_stats_update(a, bytes, packets, lastuse)

#endif /* CONFIG_NET_CLS_ACT */
#endif
+36 −5
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
struct tcf_exts {
#ifdef CONFIG_NET_CLS_ACT
	__u32	type; /* for backward compat(TCA_OLD_COMPAT) */
	struct list_head actions;
	int nr_actions;
	struct tc_action **actions;
#endif
	/* Map to export classifier specific extension TLV types to the
	 * generic extensions API. Unsupported extensions must be set to 0.
@@ -72,7 +73,10 @@ static inline void tcf_exts_init(struct tcf_exts *exts, int action, int police)
{
#ifdef CONFIG_NET_CLS_ACT
	exts->type = 0;
	INIT_LIST_HEAD(&exts->actions);
	exts->nr_actions = 0;
	exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
				GFP_KERNEL);
	WARN_ON(!exts->actions); /* TODO: propagate the error to callers */
#endif
	exts->action = action;
	exts->police = police;
@@ -89,7 +93,7 @@ static inline int
tcf_exts_is_predicative(struct tcf_exts *exts)
{
#ifdef CONFIG_NET_CLS_ACT
	return !list_empty(&exts->actions);
	return exts->nr_actions;
#else
	return 0;
#endif
@@ -108,6 +112,20 @@ tcf_exts_is_available(struct tcf_exts *exts)
	return tcf_exts_is_predicative(exts);
}

static inline void tcf_exts_to_list(const struct tcf_exts *exts,
				    struct list_head *actions)
{
#ifdef CONFIG_NET_CLS_ACT
	int i;

	for (i = 0; i < exts->nr_actions; i++) {
		struct tc_action *a = exts->actions[i];

		list_add(&a->list, actions);
	}
#endif
}

/**
 * tcf_exts_exec - execute tc filter extensions
 * @skb: socket buffer
@@ -124,12 +142,25 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
	       struct tcf_result *res)
{
#ifdef CONFIG_NET_CLS_ACT
	if (!list_empty(&exts->actions))
		return tcf_action_exec(skb, &exts->actions, res);
	if (exts->nr_actions)
		return tcf_action_exec(skb, exts->actions, exts->nr_actions,
				       res);
#endif
	return 0;
}

#ifdef CONFIG_NET_CLS_ACT

#define tc_no_actions(_exts)  ((_exts)->nr_actions == 0)
#define tc_single_action(_exts) ((_exts)->nr_actions == 1)

#else /* CONFIG_NET_CLS_ACT */

#define tc_no_actions(_exts) true
#define tc_single_action(_exts) false

#endif /* CONFIG_NET_CLS_ACT */

int tcf_exts_validate(struct net *net, struct tcf_proto *tp,
		      struct nlattr **tb, struct nlattr *rate_tlv,
		      struct tcf_exts *exts, bool ovr);
Loading