All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances
@ 2017-11-03 17:19 Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 1/5] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Jiri Pirko @ 2017-11-03 17:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

From: Jiri Pirko <jiri@mellanox.com>

Currently the filters added to qdiscs are independent. So for example if you
have 2 netdevices and you create ingress qdisc on both and you want to add
identical filter rules both, you need to add them twice. This patchset
makes this easier and mainly saves resources allowing to share all filters
within a qdisc - I call it a "filter block". Also this helps to save
resources when we do offload to hw for example to expensive TCAM.

So back to the example. First, we create 2 qdiscs. Both will share
block number 22. "22" is just an identification. If we don't pass any
block number, a new one will be generated by kernel:

$ tc qdisc add dev ens7 ingress block 22
                                ^^^^^^^^
$ tc qdisc add dev ens8 ingress block 22
                                ^^^^^^^^

Now if we list the qdiscs, we will see the block index in the output:

$ tc qdisc
qdisc ingress ffff: dev ens7 parent ffff:fff1 block 22
qdisc ingress ffff: dev ens8 parent ffff:fff1 block 22

Now we can add filter to any of qdiscs sharing the same block:

$ tc filter add dev ens7 ingress protocol ip pref 25 flower dst_ip 192.168.0.0/16 action drop


We will see the same output if we list filters for ens7 and ens8, including stats:

$ tc -s filter show dev ens7 ingress
filter protocol ip pref 25 flower chain 0
filter protocol ip pref 25 flower chain 0 handle 0x1
  eth_type ipv4
  dst_ip 192.168.0.0/16
  not_in_hw
        action order 1: gact action drop
         random type none pass val 0
         index 1 ref 1 bind 1 installed 39 sec used 2 sec
        Action statistics:
        Sent 3108 bytes 37 pkt (dropped 37, overlimits 0 requeues 0)
        backlog 0b 0p requeues 0

$ tc -s filter show dev ens8 ingress
filter protocol ip pref 25 flower chain 0
filter protocol ip pref 25 flower chain 0 handle 0x1
  eth_type ipv4
  dst_ip 192.168.0.0/16
  not_in_hw
        action order 1: gact action drop
         random type none pass val 0
         index 1 ref 1 bind 1 installed 40 sec used 3 sec
        Action statistics:
        Sent 3108 bytes 37 pkt (dropped 37, overlimits 0 requeues 0)
        backlog 0b 0p requeues 0

Jiri Pirko (5):
  net: sched: introduce support for multiple filter chain pointers
    registration
  net: sched: avoid usage of tp->q in tcf_classify
  net: sched: introduce block mechanism to handle netif_keep_dst calls
  net: sched: remove classid and q fields from tcf_proto
  net: sched: allow ingress and clsact qdiscs to share filter blocks

 include/net/pkt_cls.h          |   4 +
 include/net/sch_generic.h      |   9 +-
 include/uapi/linux/pkt_sched.h |  11 ++
 net/sched/cls_api.c            | 327 +++++++++++++++++++++++++++++++++++------
 net/sched/cls_bpf.c            |   4 +-
 net/sched/cls_flow.c           |   2 +-
 net/sched/cls_route.c          |   2 +-
 net/sched/sch_ingress.c        |  89 ++++++++++-
 8 files changed, 397 insertions(+), 51 deletions(-)

-- 
2.9.5

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

