All of lore.kernel.org
 help / color / mirror / Atom feed
* [Patch net v4 0/7] net_sched: tc action fixes and updates
@ 2016-08-14  5:34 Cong Wang
  2016-08-14  5:34 ` [Patch net v4 1/7] net_sched: remove the leftover cleanup_a() Cong Wang
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:34 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang

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

Cong Wang (7):
  net_sched: remove the leftover cleanup_a()
  net_sched: remove an unnecessary list_del()
  net_sched: fix a typo in tc_for_each_action()
  net_sched: move tc offload macros to pkt_cls.h
  net_sched: convert tcf_exts from list to pointer array
  net_sched: unify the init logic for act_police
  net_sched: allow flushing tc police actions

 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c   |  4 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 12 +++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c  |  4 +-
 include/net/act_api.h                           | 23 ++-------
 include/net/pkt_cls.h                           | 41 ++++++++++++++--
 net/sched/act_api.c                             | 34 ++++----------
 net/sched/act_police.c                          | 62 +++++--------------------
 net/sched/cls_api.c                             | 51 ++++++++++++++------
 8 files changed, 112 insertions(+), 119 deletions(-)

-- 
1.8.4.5

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Patch net v4 1/7] net_sched: remove the leftover cleanup_a()
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
@ 2016-08-14  5:34 ` Cong Wang
  2016-08-14 11:01   ` Jamal Hadi Salim
  2016-08-14  5:34 ` [Patch net v4 2/7] net_sched: remove an unnecessary list_del() Cong Wang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:34 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang

After refactoring tc_action into tcf_common, we no
longer need to cleanup temporary "actions" in list,
they are permanently stored in the hashtable.

Fixes: a85a970af265 ("net_sched: move tc_action into tcf_common")
Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/sched/act_api.c | 22 +++-------------------
 1 file changed, 3 insertions(+), 19 deletions(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index e4a5f26..cce6986 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -754,16 +754,6 @@ err_out:
 	return ERR_PTR(err);
 }
 
-static void cleanup_a(struct list_head *actions)
-{
-	struct tc_action *a, *tmp;
-
-	list_for_each_entry_safe(a, tmp, actions, list) {
-		list_del(&a->list);
-		kfree(a);
-	}
-}
-
 static int tca_action_flush(struct net *net, struct nlattr *nla,
 			    struct nlmsghdr *n, u32 portid)
 {
@@ -905,7 +895,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 		return ret;
 	}
 err:
-	cleanup_a(&actions);
+	tcf_action_destroy(&actions, 0);
 	return ret;
 }
 
@@ -942,15 +932,9 @@ tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 
 	ret = tcf_action_init(net, nla, NULL, NULL, ovr, 0, &actions);
 	if (ret)
-		goto done;
+		return ret;
 
-	/* dump then free all the actions after update; inserted policy
-	 * stays intact
-	 */
-	ret = tcf_add_notify(net, n, &actions, portid);
-	cleanup_a(&actions);
-done:
-	return ret;
+	return tcf_add_notify(net, n, &actions, portid);
 }
 
 static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n)
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Patch net v4 2/7] net_sched: remove an unnecessary list_del()
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
  2016-08-14  5:34 ` [Patch net v4 1/7] net_sched: remove the leftover cleanup_a() Cong Wang
@ 2016-08-14  5:34 ` Cong Wang
  2016-08-14 11:01   ` Jamal Hadi Salim
  2016-08-14  5:34 ` [Patch net v4 3/7] net_sched: fix a typo in tc_for_each_action() Cong Wang
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:34 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang

This list_del() for tc action is not needed actually,
because we only use this list to chain bulk operations,
therefore should not be carried for latter operations.

Fixes: ec0595cc4495 ("net_sched: get rid of struct tcf_common")
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/sched/act_api.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index cce6986..b4c7be3 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -64,7 +64,6 @@ int __tcf_hash_release(struct tc_action *p, bool bind, bool strict)
 		if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
 			if (p->ops->cleanup)
 				p->ops->cleanup(p, bind);