* [patch net-next 1/5] net: sched: introduce support for multiple filter chain pointers registration
  2017-11-03 17:19 [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances Jiri Pirko
@ 2017-11-03 17:19 ` Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 2/5] net: sched: avoid usage of tp->q in tcf_classify Jiri Pirko
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Jiri Pirko @ 2017-11-03 17:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

From: Jiri Pirko <jiri@mellanox.com>

So far, there was possible only to register a single filter chain
pointer to block->chain[0]. However, when the blocks will get shareable,
we need to allow multiple filter chain pointers registration.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/pkt_cls.h     |   3 +
 include/net/sch_generic.h |   5 +-
 net/sched/cls_api.c       | 247 +++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 218 insertions(+), 37 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 505d4b7..05c478e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -28,6 +28,8 @@ struct tcf_block_ext_info {
 	enum tcf_block_binder_type binder_type;
 	tcf_chain_head_change_t *chain_head_change;
 	void *chain_head_change_priv;
+	bool shareable;
+	u32 block_index;
 };
 
 struct tcf_block_cb;
@@ -47,6 +49,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
 
 static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
 {
+	WARN_ON(block->refcnt != 1);
 	return block->q;
 }
 
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c64e62c..8cbdd82 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -264,8 +264,7 @@ typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv);
 
 struct tcf_chain {
 	struct tcf_proto __rcu *filter_chain;
-	tcf_chain_head_change_t *chain_head_change;
-	void *chain_head_change_priv;
+	struct list_head filter_chain_list;
 	struct list_head list;
 	struct tcf_block *block;
 	u32 index; /* chain index */
@@ -274,6 +273,8 @@ struct tcf_chain {
 
 struct tcf_block {
 	struct list_head chain_list;
+	u32 index; /* block index for shared blocks */
+	unsigned int refcnt;
 	struct net *net;
 	struct Qdisc *q;
 	struct list_head cb_list;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 206e19f..4576b2d 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -25,6 +25,7 @@
 #include <linux/kmod.h>
 #include <linux/err.h>
 #include <linux/slab.h>
+#include <linux/idr.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <net/netlink.h>
@@ -180,6 +181,12 @@ static void tcf_proto_destroy(struct tcf_proto *tp)
 	kfree_rcu(tp, rcu);
 }
 
+struct tcf_filter_chain_list_item {
+	struct list_head list;
+	tcf_chain_head_change_t *chain_head_change;
+	void *chain_head_change_priv;
+};
+
 static struct tcf_chain *tcf_chain_create(struct tcf_block *block,
 					  u32 chain_index)
 {
@@ -188,6 +195,7 @@ static struct tcf_chain *tcf_chain_create(struct tcf_block *block,
 	chain = kzalloc(sizeof(*chain), GFP_KERNEL);
 	if (!chain)
 		return NULL;
+	INIT_LIST_HEAD(&chain->filter_chain_list);
 	list_add_tail(&chain->list, &block->chain_list);
 	chain->block = block;
 	chain->index = chain_index;
@@ -195,12 +203,19 @@ static struct tcf_chain *tcf_chain_create(struct tcf_block *block,
 	return chain;
 }
 
+static void tcf_chain_head_change_item(struct tcf_filter_chain_list_item *item,
+				       struct tcf_proto *tp_head)
+{
+	if (item->chain_head_change)
+		item->chain_head_change(tp_head, item->chain_head_change_priv);
+}
 static void tcf_chain_head_change(struct tcf_chain *chain,
 				  struct tcf_proto *tp_head)
 {
-	if (chain->chain_head_change)
-		chain->chain_head_change(tp_head,
-					 chain->chain_head_change_priv);
+	struct tcf_filter_chain_list_item *item;
+
+	list_for_each_entry(item, &chain->filter_chain_list, list)
+		tcf_chain_head_change_item(item, tp_head);
 }
 
 static void tcf_chain_flush(struct tcf_chain *chain)
@@ -276,15 +291,84 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
 	tcf_block_offload_cmd(block, q, ei, TC_BLOCK_UNBIND);
 }
 
-int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
-		      struct tcf_block_ext_info *ei)
+static int
+tcf_chain_head_change_cb_add(struct tcf_chain *chain,
+			     struct tcf_block_ext_info *ei)
+{
+	struct tcf_filter_chain_list_item *item;
+
+	item = kmalloc(sizeof(*item), GFP_KERNEL);
+	if (!item)
+		return -ENOMEM;
+	item->chain_head_change = ei->chain_head_change;
+	item->chain_head_change_priv = ei->chain_head_change_priv;
+	if (chain->filter_chain)
+		tcf_chain_head_change_item(item, chain->filter_chain);
+	list_add(&item->list, &chain->filter_chain_list);
+	return 0;
+}
+
+static void
+tcf_chain_head_change_cb_del(struct tcf_chain *chain,
+			     struct tcf_block_ext_info *ei)
+{
+	struct tcf_filter_chain_list_item *item;
+
+	list_for_each_entry(item, &chain->filter_chain_list, list) {
+		if ((!ei->chain_head_change && !ei->chain_head_change_priv) ||
+		    (item->chain_head_change == ei->chain_head_change &&
+		     item->chain_head_change_priv == ei->chain_head_change_priv)) {
+			tcf_chain_head_change_item(item, NULL);
+			list_del(&item->list);
+			kfree(item);
+			return;
+		}
+	}
+	WARN_ON(1);
+}
+
+struct tcf_net {
+	struct idr idr;
+};
+
+static unsigned int tcf_net_id;
+
+static int tcf_block_insert(struct tcf_block *block, struct net *net,
+			    u32 block_index)
+{
+	struct tcf_net *tn = net_generic(net, tcf_net_id);
+	int idr_start;
+	int idr_end;
+	int index;
+
+	if (block_index >= INT_MAX)
+		return -EINVAL;
+	idr_start = block_index ? block_index : 1;
+	idr_end = block_index ? block_index + 1 : INT_MAX;
+
+	index = idr_alloc(&tn->idr, block, idr_start, idr_end, GFP_KERNEL);
+	if (index < 0)
+		return index;
+	block->index = index;
+	return 0;
+}
+
+static void tcf_block_remove(struct tcf_block *block, struct net *net)
 {
-	struct tcf_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
+	struct tcf_net *tn = net_generic(net, tcf_net_id);
+
+	idr_remove(&tn->idr, block->index);
+}
+
+static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q)
+{
+	struct tcf_block *block;
 	struct tcf_chain *chain;
 	int err;
 
+	block = kzalloc(sizeof(*block), GFP_KERNEL);
 	if (!block)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	INIT_LIST_HEAD(&block->chain_list);
 	INIT_LIST_HEAD(&block->cb_list);
 
@@ -294,17 +378,96 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
 		err = -ENOMEM;
 		goto err_chain_create;
 	}
-	WARN_ON(!ei->chain_head_change);
-	chain->chain_head_change = ei->chain_head_change;
-	chain->chain_head_change_priv = ei->chain_head_change_priv;
 	block->net = qdisc_net(q);
+	block->refcnt = 1;
+	block->net = net;
 	block->q = q;
+	return block;
+
+err_chain_create:
+	kfree(block);
+	return ERR_PTR(err);
+}
+
+static void tcf_block_destroy_final(struct work_struct *work)
+{
+	struct tcf_block *block = container_of(work, struct tcf_block, work);
+	struct tcf_chain *chain, *tmp;
+
+	rtnl_lock();
+	/* Only chain 0 should be still here. */
+	list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
+		tcf_chain_put(chain);
+	rtnl_unlock();
+	kfree(block);
+}
+
+static void tcf_block_destroy(struct tcf_block *block)
+{
+	INIT_WORK(&block->work, tcf_block_destroy_final);
+	/* Wait for existing RCU callbacks to cool down, make sure their works
+	 * have been queued before this. We can not flush pending works here
+	 * because we are holding the RTNL lock.
+	 */
+	rcu_barrier();
+	tcf_queue_work(&block->work);
+}
+
+static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index)
+{
+	struct tcf_net *tn = net_generic(net, tcf_net_id);
+
+	return idr_find(&tn->idr, block_index);
+}
+
+static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block)
+{
+	return list_first_entry(&block->chain_list, struct tcf_chain, list);
+}
+
+int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
+		      struct tcf_block_ext_info *ei)
+{
+	struct net *net = qdisc_net(q);
+	struct tcf_block *block = NULL;
+	bool created = false;
+	int err;
+
+	if (ei->shareable) {
+		block = tcf_block_lookup(net, ei->block_index);
+		if (block)
+			block->refcnt++;
+	}
+
+	if (!block) {
+		block = tcf_block_create(net, q);
+		if (IS_ERR(block))
+			return PTR_ERR(block);
+		created = true;
+		if (ei->shareable) {
+			err = tcf_block_insert(block, net, ei->block_index);
+			if (err)
+				goto err_block_insert;
+		}
+	}
+
+	err = tcf_chain_head_change_cb_add(tcf_block_chain_zero(block), ei);
+	if (err)
+		goto err_chain_head_change_cb_add;
+
 	tcf_block_offload_bind(block, q, ei);
 	*p_block = block;
 	return 0;
 
-err_chain_create:
-	kfree(block);
+err_chain_head_change_cb_add:
+	if (created) {
+		if (ei->shareable)
+			tcf_block_remove(block, net);
+err_block_insert:
+		tcf_block_destroy(block);
+	} else {
+		block->refcnt--;
+	}
 	return err;
 }
 EXPORT_SYMBOL(tcf_block_get_ext);
@@ -329,19 +492,6 @@ int tcf_block_get(struct tcf_block **p_block,
 }
 EXPORT_SYMBOL(tcf_block_get);
 
-static void tcf_block_put_final(struct work_struct *work)
-{
-	struct tcf_block *block = container_of(work, struct tcf_block, work);
-	struct tcf_chain *chain, *tmp;
-
-	rtnl_lock();
-	/* Only chain 0 should be still here. */
-	list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
-		tcf_chain_put(chain);
-	rtnl_unlock();
-	kfree(block);
-}
-
 /* XXX: Standalone actions are not allowed to jump to any chain, and bound
  * actions should be all removed after flushing. However, filters are now
  * destroyed in tc filter workqueue with RTNL lock, they can not race here.
@@ -351,18 +501,17 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
 {
 	struct tcf_chain *chain, *tmp;
 
-	list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
-		tcf_chain_flush(chain);
+	tcf_chain_head_change_cb_del(tcf_block_chain_zero(block), ei);
 
+	if (--block->refcnt == 0) {
+		if (ei->shareable)
+			tcf_block_remove(block, block->net);
+		list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
+			tcf_chain_flush(chain);
+	}
 	tcf_block_offload_unbind(block, q, ei);
-
-	INIT_WORK(&block->work, tcf_block_put_final);
-	/* Wait for existing RCU callbacks to cool down, make sure their works
-	 * have been queued before this. We can not flush pending works here
-	 * because we are holding the RTNL lock.
-	 */
-	rcu_barrier();
-	tcf_queue_work(&block->work);
+	if (block->refcnt == 0)
+		tcf_block_destroy(block);
 }
 EXPORT_SYMBOL(tcf_block_put_ext);
 
@@ -1248,12 +1397,40 @@ int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
 }
 EXPORT_SYMBOL(tc_setup_cb_call);
 
+static __net_init int tcf_net_init(struct net *net)
+{
+	struct tcf_net *tn = net_generic(net, tcf_net_id);
+
+	idr_init(&tn->idr);
+	return 0;
+}
+
+static void __net_exit tcf_net_exit(struct net *net)
+{
+	struct tcf_net *tn = net_generic(net, tcf_net_id);
+
+	idr_destroy(&tn->idr);
+}
+
+static struct pernet_operations tcf_net_ops = {
+	.init = tcf_net_init,
+	.exit = tcf_net_exit,
+	.id   = &tcf_net_id,
+	.size = sizeof(struct tcf_net),
+};
+
 static int __init tc_filter_init(void)
 {
+	int err;
+
 	tc_filter_wq = alloc_ordered_workqueue("tc_filter_workqueue", 0);
 	if (!tc_filter_wq)
 		return -ENOMEM;
 
+	err = register_pernet_subsys(&tcf_net_ops);
+	if (err)
+		return err;
+
 	rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, 0);
 	rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, 0);
 	rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
-- 
2.9.5

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

* [patch net-next 2/5] net: sched: avoid usage of tp->q in tcf_classify
  2017-11-03 17:19 [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 1/5] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
@ 2017-11-03 17:19 ` Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Jiri Pirko @ 2017-11-03 17:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

From: Jiri Pirko <jiri@mellanox.com>

Use block index in the messages instead.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 net/sched/cls_api.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 4576b2d..b3e313f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -670,8 +670,9 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 #ifdef CONFIG_NET_CLS_ACT
 reset:
 	if (unlikely(limit++ >= max_reclassify_loop)) {
-		net_notice_ratelimited("%s: reclassify loop, rule prio %u, protocol %02x\n",
-				       tp->q->ops->id, tp->prio & 0xffff,
+		net_notice_ratelimited("%u: reclassify loop, rule prio %u, protocol %02x\n",
+				       tp->chain->block->index,
+				       tp->prio & 0xffff,
 				       ntohs(tp->protocol));
 		return TC_ACT_SHOT;
 	}
-- 
2.9.5

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

* [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls
  2017-11-03 17:19 [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 1/5] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 2/5] net: sched: avoid usage of tp->q in tcf_classify Jiri Pirko
@ 2017-11-03 17:19 ` Jiri Pirko
  2017-11-03 20:15   ` Daniel Borkmann
  2017-11-03 17:19 ` [patch net-next 4/5] net: sched: remove classid and q fields from tcf_proto Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 5/5] net: sched: allow ingress and clsact qdiscs to share filter blocks Jiri Pirko
  4 siblings, 1 reply; 11+ messages in thread
From: Jiri Pirko @ 2017-11-03 17:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

From: Jiri Pirko <jiri@mellanox.com>

Couple of classifiers call netif_keep_dst directly on q->dev. That is
not possible to do directly for shared blocke where multiple qdiscs are
owning the block. So introduce a infrastructure to keep track of the
block owners in list and use this list to implement block variant of
netif_keep_dst.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/pkt_cls.h     |  1 +
 include/net/sch_generic.h |  2 ++
 net/sched/cls_api.c       | 68 +++++++++++++++++++++++++++++++++++++++++++++++
 net/sched/cls_bpf.c       |  4 +--
 net/sched/cls_flow.c      |  2 +-
 net/sched/cls_route.c     |  2 +-
 6 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 05c478e..683c5d5 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -39,6 +39,7 @@ bool tcf_queue_work(struct work_struct *work);
 struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
 				bool create);
 void tcf_chain_put(struct tcf_chain *chain);
+void tcf_block_netif_keep_dst(struct tcf_block *block);
 int tcf_block_get(struct tcf_block **p_block,
 		  struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q);
 int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 8cbdd82..ef907d4 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -278,6 +278,8 @@ struct tcf_block {
 	struct net *net;
 	struct Qdisc *q;
 	struct list_head cb_list;
+	struct list_head owner_list;
+	bool keep_dst;
 	struct work_struct work;
 };
 
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b3e313f..4166e3f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -371,6 +371,7 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q)
 		return ERR_PTR(-ENOMEM);
 	INIT_LIST_HEAD(&block->chain_list);
 	INIT_LIST_HEAD(&block->cb_list);
+	INIT_LIST_HEAD(&block->owner_list);
 
 	/* Create chain 0 by default, it has to be always present. */
 	chain = tcf_chain_create(block, 0);
@@ -425,6 +426,64 @@ static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block)
 	return list_first_entry(&block->chain_list, struct tcf_chain, list);
 }
 
+struct tcf_block_owner_item {
+	struct list_head list;
+	struct Qdisc *q;
+	enum tcf_block_binder_type binder_type;
+};
+
+static void
+tcf_block_owner_netif_keep_dst(struct tcf_block *block,
+			       struct Qdisc *q,
+			       enum tcf_block_binder_type binder_type)
+{
+	if (block->keep_dst &&
+	    binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+		netif_keep_dst(qdisc_dev(q));
+}
+
+void tcf_block_netif_keep_dst(struct tcf_block *block)
+{
+	struct tcf_block_owner_item *item;
+
+	block->keep_dst = true;
+	list_for_each_entry(item, &block->owner_list, list)
+		tcf_block_owner_netif_keep_dst(block, item->q,
+					       item->binder_type);
+}
+EXPORT_SYMBOL(tcf_block_netif_keep_dst);
+
+static int tcf_block_owner_add(struct tcf_block *block,
+			       struct Qdisc *q,
+			       enum tcf_block_binder_type binder_type)
+{
+	struct tcf_block_owner_item *item;
+
+	item = kmalloc(sizeof(*item), GFP_KERNEL);
+	if (!item)
+		return -ENOMEM;
+	item->q = q;
+	item->binder_type = binder_type;
+	list_add(&item->list, &block->owner_list);
+	return 0;
+}
+
+static void tcf_block_owner_del(struct tcf_block *block,
+				struct Qdisc *q,
+				enum tcf_block_binder_type binder_type)
+{
+	struct tcf_block_owner_item *item;
+
+	list_for_each_entry(item, &block->owner_list, list) {
+		if (item->q == q && item->binder_type == binder_type) {
+			list_del(&item->list);
+			kfree(item);
+			return;
+		}
+	}
+	WARN_ON(1);
+}
+
 int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
 		      struct tcf_block_ext_info *ei)
 {
@@ -451,6 +510,12 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
 		}
 	}
 
+	err = tcf_block_owner_add(block, q, ei->binder_type);
+	if (err)
+		goto err_block_owner_add;
+
+	tcf_block_owner_netif_keep_dst(block, q, ei->binder_type);
+
 	err = tcf_chain_head_change_cb_add(tcf_block_chain_zero(block), ei);
 	if (err)
 		goto err_chain_head_change_cb_add;
@@ -460,6 +525,8 @@ int tcf_block_get_ext(struct tcf_block **p_block, struct Qdisc *q,
 	return 0;
 
 err_chain_head_change_cb_add:
+	tcf_block_owner_del(block, q, ei->binder_type);
+err_block_owner_add:
 	if (created) {
 		if (ei->shareable)
 			tcf_block_remove(block, net);
@@ -502,6 +569,7 @@ void tcf_block_put_ext(struct tcf_block *block, struct Qdisc *q,
 	struct tcf_chain *chain, *tmp;
 
 	tcf_chain_head_change_cb_del(tcf_block_chain_zero(block), ei);
+	tcf_block_owner_del(block, q, ei->binder_type);
 
 	if (--block->refcnt == 0) {
 		if (ei->shareable)
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index bc3edde..81a8c8f 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -398,8 +398,8 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
 	prog->bpf_name = name;
 	prog->filter = fp;
 
-	if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
-		netif_keep_dst(qdisc_dev(tp->q));
+	if (fp->dst_needed)
+		tcf_block_netif_keep_dst(tp->chain->block);
 
 	return 0;
 }
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 9c08fcd..97e4f25 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -520,7 +520,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
 
 	timer_setup(&fnew->perturb_timer, flow_perturbation, TIMER_DEFERRABLE);
 
-	netif_keep_dst(qdisc_dev(tp->q));
+	tcf_block_netif_keep_dst(tp->chain->block);
 
 	if (tb[TCA_FLOW_KEYS]) {
 		fnew->keymask = keymask;
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 4b14ccd..0602aaa 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -517,7 +517,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
 		if (f->handle < f1->handle)
 			break;
 
-	netif_keep_dst(qdisc_dev(tp->q));
+	tcf_block_netif_keep_dst(tp->chain->block);
 	rcu_assign_pointer(f->next, f1);
 	rcu_assign_pointer(*fp, f);
 
-- 
2.9.5

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

* [patch net-next 4/5] net: sched: remove classid and q fields from tcf_proto
  2017-11-03 17:19 [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances Jiri Pirko
                   ` (2 preceding siblings ...)
  2017-11-03 17:19 ` [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
@ 2017-11-03 17:19 ` Jiri Pirko
  2017-11-03 17:19 ` [patch net-next 5/5] net: sched: allow ingress and clsact qdiscs to share filter blocks Jiri Pirko
  4 siblings, 0 replies; 11+ messages in thread
From: Jiri Pirko @ 2017-11-03 17:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

From: Jiri Pirko <jiri@mellanox.com>

Both are no longer used, so remove them.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/sch_generic.h | 2 --
 net/sched/cls_api.c       | 7 ++-----
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index ef907d4..f551163 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -244,8 +244,6 @@ struct tcf_proto {
 
 	/* All the rest */
 	u32			prio;
-	u32			classid;
-	struct Qdisc		*q;
 	void			*data;
 	const struct tcf_proto_ops	*ops;
 	struct tcf_chain	*chain;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 4166e3f..d50cdac 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -123,8 +123,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 }
 
 static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
-					  u32 prio, u32 parent, struct Qdisc *q,
-					  struct tcf_chain *chain)
+					  u32 prio, struct tcf_chain *chain)
 {
 	struct tcf_proto *tp;
 	int err;
@@ -158,8 +157,6 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
 	tp->classify = tp->ops->classify;
 	tp->protocol = protocol;
 	tp->prio = prio;
-	tp->classid = parent;
-	tp->q = q;
 	tp->chain = chain;
 
 	err = tp->ops->init(tp);
@@ -1066,7 +1063,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
 			prio = tcf_auto_prio(tcf_chain_tp_prev(&chain_info));
 
 		tp = tcf_proto_create(nla_data(tca[TCA_KIND]),
-				      protocol, prio, parent, q, chain);
+				      protocol, prio, chain);
 		if (IS_ERR(tp)) {
 			err = PTR_ERR(tp);
 			goto errout;
-- 
2.9.5

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

* [patch net-next 5/5] net: sched: allow ingress and clsact qdiscs to share filter blocks
  2017-11-03 17:19 [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances Jiri Pirko
                   ` (3 preceding siblings ...)
  2017-11-03 17:19 ` [patch net-next 4/5] net: sched: remove classid and q fields from tcf_proto Jiri Pirko
@ 2017-11-03 17:19 ` Jiri Pirko
  4 siblings, 0 replies; 11+ messages in thread
From: Jiri Pirko @ 2017-11-03 17:19 UTC (permalink / raw)
  To: netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

From: Jiri Pirko <jiri@mellanox.com>

Benefit from the previously introduced shared filter blocks
infrastructure and allow ingress and clsact qdisc instances to share
filter blocks. The block index is coming from userspace as qdisc option.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/uapi/linux/pkt_sched.h | 11 ++++++
 net/sched/sch_ingress.c        | 89 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 0e88cc2..9197d25 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -923,4 +923,15 @@ enum {
 
 #define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
 
+/* Ingress/clsact */
+
+enum {
+	TCA_CLSACT_UNSPEC,
+	TCA_CLSACT_INGRESS_BLOCK,
+	TCA_CLSACT_EGRESS_BLOCK,
+	__TCA_CLSACT_MAX
+};
+
+#define TCA_CLSACT_MAX	(__TCA_CLSACT_MAX - 1)
+
 #endif
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 5ecc38f..ee89efc 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -60,6 +60,29 @@ static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)
 	struct mini_Qdisc_pair *miniqp = priv;
 
 	mini_qdisc_pair_swap(miniqp, tp_head);
+};
+
+static const struct nla_policy ingress_policy[TCA_CLSACT_MAX + 1] = {
+	[TCA_CLSACT_INGRESS_BLOCK]	= { .type = NLA_U32 },
+};
+
+static int ingress_parse_opt(struct nlattr *opt, u32 *p_ingress_block_index)
+{
+	struct nlattr *tb[TCA_CLSACT_MAX + 1];
+	int err;
+
+	*p_ingress_block_index = 0;
+
+	if (!opt)
+		return 0;
+	err = nla_parse_nested(tb, TCA_CLSACT_MAX, opt, ingress_policy, NULL);
+	if (err)
+		return err;
+
+	if (tb[TCA_CLSACT_INGRESS_BLOCK])
+		*p_ingress_block_index =
+			nla_get_u32(tb[TCA_CLSACT_INGRESS_BLOCK]);
+	return 0;
 }
 
 static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
@@ -70,6 +93,11 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
 
 	mini_qdisc_pair_init(&q->miniqp, sch, &dev->miniq_ingress);
 
+	err = ingress_parse_opt(opt, &q->block_info.block_index);
+	if (err)
+		return err;
+
+	q->block_info.shareable = true;
 	q->block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
 	q->block_info.chain_head_change = clsact_chain_head_change;
 	q->block_info.chain_head_change_priv = &q->miniqp;
@@ -94,11 +122,14 @@ static void ingress_destroy(struct Qdisc *sch)
 
 static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
+	struct ingress_sched_data *q = qdisc_priv(sch);
 	struct nlattr *nest;
 
 	nest = nla_nest_start(skb, TCA_OPTIONS);
 	if (nest == NULL)
 		goto nla_put_failure;
+	if (nla_put_u32(skb, TCA_CLSACT_INGRESS_BLOCK, q->block->index))
+		goto nla_put_failure;
 
 	return nla_nest_end(skb, nest);
 
@@ -166,6 +197,35 @@ static struct tcf_block *clsact_tcf_block(struct Qdisc *sch, unsigned long cl)
 	}
 }
 