-			list_del(&p->list);
 			tcf_hash_destroy(p->hinfo, p);
 			ret = ACT_P_DELETED;
 		}
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Patch net v4 3/7] net_sched: fix a typo in tc_for_each_action()
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
  2016-08-14  5:34 ` [Patch net v4 1/7] net_sched: remove the leftover cleanup_a() Cong Wang
  2016-08-14  5:34 ` [Patch net v4 2/7] net_sched: remove an unnecessary list_del() Cong Wang
@ 2016-08-14  5:34 ` Cong Wang
  2016-08-14 11:02   ` Jamal Hadi Salim
  2016-08-14  5:34 ` [Patch net v4 4/7] net_sched: move tc offload macros to pkt_cls.h Cong Wang
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:34 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang, Amir Vadai

It is harmless because all users pass 'a' to this macro.

Fixes: 00175aec941e ("net/sched: Macro instead of CONFIG_NET_CLS_ACT ifdef")
Cc: Amir Vadai <amir@vadai.me>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 include/net/act_api.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index 41e6a24..f53ee9d 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -193,7 +193,7 @@ int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);
 	(list_empty(&(_exts)->actions))
 
 #define tc_for_each_action(_a, _exts) \
-	list_for_each_entry(a, &(_exts)->actions, list)
+	list_for_each_entry(_a, &(_exts)->actions, list)
 
 #define tc_single_action(_exts) \
 	(list_is_singular(&(_exts)->actions))
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Patch net v4 4/7] net_sched: move tc offload macros to pkt_cls.h
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
                   ` (2 preceding siblings ...)
  2016-08-14  5:34 ` [Patch net v4 3/7] net_sched: fix a typo in tc_for_each_action() Cong Wang
@ 2016-08-14  5:34 ` Cong Wang
  2016-08-14 11:03   ` Jamal Hadi Salim
  2016-08-14  5:35 ` [Patch net v4 5/7] net_sched: convert tcf_exts from list to pointer array Cong Wang
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:34 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang, Ido Schimmel

struct tcf_exts belongs to filters, should not be visible
to plain tc actions.

Cc: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 include/net/act_api.h | 19 +++----------------
 include/net/pkt_cls.h | 19 +++++++++++++++++++
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/include/net/act_api.h b/include/net/act_api.h
index f53ee9d..870332f 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -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
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 6f8d653..00dd5c4 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -130,6 +130,25 @@ tcf_exts_exec(struct sk_buff *skb, struct tcf_exts *exts,
 	return 0;
 }
 
+#ifdef CONFIG_NET_CLS_ACT
+
+#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))
+
+#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
+
+#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);
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Patch net v4 5/7] net_sched: convert tcf_exts from list to pointer array
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
                   ` (3 preceding siblings ...)
  2016-08-14  5:34 ` [Patch net v4 4/7] net_sched: move tc offload macros to pkt_cls.h Cong Wang
@ 2016-08-14  5:35 ` Cong Wang
  2016-08-14 11:04   ` Jamal Hadi Salim
  2016-08-14  5:35 ` [Patch net v4 6/7] net_sched: unify the init logic for act_police Cong Wang
  2016-08-14  5:35 ` [Patch net v4 7/7] net_sched: allow flushing tc police actions Cong Wang
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:35 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang

As pointed out by Jamal, an action could be shared by
multiple filters, so we can't use list to chain them
any more after we get rid of the original tc_action.
Instead, we could just save pointers to these actions
in tcf_exts, since they are refcount'ed, so convert
the list to an array of pointers.

The "ugly" part is the action API still accepts list
as a parameter, I just introduce a helper function to
convert the array of pointers to a list, instead of
relying on the C99 feature to iterate the array.

Fixes: a85a970af265 ("net_sched: move tc_action into tcf_common")
Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 drivers/net/ethernet/intel/ixgbe/ixgbe_main.c   |  4 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 12 ++++--
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c  |  4 +-
 include/net/act_api.h                           |  4 +-
 include/net/pkt_cls.h                           | 40 ++++++++++++-------
 net/sched/act_api.c                             | 11 +++---
 net/sched/cls_api.c                             | 51 +++++++++++++++++--------
 7 files changed, 85 insertions(+), 41 deletions(-)

diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 5418c69a..6ac1254 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8390,12 +8390,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)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 0f19b01..dc8b1cb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -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;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index e1b8f62..9130cb2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1149,6 +1149,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)) {
@@ -1156,7 +1157,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;
 
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 870332f..82f3c91 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -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 *);
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 00dd5c4..c99508d 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -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,27 +142,21 @@ 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) \
-	(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))
+#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_for_each_action(_a, _exts) while ((void)(_a), 0)
 #define tc_single_action(_exts) false
 
 #endif /* CONFIG_NET_CLS_ACT */
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index b4c7be3..d09d068 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -420,18 +420,19 @@ static struct tc_action_ops *tc_lookup_action(struct nlattr *kind)
 	return res;
 }
 
-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)
 {
-	const struct tc_action *a;
-	int ret = -1;
+	int ret = -1, i;
 
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
 		ret = TC_ACT_OK;
 		goto exec_done;
 	}
-	list_for_each_entry(a, actions, list) {
+	for (i = 0; i < nr_actions; i++) {
+		const struct tc_action *a = actions[i];
+
 repeat:
 		ret = a->ops->act(skb, a, res);
 		if (ret == TC_ACT_REPEAT)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 843a716..a7c5645 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -541,8 +541,12 @@ out:
 void tcf_exts_destroy(struct tcf_exts *exts)
 {
 #ifdef CONFIG_NET_CLS_ACT
-	tcf_action_destroy(&exts->actions, TCA_ACT_UNBIND);
-	INIT_LIST_HEAD(&exts->actions);
+	LIST_HEAD(actions);
+
+	tcf_exts_to_list(exts, &actions);
+	tcf_action_destroy(&actions, TCA_ACT_UNBIND);
+	kfree(exts->actions);
+	exts->nr_actions = 0;
 #endif
 }
 EXPORT_SYMBOL(tcf_exts_destroy);
@@ -554,7 +558,6 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
 	{
 		struct tc_action *act;
 
-		INIT_LIST_HEAD(&exts->actions);
 		if (exts->police && tb[exts->police]) {
 			act = tcf_action_init_1(net, tb[exts->police], rate_tlv,
 						"police", ovr,
@@ -563,14 +566,20 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb,
 				return PTR_ERR(act);
 
 			act->type = exts->type = TCA_OLD_COMPAT;
-			list_add(&act->list, &exts->actions);
+			exts->actions[0] = act;
+			exts->nr_actions = 1;
 		} else if (exts->action && tb[exts->action]) {
-			int err;
+			LIST_HEAD(actions);
+			int err, i = 0;
+
 			err = tcf_action_init(net, tb[exts->action], rate_tlv,
 					      NULL, ovr,
-					      TCA_ACT_BIND, &exts->actions);
+					      TCA_ACT_BIND, &actions);
 			if (err)
 				return err;
+			list_for_each_entry(act, &actions, list)
+				exts->actions[i++] = act;
+			exts->nr_actions = i;
 		}
 	}
 #else
@@ -587,37 +596,49 @@ void tcf_exts_change(struct tcf_proto *tp, struct tcf_exts *dst,
 		     struct tcf_exts *src)
 {
 #ifdef CONFIG_NET_CLS_ACT
-	LIST_HEAD(tmp);
+	struct tcf_exts old = *dst;
+
 	tcf_tree_lock(tp);
-	list_splice_init(&dst->actions, &tmp);
-	list_splice(&src->actions, &dst->actions);
+	dst->nr_actions = src->nr_actions;
+	dst->actions = src->actions;
 	dst->type = src->type;
 	tcf_tree_unlock(tp);
-	tcf_action_destroy(&tmp, TCA_ACT_UNBIND);
+
+	tcf_exts_destroy(&old);
 #endif
 }
 EXPORT_SYMBOL(tcf_exts_change);
 
-#define tcf_exts_first_act(ext)					\
-	list_first_entry_or_null(&(exts)->actions,		\
-				 struct tc_action, list)
+#ifdef CONFIG_NET_CLS_ACT
+static struct tc_action *tcf_exts_first_act(struct tcf_exts *exts)
+{
+	if (exts->nr_actions == 0)
+		return NULL;
+	else
+		return exts->actions[0];
+}
+#endif
 
 int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts)
 {
 #ifdef CONFIG_NET_CLS_ACT
 	struct nlattr *nest;
 
-	if (exts->action && !list_empty(&exts->actions)) {
+	if (exts->action && exts->nr_actions) {
 		/*
 		 * again for backward compatible mode - we want
 		 * to work with both old and new modes of entering
 		 * tc data even if iproute2  was newer - jhs
 		 */
 		if (exts->type != TCA_OLD_COMPAT) {
+			LIST_HEAD(actions);
+
 			nest = nla_nest_start(skb, exts->action);
 			if (nest == NULL)
 				goto nla_put_failure;
-			if (tcf_action_dump(skb, &exts->actions, 0, 0) < 0)
+
+			tcf_exts_to_list(exts, &actions);
+			if (tcf_action_dump(skb, &actions, 0, 0) < 0)
 				goto nla_put_failure;
 			nla_nest_end(skb, nest);
 		} else if (exts->police) {
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Patch net v4 6/7] net_sched: unify the init logic for act_police
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
                   ` (4 preceding siblings ...)
  2016-08-14  5:35 ` [Patch net v4 5/7] net_sched: convert tcf_exts from list to pointer array Cong Wang
@ 2016-08-14  5:35 ` Cong Wang
  2016-08-14 11:04   ` Jamal Hadi Salim
  2016-08-14  5:35 ` [Patch net v4 7/7] net_sched: allow flushing tc police actions Cong Wang
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:35 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang

Jamal reported a crash when we create a police action
with a specific index, this is because the init logic
is not correct, we should always create one for this
case. Just unify the logic with other tc actions.

Fixes: a03e6fe56971 ("act_police: fix a crash during removal")
Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/sched/act_police.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index b3c7e97..259352d 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -125,6 +125,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
 	struct tcf_police *police;
 	struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
 	struct tc_action_net *tn = net_generic(net, police_net_id);
+	bool exists = false;
 	int size;
 
 	if (nla == NULL)
@@ -139,24 +140,24 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
 	size = nla_len(tb[TCA_POLICE_TBF]);
 	if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
 		return -EINVAL;
+
 	parm = nla_data(tb[TCA_POLICE_TBF]);
+	exists = tcf_hash_check(tn, parm->index, a, bind);
+	if (exists && bind)
+		return 0;
 
-	if (parm->index) {
-		if (tcf_hash_check(tn, parm->index, a, bind)) {
-			if (ovr)
-				goto override;
-			/* not replacing */
-			return -EEXIST;
-		}
-	} else {
+	if (!exists) {
 		ret = tcf_hash_create(tn, parm->index, NULL, a,
 				      &act_police_ops, bind, false);
 		if (ret)
 			return ret;
 		ret = ACT_P_CREATED;
+	} else {
+		tcf_hash_release(*a, bind);
+		if (!ovr)
+			return -EEXIST;
 	}
 
-override:
 	police = to_police(*a);
 	if (parm->rate.rate) {
 		err = -ENOMEM;
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [Patch net v4 7/7] net_sched: allow flushing tc police actions
  2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
                   ` (5 preceding siblings ...)
  2016-08-14  5:35 ` [Patch net v4 6/7] net_sched: unify the init logic for act_police Cong Wang
@ 2016-08-14  5:35 ` Cong Wang
  2016-08-14 11:05   ` Jamal Hadi Salim
  6 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2016-08-14  5:35 UTC (permalink / raw)
  To: netdev; +Cc: jhs, Cong Wang, Roman Mashak

From: Roman Mashak <mrv@mojatatu.com>

The act_police uses its own code to walk the
action hashtable, which leads to that we could
not flush standalone tc police actions, so just
switch to tcf_generic_walker() like other actions.

(Joint work from Roman and Cong.)

Signed-off-by: Roman Mashak <mrv@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/sched/act_police.c | 43 +------------------------------------------
 1 file changed, 1 insertion(+), 42 deletions(-)

diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 259352d..8a3be1d 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -63,49 +63,8 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
 				 const struct tc_action_ops *ops)
 {
 	struct tc_action_net *tn = net_generic(net, police_net_id);
-	struct tcf_hashinfo *hinfo = tn->hinfo;
-	int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
-	struct nlattr *nest;
-
-	spin_lock_bh(&hinfo->lock);
-
-	s_i = cb->args[0];
-
-	for (i = 0; i < (POL_TAB_MASK + 1); i++) {
-		struct hlist_head *head;
-		struct tc_action *p;
-
-		head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)];
-
-		hlist_for_each_entry_rcu(p, head, tcfa_head) {
-			index++;
-			if (index < s_i)
-				continue;
-			nest = nla_nest_start(skb, index);
-			if (nest == NULL)
-				goto nla_put_failure;
-			if (type == RTM_DELACTION)
-				err = tcf_action_dump_1(skb, p, 0, 1);
-			else
-				err = tcf_action_dump_1(skb, p, 0, 0);
-			if (err < 0) {
-				index--;
-				nla_nest_cancel(skb, nest);
-				goto done;
-			}
-			nla_nest_end(skb, nest);
-			n_i++;
-		}
-	}
-done:
-	spin_unlock_bh(&hinfo->lock);
-	if (n_i)
-		cb->args[0] += n_i;
-	return n_i;
 
-nla_put_failure:
-	nla_nest_cancel(skb, nest);
-	goto done;
+	return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
 static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
-- 
1.8.4.5

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 1/7] net_sched: remove the leftover cleanup_a()
  2016-08-14  5:34 ` [Patch net v4 1/7] net_sched: remove the leftover cleanup_a() Cong Wang
@ 2016-08-14 11:01   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:01 UTC (permalink / raw)
  To: Cong Wang, netdev

On 16-08-14 01:34 AM, Cong Wang wrote:
> After refactoring tc_action into tcf_common, we no
> longer need to cleanup temporary "actions" in list,
> they are permanently stored in the hashtable.
>
> Fixes: a85a970af265 ("net_sched: move tc_action into tcf_common")
> Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

acked-by: Jamal Hadi Salim <jhs@mojatatu.com>


cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 2/7] net_sched: remove an unnecessary list_del()
  2016-08-14  5:34 ` [Patch net v4 2/7] net_sched: remove an unnecessary list_del() Cong Wang
@ 2016-08-14 11:01   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:01 UTC (permalink / raw)
  To: Cong Wang, netdev

On 16-08-14 01:34 AM, Cong Wang wrote:
> This list_del() for tc action is not needed actually,
> because we only use this list to chain bulk operations,
> therefore should not be carried for latter operations.
>
> Fixes: ec0595cc4495 ("net_sched: get rid of struct tcf_common")
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 3/7] net_sched: fix a typo in tc_for_each_action()
  2016-08-14  5:34 ` [Patch net v4 3/7] net_sched: fix a typo in tc_for_each_action() Cong Wang
@ 2016-08-14 11:02   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:02 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: Amir Vadai

On 16-08-14 01:34 AM, Cong Wang wrote:
> It is harmless because all users pass 'a' to this macro.
>
> Fixes: 00175aec941e ("net/sched: Macro instead of CONFIG_NET_CLS_ACT ifdef")
> Cc: Amir Vadai <amir@vadai.me>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 4/7] net_sched: move tc offload macros to pkt_cls.h
  2016-08-14  5:34 ` [Patch net v4 4/7] net_sched: move tc offload macros to pkt_cls.h Cong Wang
@ 2016-08-14 11:03   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:03 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: Ido Schimmel

On 16-08-14 01:34 AM, Cong Wang wrote:
> struct tcf_exts belongs to filters, should not be visible
> to plain tc actions.
>
> Cc: Ido Schimmel <idosch@mellanox.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 5/7] net_sched: convert tcf_exts from list to pointer array
  2016-08-14  5:35 ` [Patch net v4 5/7] net_sched: convert tcf_exts from list to pointer array Cong Wang
@ 2016-08-14 11:04   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:04 UTC (permalink / raw)
  To: Cong Wang, netdev

On 16-08-14 01:35 AM, Cong Wang wrote:
> As pointed out by Jamal, an action could be shared by
> multiple filters, so we can't use list to chain them
> any more after we get rid of the original tc_action.
> Instead, we could just save pointers to these actions
> in tcf_exts, since they are refcount'ed, so convert
> the list to an array of pointers.
>
> The "ugly" part is the action API still accepts list
> as a parameter, I just introduce a helper function to
> convert the array of pointers to a list, instead of
> relying on the C99 feature to iterate the array.
>
> Fixes: a85a970af265 ("net_sched: move tc_action into tcf_common")
> Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
> Cc: Jamal Hadi Salim <jhs@mojatatu.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>


cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 6/7] net_sched: unify the init logic for act_police
  2016-08-14  5:35 ` [Patch net v4 6/7] net_sched: unify the init logic for act_police Cong Wang
@ 2016-08-14 11:04   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:04 UTC (permalink / raw)
  To: Cong Wang, netdev

On 16-08-14 01:35 AM, Cong Wang wrote:
> Jamal reported a crash when we create a police action
> with a specific index, this is because the init logic
> is not correct, we should always create one for this
> case. Just unify the logic with other tc actions.
>
> Fixes: a03e6fe56971 ("act_police: fix a crash during removal")
> Reported-by: Jamal Hadi Salim <jhs@mojatatu.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>

Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>

cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [Patch net v4 7/7] net_sched: allow flushing tc police actions
  2016-08-14  5:35 ` [Patch net v4 7/7] net_sched: allow flushing tc police actions Cong Wang
@ 2016-08-14 11:05   ` Jamal Hadi Salim
  0 siblings, 0 replies; 15+ messages in thread
From: Jamal Hadi Salim @ 2016-08-14 11:05 UTC (permalink / raw)
  To: Cong Wang, netdev; +Cc: Roman Mashak

On 16-08-14 01:35 AM, Cong Wang wrote:
> From: Roman Mashak <mrv@mojatatu.com>
>
> The act_police uses its own code to walk the
> action hashtable, which leads to that we could
> not flush standalone tc police actions, so just
> switch to tcf_generic_walker() like other actions.
>
> (Joint work from Roman and Cong.)
>
> Signed-off-by: Roman Mashak <mrv@mojatatu.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>


Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>


cheers,
jamal

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-08-14 11:18 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-14  5:34 [Patch net v4 0/7] net_sched: tc action fixes and updates Cong Wang
2016-08-14  5:34 ` [Patch net v4 1/7] net_sched: remove the leftover cleanup_a() Cong Wang
2016-08-14 11:01   ` Jamal Hadi Salim
2016-08-14  5:34 ` [Patch net v4 2/7] net_sched: remove an unnecessary list_del() Cong Wang
2016-08-14 11:01   ` Jamal Hadi Salim
2016-08-14  5:34 ` [Patch net v4 3/7] net_sched: fix a typo in tc_for_each_action() Cong Wang
2016-08-14 11:02   ` Jamal Hadi Salim
2016-08-14  5:34 ` [Patch net v4 4/7] net_sched: move tc offload macros to pkt_cls.h Cong Wang
2016-08-14 11:03   ` Jamal Hadi Salim
2016-08-14  5:35 ` [Patch net v4 5/7] net_sched: convert tcf_exts from list to pointer array Cong Wang
2016-08-14 11:04   ` Jamal Hadi Salim
2016-08-14  5:35 ` [Patch net v4 6/7] net_sched: unify the init logic for act_police Cong Wang
2016-08-14 11:04   ` Jamal Hadi Salim
2016-08-14  5:35 ` [Patch net v4 7/7] net_sched: allow flushing tc police actions Cong Wang
2016-08-14 11:05   ` Jamal Hadi Salim

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.