+static const struct nla_policy clsact_policy[TCA_CLSACT_MAX + 1] = {
+	[TCA_CLSACT_INGRESS_BLOCK]	= { .type = NLA_U32 },
+	[TCA_CLSACT_EGRESS_BLOCK]	= { .type = NLA_U32 },
+};
+
+static int clsact_parse_opt(struct nlattr *opt, u32 *p_ingress_block_index,
+			    u32 *p_egress_block_index)
+{
+	struct nlattr *tb[TCA_CLSACT_MAX + 1];
+	int err;
+
+	*p_ingress_block_index = 0;
+	*p_egress_block_index = 0;
+
+	if (!opt)
+		return 0;
+	err = nla_parse_nested(tb, TCA_CLSACT_MAX, opt, clsact_policy, NULL);
+	if (err)
+		return err;
+
+	if (tb[TCA_CLSACT_INGRESS_BLOCK])
+		*p_ingress_block_index =
+			nla_get_u32(tb[TCA_CLSACT_INGRESS_BLOCK]);
+	if (tb[TCA_CLSACT_EGRESS_BLOCK])
+		*p_egress_block_index =
+			nla_get_u32(tb[TCA_CLSACT_EGRESS_BLOCK]);
+	return 0;
+}
+
 static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct clsact_sched_data *q = qdisc_priv(sch);
@@ -174,6 +234,12 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
 
 	mini_qdisc_pair_init(&q->miniqp_ingress, sch, &dev->miniq_ingress);
 
+	err = clsact_parse_opt(opt, &q->ingress_block_info.block_index,
+			       &q->egress_block_info.block_index);
+	if (err)
+		return err;
+
+	q->ingress_block_info.shareable = true;
 	q->ingress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
 	q->ingress_block_info.chain_head_change = clsact_chain_head_change;
 	q->ingress_block_info.chain_head_change_priv = &q->miniqp_ingress;
@@ -184,6 +250,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
 
 	mini_qdisc_pair_init(&q->miniqp_egress, sch, &dev->miniq_egress);
 
+	q->egress_block_info.shareable = true;
 	q->egress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS;
 	q->egress_block_info.chain_head_change = clsact_chain_head_change;
 	q->egress_block_info.chain_head_change_priv = &q->miniqp_egress;
@@ -215,6 +282,26 @@ static void clsact_destroy(struct Qdisc *sch)
 	net_dec_egress_queue();
 }
 
+static int clsact_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct clsact_sched_data *q = qdisc_priv(sch);
+	struct nlattr *nest;
+
+	nest = nla_nest_start(skb, TCA_OPTIONS);
+	if (!nest)
+		goto nla_put_failure;
+	if (nla_put_u32(skb, TCA_CLSACT_INGRESS_BLOCK, q->ingress_block->index))
+		goto nla_put_failure;
+	if (nla_put_u32(skb, TCA_CLSACT_EGRESS_BLOCK, q->egress_block->index))
+		goto nla_put_failure;
+
+	return nla_nest_end(skb, nest);
+
+nla_put_failure:
+	nla_nest_cancel(skb, nest);
+	return -1;
+}
+
 static const struct Qdisc_class_ops clsact_class_ops = {
 	.leaf		=	ingress_leaf,
 	.find		=	clsact_find,
@@ -230,7 +317,7 @@ static struct Qdisc_ops clsact_qdisc_ops __read_mostly = {
 	.priv_size	=	sizeof(struct clsact_sched_data),
 	.init		=	clsact_init,
 	.destroy	=	clsact_destroy,
-	.dump		=	ingress_dump,
+	.dump		=	clsact_dump,
 	.owner		=	THIS_MODULE,
 };
 
-- 
2.9.5

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

* Re: [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls
  2017-11-03 17:19 ` [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
@ 2017-11-03 20:15   ` Daniel Borkmann
  2017-11-04  9:55     ` Jiri Pirko
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2017-11-03 20:15 UTC (permalink / raw)
  To: Jiri Pirko, netdev
  Cc: davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

On 11/03/2017 06:19 PM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> Couple of classifiers call netif_keep_dst directly on q->dev. That is
> not possible to do directly for shared blocke where multiple qdiscs are
> owning the block. So introduce a infrastructure to keep track of the
> block owners in list and use this list to implement block variant of
> netif_keep_dst.
>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
[...]
> +struct tcf_block_owner_item {
> +	struct list_head list;
> +	struct Qdisc *q;
> +	enum tcf_block_binder_type binder_type;
> +};
> +
> +static void
> +tcf_block_owner_netif_keep_dst(struct tcf_block *block,
> +			       struct Qdisc *q,
> +			       enum tcf_block_binder_type binder_type)
> +{
> +	if (block->keep_dst &&
> +	    binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)

Why we need to keep dst on TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS ?
I presume this enum means sch_handle_egress() ? dst is dropped
later ...

> +		netif_keep_dst(qdisc_dev(q));
> +}
> +
> +void tcf_block_netif_keep_dst(struct tcf_block *block)
> +{
> +	struct tcf_block_owner_item *item;
> +
> +	block->keep_dst = true;
> +	list_for_each_entry(item, &block->owner_list, list)

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

* Re: [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls
  2017-11-03 20:15   ` Daniel Borkmann
@ 2017-11-04  9:55     ` Jiri Pirko
  2017-11-04 10:33       ` Daniel Borkmann
  0 siblings, 1 reply; 11+ messages in thread
From: Jiri Pirko @ 2017-11-04  9:55 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: netdev, davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend

Fri, Nov 03, 2017 at 09:15:54PM CET, daniel@iogearbox.net wrote:
>On 11/03/2017 06:19 PM, Jiri Pirko wrote:
>> From: Jiri Pirko <jiri@mellanox.com>
>> 
>> Couple of classifiers call netif_keep_dst directly on q->dev. That is
>> not possible to do directly for shared blocke where multiple qdiscs are
>> owning the block. So introduce a infrastructure to keep track of the
>> block owners in list and use this list to implement block variant of
>> netif_keep_dst.
>> 
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>[...]
>> +struct tcf_block_owner_item {
>> +	struct list_head list;
>> +	struct Qdisc *q;
>> +	enum tcf_block_binder_type binder_type;
>> +};
>> +
>> +static void
>> +tcf_block_owner_netif_keep_dst(struct tcf_block *block,
>> +			       struct Qdisc *q,
>> +			       enum tcf_block_binder_type binder_type)
>> +{
>> +	if (block->keep_dst &&
>> +	    binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
>
>Why we need to keep dst on TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS ?
>I presume this enum means sch_handle_egress() ? dst is dropped
>later ...

This is because of the bpf check:
       if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
               netif_keep_dst(qdisc_dev(tp->q));

I just maintain the same logic here.

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

* Re: [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls
  2017-11-04  9:55     ` Jiri Pirko
@ 2017-11-04 10:33       ` Daniel Borkmann
  2017-11-04 13:01         ` Jiri Pirko
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Borkmann @ 2017-11-04 10:33 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend, alexei.starovoitov

On 11/04/2017 10:55 AM, Jiri Pirko wrote:
> Fri, Nov 03, 2017 at 09:15:54PM CET, daniel@iogearbox.net wrote:
>> On 11/03/2017 06:19 PM, Jiri Pirko wrote:
>>> From: Jiri Pirko <jiri@mellanox.com>
>>>
>>> Couple of classifiers call netif_keep_dst directly on q->dev. That is
>>> not possible to do directly for shared blocke where multiple qdiscs are
>>> owning the block. So introduce a infrastructure to keep track of the
>>> block owners in list and use this list to implement block variant of
>>> netif_keep_dst.
>>>
>>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> [...]
>>> +struct tcf_block_owner_item {
>>> +	struct list_head list;
>>> +	struct Qdisc *q;
>>> +	enum tcf_block_binder_type binder_type;
>>> +};
>>> +
>>> +static void
>>> +tcf_block_owner_netif_keep_dst(struct tcf_block *block,
>>> +			       struct Qdisc *q,
>>> +			       enum tcf_block_binder_type binder_type)
>>> +{
>>> +	if (block->keep_dst &&
>>> +	    binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
>>
>> Why we need to keep dst on TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS ?
>> I presume this enum means sch_handle_egress() ? dst is dropped
>> later ...
>
> This is because of the bpf check:
>         if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
>                 netif_keep_dst(qdisc_dev(tp->q));
>
> I just maintain the same logic here.

No, that's a wrong claim, really ...

clsact in general hooks into the same logic as ingress, so TC_H_CLSACT
as major needs to reuse TC_H_INGRESS, and qdiscs set up as such set
TCQ_F_INGRESS as flags. For clsact that means both your block binder
types for clsact here (ingress/egress).

Please make sure that your other changes don't have similar assumption.

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

* Re: [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls
  2017-11-04 10:33       ` Daniel Borkmann
@ 2017-11-04 13:01         ` Jiri Pirko
  2017-11-04 21:21           ` Daniel Borkmann
  0 siblings, 1 reply; 11+ messages in thread
From: Jiri Pirko @ 2017-11-04 13:01 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: netdev, davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend, alexei.starovoitov

Sat, Nov 04, 2017 at 11:33:58AM CET, daniel@iogearbox.net wrote:
>On 11/04/2017 10:55 AM, Jiri Pirko wrote:
>> Fri, Nov 03, 2017 at 09:15:54PM CET, daniel@iogearbox.net wrote:
>> > On 11/03/2017 06:19 PM, Jiri Pirko wrote:
>> > > From: Jiri Pirko <jiri@mellanox.com>
>> > > 
>> > > Couple of classifiers call netif_keep_dst directly on q->dev. That is
>> > > not possible to do directly for shared blocke where multiple qdiscs are
>> > > owning the block. So introduce a infrastructure to keep track of the
>> > > block owners in list and use this list to implement block variant of
>> > > netif_keep_dst.
>> > > 
>> > > Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> > [...]
>> > > +struct tcf_block_owner_item {
>> > > +	struct list_head list;
>> > > +	struct Qdisc *q;
>> > > +	enum tcf_block_binder_type binder_type;
>> > > +};
>> > > +
>> > > +static void
>> > > +tcf_block_owner_netif_keep_dst(struct tcf_block *block,
>> > > +			       struct Qdisc *q,
>> > > +			       enum tcf_block_binder_type binder_type)
>> > > +{
>> > > +	if (block->keep_dst &&
>> > > +	    binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
>> > 
>> > Why we need to keep dst on TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS ?
>> > I presume this enum means sch_handle_egress() ? dst is dropped
>> > later ...
>> 
>> This is because of the bpf check:
>>         if (fp->dst_needed && !(tp->q->flags & TCQ_F_INGRESS))
>>                 netif_keep_dst(qdisc_dev(tp->q));
>> 
>> I just maintain the same logic here.
>
>No, that's a wrong claim, really ...
>
>clsact in general hooks into the same logic as ingress, so TC_H_CLSACT
>as major needs to reuse TC_H_INGRESS, and qdiscs set up as such set
>TCQ_F_INGRESS as flags. For clsact that means both your block binder
>types for clsact here (ingress/egress).

Ah, indeed, I missed this. I will rename TCQ_F_INGRESS to TCQ_F_CLSACT
as a part of this patchset too.


>
>Please make sure that your other changes don't have similar assumption.

They don't. Thanks for the review!

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

* Re: [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls
  2017-11-04 13:01         ` Jiri Pirko
@ 2017-11-04 21:21           ` Daniel Borkmann
  0 siblings, 0 replies; 11+ messages in thread
From: Daniel Borkmann @ 2017-11-04 21:21 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, nogahf, jhs, xiyou.wangcong, mlxsw, andrew,
	vivien.didelot, f.fainelli, michael.chan, ganeshgr, saeedm,
	matanb, leonro, idosch, jakub.kicinski, simon.horman,
	pieter.jansenvanvuuren, john.hurley, alexander.h.duyck, ogerlitz,
	john.fastabend, alexei.starovoitov

On 11/04/2017 02:01 PM, Jiri Pirko wrote:
[...]
> Ah, indeed, I missed this. I will rename TCQ_F_INGRESS to TCQ_F_CLSACT
> as a part of this patchset too.

Sounds reasonable, thanks!

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

end of thread, other threads:[~2017-11-04 21:21 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-03 17:19 [patch net-next 0/5] net: sched: allow qdiscs to share filter block instances Jiri Pirko
2017-11-03 17:19 ` [patch net-next 1/5] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
2017-11-03 17:19 ` [patch net-next 2/5] net: sched: avoid usage of tp->q in tcf_classify Jiri Pirko
2017-11-03 17:19 ` [patch net-next 3/5] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
2017-11-03 20:15   ` Daniel Borkmann
2017-11-04  9:55     ` Jiri Pirko
2017-11-04 10:33       ` Daniel Borkmann
2017-11-04 13:01         ` Jiri Pirko
2017-11-04 21:21           ` Daniel Borkmann
2017-11-03 17:19 ` [patch net-next 4/5] net: sched: remove classid and q fields from tcf_proto Jiri Pirko
2017-11-03 17:19 ` [patch net-next 5/5] net: sched: allow ingress and clsact qdiscs to share filter blocks Jiri Pirko

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.