* [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
@ 2017-10-12 17:17 Jiri Pirko
2017-10-12 17:17 ` [patch net-next 01/34] net: sched: store Qdisc pointer in struct block Jiri Pirko
` (35 more replies)
0 siblings, 36 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
First of all, I would like to apologize for big patchset. However after
couple of hours trying to figure out how to cut it, I found out it is
actually not possible. I would have to add some interface in one patchset
and only use it in second, which is forbidden. Also, I would like
to provide the reviewer the full picture. Most of the patches are small
and contained anyway, so it should be easy to review them. But to the
motivation:
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 parent ffff: 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
Patches overview:
Patches 1-3 introduce infrastructure for block sharing and the interface
funtions to the qdisc, tcf_block_get_ext and tcf_block_put_ext
Patches 4-11 are removing usages of tp->q pointer, which needs to be
eventually removed in order to set the tfc_proto independent
on a qdisc instance
Patches 12-19 introduces block callbacks, internal infra and driver-facing
interface, they add callback calling to individual classifiers
Patches 20-28 convert individual drivers from ndo_setup_tc to block
callbacks for classifiers offloading
Patches 29-31 remove unused things due to the previous conversion
Patch 32 introduces block mechanism to handle netif_keep_dst calls
Patch 33 removes tp->q and tp->classid - makes tcf_proto independent on qdisc
Patch 34 finally enables block sharing for cls_ingress and cls_clsact
Iproute2 implementation is here:
https://github.com/jpirko/iproute2_mlxsw/commit/f91ff81e3b307adfe769f29b3c04c70f39a2520c
The next patchset will introduce block sharing for mlxsw. For the
curious ones the patches could be found here:
https://github.com/jpirko/linux_mlxsw/commits/jiri_devel_shblock
Jiri Pirko (34):
net: sched: store Qdisc pointer in struct block
net: sched: introduce support for multiple filter chain pointers
registration
net: sched: introduce shared filter blocks infrastructure
net: sched: teach tcf_bind/unbind_filter to use block->q
net: sched: ematch: obtain net pointer from blocks
net: core: use dev->ingress_queue instead of tp->q
net: sched: cls_u32: use block instead of q in tc_u_common
net: sched: avoid usage of tp->q in tcf_classify
net: sched: tcindex, fw, flow: use tcf_block_q helper to get struct
Qdisc
net: sched: use tcf_block_q helper to get q pointer for sch_tree_lock
net: sched: propagate q and parent from caller down to tcf_fill_node
net: sched: add block bind/unbind notification to drivers
net: sched: introduce per-block callbacks
net: sched: use extended variants of block get and put in ingress and
clsact qdiscs
net: sched: use tc_setup_cb_call to call per-block callbacks
net: sched: cls_matchall: call block callbacks for offload
net: sched: cls_u32: swap u32_remove_hw_knode and u32_remove_hw_hnode
net: sched: cls_u32: call block callbacks for offload
net: sched: cls_bpf: call block callbacks for offload
mlxsw: spectrum: Convert ndo_setup_tc offloads to block callbacks
mlx5e: Convert ndo_setup_tc offloads to block callbacks
bnxt: Convert ndo_setup_tc offloads to block callbacks
cxgb4: Convert ndo_setup_tc offloads to block callbacks
ixgbe: Convert ndo_setup_tc offloads to block callbacks
mlx5e_rep: Convert ndo_setup_tc offloads to block callbacks
nfp: flower: Convert ndo_setup_tc offloads to block callbacks
nfp: bpf: Convert ndo_setup_tc offloads to block callbacks
dsa: Convert ndo_setup_tc offloads to block callbacks
net: sched: avoid ndo_setup_tc calls for TC_SETUP_CLS*
net: sched: remove unused classid field from tc_cls_common_offload
net: sched: remove unused is_classid_clsact_ingress/egress helpers
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
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 37 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 3 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 41 +-
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 42 +-
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 45 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 45 +-
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 62 ++-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 83 +++-
drivers/net/ethernet/netronome/nfp/bpf/main.c | 51 +-
drivers/net/ethernet/netronome/nfp/bpf/offload.c | 4 +
.../net/ethernet/netronome/nfp/flower/offload.c | 54 ++-
include/linux/netdevice.h | 1 +
include/net/pkt_cls.h | 195 +++++++-
include/net/pkt_sched.h | 14 +-
include/net/sch_generic.h | 15 +-
include/uapi/linux/pkt_sched.h | 12 +
net/core/dev.c | 21 +-
net/dsa/slave.c | 64 ++-
net/sched/cls_api.c | 527 +++++++++++++++++++--
net/sched/cls_bpf.c | 32 +-
net/sched/cls_flow.c | 9 +-
net/sched/cls_flower.c | 29 +-
net/sched/cls_fw.c | 5 +-
net/sched/cls_matchall.c | 58 +--
net/sched/cls_route.c | 2 +-
net/sched/cls_tcindex.c | 5 +-
net/sched/cls_u32.c | 79 ++-
net/sched/ematch.c | 2 +-
net/sched/sch_api.c | 6 +-
net/sched/sch_atm.c | 4 +-
net/sched/sch_cbq.c | 2 +-
net/sched/sch_drr.c | 2 +-
net/sched/sch_dsmark.c | 2 +-
net/sched/sch_fq_codel.c | 2 +-
net/sched/sch_hfsc.c | 4 +-
net/sched/sch_htb.c | 4 +-
net/sched/sch_ingress.c | 123 ++++-
net/sched/sch_multiq.c | 2 +-
net/sched/sch_prio.c | 2 +-
net/sched/sch_qfq.c | 2 +-
net/sched/sch_sfb.c | 2 +-
net/sched/sch_sfq.c | 2 +-
43 files changed, 1370 insertions(+), 330 deletions(-)
--
2.9.5
^ permalink raw reply [flat|nested] 53+ messages in thread
* [patch net-next 01/34] net: sched: store Qdisc pointer in struct block
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 02/34] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
` (34 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Prepare for removal of tp->q and store Qdisc pointer in the block
structure.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 4 ++--
include/net/sch_generic.h | 1 +
net/sched/cls_api.c | 3 ++-
net/sched/sch_atm.c | 4 ++--
net/sched/sch_cbq.c | 2 +-
net/sched/sch_drr.c | 2 +-
net/sched/sch_dsmark.c | 2 +-
net/sched/sch_fq_codel.c | 2 +-
net/sched/sch_hfsc.c | 4 ++--
net/sched/sch_htb.c | 4 ++--
net/sched/sch_ingress.c | 6 +++---
net/sched/sch_multiq.c | 2 +-
net/sched/sch_prio.c | 2 +-
net/sched/sch_qfq.c | 2 +-
net/sched/sch_sfb.c | 2 +-
net/sched/sch_sfq.c | 2 +-
16 files changed, 23 insertions(+), 21 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index f526374..772dfa8 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -22,7 +22,7 @@ struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
bool create);
void tcf_chain_put(struct tcf_chain *chain);
int tcf_block_get(struct tcf_block **p_block,
- struct tcf_proto __rcu **p_filter_chain);
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q);
void tcf_block_put(struct tcf_block *block);
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode);
@@ -30,7 +30,7 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
#else
static inline
int tcf_block_get(struct tcf_block **p_block,
- struct tcf_proto __rcu **p_filter_chain)
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
{
return 0;
}
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 684d8ed..df4032c 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -270,6 +270,7 @@ struct tcf_chain {
struct tcf_block {
struct list_head chain_list;
+ struct Qdisc *q;
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 2977b8a..f7d3f1f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -241,7 +241,7 @@ tcf_chain_filter_chain_ptr_set(struct tcf_chain *chain,
}
int tcf_block_get(struct tcf_block **p_block,
- struct tcf_proto __rcu **p_filter_chain)
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
{
struct tcf_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
struct tcf_chain *chain;
@@ -257,6 +257,7 @@ int tcf_block_get(struct tcf_block **p_block,
goto err_chain_create;
}
tcf_chain_filter_chain_ptr_set(chain, p_filter_chain);
+ block->q = q;
*p_block = block;
return 0;
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index c5fcdf1..2dbd249 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -281,7 +281,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent,
goto err_out;
}
- error = tcf_block_get(&flow->block, &flow->filter_list);
+ error = tcf_block_get(&flow->block, &flow->filter_list, sch);
if (error) {
kfree(flow);
goto err_out;
@@ -546,7 +546,7 @@ static int atm_tc_init(struct Qdisc *sch, struct nlattr *opt)
p->link.q = &noop_qdisc;
pr_debug("atm_tc_init: link (%p) qdisc %p\n", &p->link, p->link.q);
- err = tcf_block_get(&p->link.block, &p->link.filter_list);
+ err = tcf_block_get(&p->link.block, &p->link.filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index dcef97f..c3b92d6 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -1566,7 +1566,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
if (cl == NULL)
goto failure;
- err = tcf_block_get(&cl->block, &cl->filter_list);
+ err = tcf_block_get(&cl->block, &cl->filter_list, sch);
if (err) {
kfree(cl);
return err;
diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c
index 2d0e8d4..753dc7a 100644
--- a/net/sched/sch_drr.c
+++ b/net/sched/sch_drr.c
@@ -412,7 +412,7 @@ static int drr_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
struct drr_sched *q = qdisc_priv(sch);
int err;
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
err = qdisc_class_hash_init(&q->clhash);
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 2836c80..fb4fb71 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -344,7 +344,7 @@ static int dsmark_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
goto errout;
- err = tcf_block_get(&p->block, &p->filter_list);
+ err = tcf_block_get(&p->block, &p->filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index de3b57c..3c40ede 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -481,7 +481,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
return err;
}
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 3f88b75..a692184 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -1033,7 +1033,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
if (cl == NULL)
return -ENOBUFS;
- err = tcf_block_get(&cl->block, &cl->filter_list);
+ err = tcf_block_get(&cl->block, &cl->filter_list, sch);
if (err) {
kfree(cl);
return err;
@@ -1405,7 +1405,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
return err;
q->eligible = RB_ROOT;
- err = tcf_block_get(&q->root.block, &q->root.filter_list);
+ err = tcf_block_get(&q->root.block, &q->root.filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index c6d7ae8..57be73c 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1030,7 +1030,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
return -EINVAL;
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
@@ -1393,7 +1393,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
if (!cl)
goto failure;
- err = tcf_block_get(&cl->block, &cl->filter_list);
+ err = tcf_block_get(&cl->block, &cl->filter_list, sch);
if (err) {
kfree(cl);
goto failure;
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 44de4ee..9ccc1b8 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -59,7 +59,7 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
struct net_device *dev = qdisc_dev(sch);
int err;
- err = tcf_block_get(&q->block, &dev->ingress_cl_list);
+ err = tcf_block_get(&q->block, &dev->ingress_cl_list, sch);
if (err)
return err;
@@ -153,11 +153,11 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
struct net_device *dev = qdisc_dev(sch);
int err;
- err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list);
+ err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list, sch);
if (err)
return err;
- err = tcf_block_get(&q->egress_block, &dev->egress_cl_list);
+ err = tcf_block_get(&q->egress_block, &dev->egress_cl_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index ff4fc3e..31e0a28 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -245,7 +245,7 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
if (opt == NULL)
return -EINVAL;
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index 2dd6c68..95fad34 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -212,7 +212,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt)
if (!opt)
return -EINVAL;
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
index 6ddfd49..8694c7b 100644
--- a/net/sched/sch_qfq.c
+++ b/net/sched/sch_qfq.c
@@ -1419,7 +1419,7 @@ static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
int i, j, err;
u32 max_cl_shift, maxbudg_shift, max_classes;
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index cc39e17..487d375 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -553,7 +553,7 @@ static int sfb_init(struct Qdisc *sch, struct nlattr *opt)
struct sfb_sched_data *q = qdisc_priv(sch);
int err;
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 74ea863..123a53a 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -725,7 +725,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
setup_deferrable_timer(&q->perturb_timer, sfq_perturbation,
(unsigned long)sch);
- err = tcf_block_get(&q->block, &q->filter_list);
+ err = tcf_block_get(&q->block, &q->filter_list, sch);
if (err)
return err;
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 02/34] net: sched: introduce support for multiple filter chain pointers registration
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
2017-10-12 17:17 ` [patch net-next 01/34] net: sched: store Qdisc pointer in struct block Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 03/34] net: sched: introduce shared filter blocks infrastructure Jiri Pirko
` (33 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
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_sched.h | 7 +++++
include/net/sch_generic.h | 3 ++-
net/sched/cls_api.c | 68 ++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 259bc19..2d234af 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -4,7 +4,9 @@
#include <linux/jiffies.h>
#include <linux/ktime.h>
#include <linux/if_vlan.h>
+#include <linux/netdevice.h>
#include <net/sch_generic.h>
+#include <net/net_namespace.h>
#include <uapi/linux/pkt_sched.h>
#define DEFAULT_TX_QUEUE_LEN 1000
@@ -146,4 +148,9 @@ static inline bool is_classid_clsact_egress(u32 classid)
TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_EGRESS);
}
+static inline struct net *qdisc_net(struct Qdisc *q)
+{
+ return dev_net(q->dev_queue->dev);
+}
+
#endif
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index df4032c..6583c59 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -261,7 +261,7 @@ struct qdisc_skb_cb {
struct tcf_chain {
struct tcf_proto __rcu *filter_chain;
- struct tcf_proto __rcu **p_filter_chain;
+ struct list_head filter_chain_list;
struct list_head list;
struct tcf_block *block;
u32 index; /* chain index */
@@ -270,6 +270,7 @@ struct tcf_chain {
struct tcf_block {
struct list_head chain_list;
+ struct net *net;
struct Qdisc *q;
};
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index f7d3f1f..0ffd79a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -171,6 +171,11 @@ static void tcf_proto_destroy(struct tcf_proto *tp)
kfree_rcu(tp, rcu);
}
+struct tfc_filter_chain_list_item {
+ struct list_head list;
+ struct tcf_proto __rcu **p_filter_chain;
+};
+
static struct tcf_chain *tcf_chain_create(struct tcf_block *block,
u32 chain_index)
{
@@ -179,6 +184,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;
@@ -188,10 +194,11 @@ static struct tcf_chain *tcf_chain_create(struct tcf_block *block,
static void tcf_chain_flush(struct tcf_chain *chain)
{
+ struct tfc_filter_chain_list_item *item;
struct tcf_proto *tp;
- if (chain->p_filter_chain)
- RCU_INIT_POINTER(*chain->p_filter_chain, NULL);
+ list_for_each_entry(item, &chain->filter_chain_list, list)
+ RCU_INIT_POINTER(*item->p_filter_chain, NULL);
while ((tp = rtnl_dereference(chain->filter_chain)) != NULL) {
RCU_INIT_POINTER(chain->filter_chain, tp->next);
tcf_chain_put(chain);
@@ -233,11 +240,41 @@ void tcf_chain_put(struct tcf_chain *chain)
}
EXPORT_SYMBOL(tcf_chain_put);
+static int
+tcf_chain_filter_chain_ptr_add(struct tcf_chain *chain,
+ struct tcf_proto __rcu **p_filter_chain)
+{
+ struct tfc_filter_chain_list_item *item;
+
+ item = kmalloc(sizeof(*item), GFP_KERNEL);
+ if (!item)
+ return -ENOMEM;
+ item->p_filter_chain = p_filter_chain;
+ list_add(&item->list, &chain->filter_chain_list);
+ return 0;
+}
+
static void
-tcf_chain_filter_chain_ptr_set(struct tcf_chain *chain,
+tcf_chain_filter_chain_ptr_del(struct tcf_chain *chain,
struct tcf_proto __rcu **p_filter_chain)
{
- chain->p_filter_chain = p_filter_chain;
+ struct tfc_filter_chain_list_item *item;
+
+ list_for_each_entry(item, &chain->filter_chain_list, list) {
+ if (!p_filter_chain ||
+ item->p_filter_chain == p_filter_chain) {
+ RCU_INIT_POINTER(*item->p_filter_chain, NULL);
+ list_del(&item->list);
+ kfree(item);
+ return;
+ }
+ }
+ WARN_ON(1);
+}
+
+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(struct tcf_block **p_block,
@@ -256,7 +293,8 @@ int tcf_block_get(struct tcf_block **p_block,
err = -ENOMEM;
goto err_chain_create;
}
- tcf_chain_filter_chain_ptr_set(chain, p_filter_chain);
+ tcf_chain_filter_chain_ptr_add(chain, p_filter_chain);
+ block->net = qdisc_net(q);
block->q = q;
*p_block = block;
return 0;
@@ -274,6 +312,8 @@ void tcf_block_put(struct tcf_block *block)
if (!block)
return;
+ tcf_chain_filter_chain_ptr_del(tcf_block_chain_zero(block), NULL);
+
/* XXX: Standalone actions are not allowed to jump to any chain, and
* bound actions should be all removed after flushing. However,
* filters are destroyed in RCU callbacks, we have to hold the chains
@@ -371,9 +411,13 @@ static void tcf_chain_tp_insert(struct tcf_chain *chain,
struct tcf_chain_info *chain_info,
struct tcf_proto *tp)
{
- if (chain->p_filter_chain &&
- *chain_info->pprev == chain->filter_chain)
- rcu_assign_pointer(*chain->p_filter_chain, tp);
+ if (*chain_info->pprev == chain->filter_chain) {
+ struct tfc_filter_chain_list_item *item;
+
+ list_for_each_entry(item, &chain->filter_chain_list, list)
+ rcu_assign_pointer(*item->p_filter_chain, tp);
+ }
+
RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain_info));
rcu_assign_pointer(*chain_info->pprev, tp);
tcf_chain_hold(chain);
@@ -385,8 +429,12 @@ static void tcf_chain_tp_remove(struct tcf_chain *chain,
{
struct tcf_proto *next = rtnl_dereference(chain_info->next);
- if (chain->p_filter_chain && tp == chain->filter_chain)
- RCU_INIT_POINTER(*chain->p_filter_chain, next);
+ if (tp == chain->filter_chain) {
+ struct tfc_filter_chain_list_item *item;
+
+ list_for_each_entry(item, &chain->filter_chain_list, list)
+ RCU_INIT_POINTER(*item->p_filter_chain, next);
+ }
RCU_INIT_POINTER(*chain_info->pprev, next);
tcf_chain_put(chain);
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 03/34] net: sched: introduce shared filter blocks infrastructure
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
2017-10-12 17:17 ` [patch net-next 01/34] net: sched: store Qdisc pointer in struct block Jiri Pirko
2017-10-12 17:17 ` [patch net-next 02/34] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 04/34] net: sched: teach tcf_bind/unbind_filter to use block->q Jiri Pirko
` (32 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Allow qdiscs to share filter blocks among them. Each qdisc type has to
use block get/put modifications that enable sharing. Shared blocks are
tracked within each net namespace and identified by u32 value. This
value is auto-generated in case user did not pass it from userspace. If
user passes value that is not used, new block is created. If user passes
value that is already used, the existing block will be re-used.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 57 ++++++++++++++-
include/net/sch_generic.h | 2 +
net/sched/cls_api.c | 183 +++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 222 insertions(+), 20 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 772dfa8..0cf520b 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -17,13 +17,42 @@ struct tcf_walker {
int register_tcf_proto_ops(struct tcf_proto_ops *ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+struct tcf_block_ext_info {
+ bool shareable;
+ u32 block_index;
+};
+
#ifdef CONFIG_NET_CLS
struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
bool create);
void tcf_chain_put(struct tcf_chain *chain);
+
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 tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
+ struct tcf_block_ext_info *ei);
void tcf_block_put(struct tcf_block *block);
+void tcf_block_put_ext(struct tcf_block *block,
+ struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_block_ext_info *ei);
+
+static inline bool tcf_is_block_shared(const struct tcf_block *block)
+{
+ return block->refcnt != 1;
+}
+
+static inline struct Qdisc *tcf_block_q(struct tcf_block *block)
+{
+ WARN_ON(tcf_is_block_shared(block));
+ return block->q;
+}
+
+static inline struct net_device *tcf_block_dev(struct tcf_block *block)
+{
+ return tcf_block_q(block)->dev_queue->dev;
+}
+
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode);
@@ -35,8 +64,34 @@ int tcf_block_get(struct tcf_block **p_block,
return 0;
}
-static inline void tcf_block_put(struct tcf_block *block)
+static inline
+int tcf_block_get_ext(struct tcf_block **p_block,
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
+ struct tcf_block_ext_info *ei)
{
+ return 0;
+}
+
+static inline
+void tcf_block_put(struct tcf_block *block)
+{
+}
+
+static inline
+void tcf_block_put_ext(struct tcf_block *block,
+ struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_block_ext_info *ei)
+{
+}
+
+static inline struct net_device *tcf_block_dev(struct tcf_block *block)
+{
+ return NULL;
+}
+
+static inline bool tcf_is_block_shared(const struct tcf_block *block)
+{
+ return false;
}
static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 6583c59..0b2ba3b 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -270,6 +270,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;
};
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 0ffd79a..2d0f18f 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>
@@ -272,48 +273,70 @@ tcf_chain_filter_chain_ptr_del(struct tcf_chain *chain,
WARN_ON(1);
}
-static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block)
+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)
{
- return list_first_entry(&block->chain_list, struct tcf_chain, list);
+ 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;
}
-int tcf_block_get(struct tcf_block **p_block,
- struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
+static void tcf_block_remove(struct tcf_block *block, struct net *net)
+{
+ 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 = kzalloc(sizeof(*block), GFP_KERNEL);
+ 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);
+ block->refcnt = 1;
+ block->net = net;
+ block->q = q;
+
/* Create chain 0 by default, it has to be always present. */
chain = tcf_chain_create(block, 0);
if (!chain) {
err = -ENOMEM;
goto err_chain_create;
}
- tcf_chain_filter_chain_ptr_add(chain, p_filter_chain);
- block->net = qdisc_net(q);
- block->q = q;
- *p_block = block;
- return 0;
+ return block;
err_chain_create:
kfree(block);
- return err;
+ return ERR_PTR(err);
}
-EXPORT_SYMBOL(tcf_block_get);
-void tcf_block_put(struct tcf_block *block)
+static void tcf_block_destroy(struct tcf_block *block)
{
struct tcf_chain *chain, *tmp;
- if (!block)
- return;
-
- tcf_chain_filter_chain_ptr_del(tcf_block_chain_zero(block), NULL);
-
/* XXX: Standalone actions are not allowed to jump to any chain, and
* bound actions should be all removed after flushing. However,
* filters are destroyed in RCU callbacks, we have to hold the chains
@@ -341,6 +364,100 @@ void tcf_block_put(struct tcf_block *block)
tcf_chain_put(chain);
kfree(block);
}
+
+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 tcf_proto __rcu **p_filter_chain, 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_filter_chain_ptr_add(tcf_block_chain_zero(block),
+ p_filter_chain);
+ if (err)
+ goto err_chain_filter_chain_ptr_add;
+
+ *p_block = block;
+ return 0;
+
+err_chain_filter_chain_ptr_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);
+
+int tcf_block_get(struct tcf_block **p_block,
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q)
+{
+ struct tcf_block_ext_info ei = {0, };
+
+ return tcf_block_get_ext(p_block, p_filter_chain, q, &ei);
+}
+EXPORT_SYMBOL(tcf_block_get);
+
+void tcf_block_put_ext(struct tcf_block *block,
+ struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_block_ext_info *ei)
+{
+ if (!block)
+ return;
+
+ tcf_chain_filter_chain_ptr_del(tcf_block_chain_zero(block),
+ p_filter_chain);
+
+ if (--block->refcnt == 0) {
+ if (ei->shareable)
+ tcf_block_remove(block, block->net);
+ tcf_block_destroy(block);
+ }
+}
+EXPORT_SYMBOL(tcf_block_put_ext);
+
+void tcf_block_put(struct tcf_block *block)
+{
+ struct tcf_block_ext_info ei = {0, };
+
+ tcf_block_put_ext(block, NULL, &ei);
+}
EXPORT_SYMBOL(tcf_block_put);
/* Main classifier routine: scans classifier chain attached
@@ -1090,8 +1207,36 @@ int tc_setup_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
}
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;
+
+ 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] 53+ messages in thread
* [patch net-next 04/34] net: sched: teach tcf_bind/unbind_filter to use block->q
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (2 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 03/34] net: sched: introduce shared filter blocks infrastructure Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 05/34] net: sched: ematch: obtain net pointer from blocks Jiri Pirko
` (31 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Whenever the block->q is set, it can be used instead of tp->q as it
contains the same value. When it is not set, which can't happen now but
it might happen with the follow-up shared blocks introduction, the class
is not set in the result. That would lead to a class lookup instead
of direct class pointer use for classful qdiscs. However, it is not
planned to support classful qdisqs sharing filter blocks, so that may
never happen.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 0cf520b..05bc999 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -108,36 +108,43 @@ __cls_set_class(unsigned long *clp, unsigned long cl)
}
static inline unsigned long
-cls_set_class(struct tcf_proto *tp, unsigned long *clp,
- unsigned long cl)
+cls_set_class(struct Qdisc *q, unsigned long *clp, unsigned long cl)
{
unsigned long old_cl;
-
- tcf_tree_lock(tp);
+
+ sch_tree_lock(q);
old_cl = __cls_set_class(clp, cl);
- tcf_tree_unlock(tp);
-
+ sch_tree_unlock(q);
return old_cl;
}
static inline void
tcf_bind_filter(struct tcf_proto *tp, struct tcf_result *r, unsigned long base)
{
+ struct Qdisc *q = tp->chain->block->q;
unsigned long cl;
- cl = tp->q->ops->cl_ops->bind_tcf(tp->q, base, r->classid);
- cl = cls_set_class(tp, &r->class, cl);
+ /* Check q as it is not set for shared blocks. In that case,
+ * setting class is not supported.
+ */
+ if (!q)
+ return;
+ cl = q->ops->cl_ops->bind_tcf(q, base, r->classid);
+ cl = cls_set_class(q, &r->class, cl);
if (cl)
- tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+ q->ops->cl_ops->unbind_tcf(q, cl);
}
static inline void
tcf_unbind_filter(struct tcf_proto *tp, struct tcf_result *r)
{
+ struct Qdisc *q = tp->chain->block->q;
unsigned long cl;
+ if (!q)
+ return;
if ((cl = __cls_set_class(&r->class, 0)) != 0)
- tp->q->ops->cl_ops->unbind_tcf(tp->q, cl);
+ q->ops->cl_ops->unbind_tcf(q, cl);
}
struct tcf_exts {
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 05/34] net: sched: ematch: obtain net pointer from blocks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (3 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 04/34] net: sched: teach tcf_bind/unbind_filter to use block->q Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q Jiri Pirko
` (30 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Instead of using tp->q, use block to get the net pointer.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/ematch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 03b677b..1331a4c 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -178,7 +178,7 @@ static int tcf_em_validate(struct tcf_proto *tp,
struct tcf_ematch_hdr *em_hdr = nla_data(nla);
int data_len = nla_len(nla) - sizeof(*em_hdr);
void *data = (void *) em_hdr + sizeof(*em_hdr);
- struct net *net = dev_net(qdisc_dev(tp->q));
+ struct net *net = tp->chain->block->net;
if (!TCF_EM_REL_VALID(em_hdr->flags))
goto errout;
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (4 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 05/34] net: sched: ematch: obtain net pointer from blocks Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 21:45 ` Daniel Borkmann
2017-10-12 17:17 ` [patch net-next 07/34] net: sched: cls_u32: use block instead of q in tc_u_common Jiri Pirko
` (29 subsequent siblings)
35 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
dev->ingress_queue which stores the same pointer instead.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/core/dev.c | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index fcddccb..cb9e5e5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
static struct sk_buff *
sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
{
+ struct netdev_queue *netdev_queue =
+ rcu_dereference_bh(dev->ingress_queue);
struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
struct tcf_result cl_res;
+ struct Qdisc *q;
- if (!cl)
+ if (!cl || !netdev_queue)
return skb;
+ q = netdev_queue->qdisc;
/* qdisc_skb_cb(skb)->pkt_len was already set by the caller. */
- qdisc_bstats_cpu_update(cl->q, skb);
+ qdisc_bstats_cpu_update(q, skb);
switch (tcf_classify(skb, cl, &cl_res, false)) {
case TC_ACT_OK:
@@ -3288,7 +3292,7 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
skb->tc_index = TC_H_MIN(cl_res.classid);
break;
case TC_ACT_SHOT:
- qdisc_qstats_cpu_drop(cl->q);
+ qdisc_qstats_cpu_drop(q);
*ret = NET_XMIT_DROP;
kfree_skb(skb);
return NULL;
@@ -4188,16 +4192,21 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
struct net_device *orig_dev)
{
#ifdef CONFIG_NET_CLS_ACT
+ struct netdev_queue *netdev_queue =
+ rcu_dereference_bh(skb->dev->ingress_queue);
struct tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list);
struct tcf_result cl_res;
+ struct Qdisc *q;
/* If there's at least one ingress present somewhere (so
* we get here via enabled static key), remaining devices
* that are not configured with an ingress qdisc will bail
* out here.
*/
- if (!cl)
+ if (!cl || !netdev_queue)
return skb;
+ q = netdev_queue->qdisc;
+
if (*pt_prev) {
*ret = deliver_skb(skb, *pt_prev, orig_dev);
*pt_prev = NULL;
@@ -4205,7 +4214,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
qdisc_skb_cb(skb)->pkt_len = skb->len;
skb->tc_at_ingress = 1;
- qdisc_bstats_cpu_update(cl->q, skb);
+ qdisc_bstats_cpu_update(q, skb);
switch (tcf_classify(skb, cl, &cl_res, false)) {
case TC_ACT_OK:
@@ -4213,7 +4222,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
skb->tc_index = TC_H_MIN(cl_res.classid);
break;
case TC_ACT_SHOT:
- qdisc_qstats_cpu_drop(cl->q);
+ qdisc_qstats_cpu_drop(q);
kfree_skb(skb);
return NULL;
case TC_ACT_STOLEN:
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 07/34] net: sched: cls_u32: use block instead of q in tc_u_common
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (5 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 08/34] net: sched: avoid usage of tp->q in tcf_classify Jiri Pirko
` (28 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
tc_u_common is now per-q. With blocks, it has to be converted to be
per-block.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_u32.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 094d224..b6d4606 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -93,7 +93,7 @@ struct tc_u_hnode {
struct tc_u_common {
struct tc_u_hnode __rcu *hlist;
- struct Qdisc *q;
+ struct tcf_block *block;
int refcnt;
struct idr handle_idr;
struct hlist_node hnode;
@@ -335,11 +335,7 @@ static struct hlist_head *tc_u_common_hash;
static unsigned int tc_u_hash(const struct tcf_proto *tp)
{
- struct net_device *dev = tp->q->dev_queue->dev;
- u32 qhandle = tp->q->handle;
- int ifindex = dev->ifindex;
-
- return hash_64((u64)ifindex << 32 | qhandle, U32_HASH_SHIFT);
+ return hash_64((u64) tp->chain->block, U32_HASH_SHIFT);
}
static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
@@ -349,7 +345,7 @@ static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
h = tc_u_hash(tp);
hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) {
- if (tc->q == tp->q)
+ if (tc->block == tp->chain->block)
return tc;
}
return NULL;
@@ -378,7 +374,7 @@ static int u32_init(struct tcf_proto *tp)
kfree(root_ht);
return -ENOBUFS;
}
- tp_c->q = tp->q;
+ tp_c->block = tp->chain->block;
INIT_HLIST_NODE(&tp_c->hnode);
idr_init(&tp_c->handle_idr);
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 08/34] net: sched: avoid usage of tp->q in tcf_classify
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (6 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 07/34] net: sched: cls_u32: use block instead of q in tc_u_common Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 09/34] net: sched: tcindex, fw, flow: use tcf_block_q helper to get struct Qdisc Jiri Pirko
` (27 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
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 2d0f18f..b1bcc8b 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -501,8 +501,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] 53+ messages in thread
* [patch net-next 09/34] net: sched: tcindex, fw, flow: use tcf_block_q helper to get struct Qdisc
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (7 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 08/34] net: sched: avoid usage of tp->q in tcf_classify Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 10/34] net: sched: use tcf_block_q helper to get q pointer for sch_tree_lock Jiri Pirko
` (26 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Use helper to get q pointer per block.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flow.c | 7 +++++--
net/sched/cls_fw.c | 5 ++++-
net/sched/cls_tcindex.c | 5 ++++-
3 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 2a3a60e..f3be666 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -491,8 +491,11 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
perturb_period = nla_get_u32(tb[TCA_FLOW_PERTURB]) * HZ;
}
- if (TC_H_MAJ(baseclass) == 0)
- baseclass = TC_H_MAKE(tp->q->handle, baseclass);
+ if (TC_H_MAJ(baseclass) == 0) {
+ struct Qdisc *q = tcf_block_q(tp->chain->block);
+
+ baseclass = TC_H_MAKE(q->handle, baseclass);
+ }
if (TC_H_MIN(baseclass) == 0)
baseclass = TC_H_MAKE(baseclass, 1);
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 941245a..aa1e1f3 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -28,6 +28,7 @@
#include <net/netlink.h>
#include <net/act_api.h>
#include <net/pkt_cls.h>
+#include <net/sch_generic.h>
#define HTSIZE 256
@@ -83,9 +84,11 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp,
}
}
} else {
+ struct Qdisc *q = tcf_block_q(tp->chain->block);
+
/* Old method: classify the packet using its skb mark. */
if (id && (TC_H_MAJ(id) == 0 ||
- !(TC_H_MAJ(id ^ tp->q->handle)))) {
+ !(TC_H_MAJ(id ^ q->handle)))) {
res->classid = id;
res->class = 0;
return 0;
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 14a7e08..d732b54 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -13,6 +13,7 @@
#include <net/act_api.h>
#include <net/netlink.h>
#include <net/pkt_cls.h>
+#include <net/sch_generic.h>
/*
* Passing parameters to the root seems to be done more awkwardly than really
@@ -90,9 +91,11 @@ static int tcindex_classify(struct sk_buff *skb, const struct tcf_proto *tp,
f = tcindex_lookup(p, key);
if (!f) {
+ struct Qdisc *q = tcf_block_q(tp->chain->block);
+
if (!p->fall_through)
return -1;
- res->classid = TC_H_MAKE(TC_H_MAJ(tp->q->handle), key);
+ res->classid = TC_H_MAKE(TC_H_MAJ(q->handle), key);
res->class = 0;
pr_debug("alg 0x%x\n", res->classid);
return 0;
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 10/34] net: sched: use tcf_block_q helper to get q pointer for sch_tree_lock
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (8 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 09/34] net: sched: tcindex, fw, flow: use tcf_block_q helper to get struct Qdisc Jiri Pirko
@ 2017-10-12 17:17 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 11/34] net: sched: propagate q and parent from caller down to tcf_fill_node Jiri Pirko
` (25 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:17 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Use tcf_block_q helper to get q pointer to be used for direct call of
sch_tree_lock/unlock instead of tcf_tree_lock/unlock.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/sch_generic.h | 3 ---
net/sched/sch_api.c | 6 ++++--
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 0b2ba3b..a4926c9 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -361,9 +361,6 @@ static inline void sch_tree_unlock(const struct Qdisc *q)
spin_unlock_bh(qdisc_root_sleeping_lock(q));
}
-#define tcf_tree_lock(tp) sch_tree_lock((tp)->q)
-#define tcf_tree_unlock(tp) sch_tree_unlock((tp)->q)
-
extern struct Qdisc noop_qdisc;
extern struct Qdisc_ops noop_qdisc_ops;
extern struct Qdisc_ops pfifo_fast_ops;
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index aa82116..a9ac912 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1661,9 +1661,11 @@ static int tcf_node_bind(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
struct tcf_bind_args *a = (void *)arg;
if (tp->ops->bind_class) {
- tcf_tree_lock(tp);
+ struct Qdisc *q = tcf_block_q(tp->chain->block);
+
+ sch_tree_lock(q);
tp->ops->bind_class(n, a->classid, a->cl);
- tcf_tree_unlock(tp);
+ sch_tree_unlock(q);
}
return 0;
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 11/34] net: sched: propagate q and parent from caller down to tcf_fill_node
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (9 preceding siblings ...)
2017-10-12 17:17 ` [patch net-next 10/34] net: sched: use tcf_block_q helper to get q pointer for sch_tree_lock Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 12/34] net: sched: add block bind/unbind notification to drivers Jiri Pirko
` (24 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
The callers have this info, they will pass it down to tcf_fill_node.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_api.c | 55 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 20 deletions(-)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b1bcc8b..908b38a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -585,8 +585,8 @@ static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,
}
static int tcf_fill_node(struct net *net, struct sk_buff *skb,
- struct tcf_proto *tp, void *fh, u32 portid,
- u32 seq, u16 flags, int event)
+ struct tcf_proto *tp, struct Qdisc *q, u32 parent,
+ void *fh, u32 portid, u32 seq, u16 flags, int event)
{
struct tcmsg *tcm;
struct nlmsghdr *nlh;
@@ -599,8 +599,8 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb,
tcm->tcm_family = AF_UNSPEC;
tcm->tcm__pad1 = 0;
tcm->tcm__pad2 = 0;
- tcm->tcm_ifindex = qdisc_dev(tp->q)->ifindex;
- tcm->tcm_parent = tp->classid;
+ tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
+ tcm->tcm_parent = parent;
tcm->tcm_info = TC_H_MAKE(tp->prio, tp->protocol);
if (nla_put_string(skb, TCA_KIND, tp->ops->kind))
goto nla_put_failure;
@@ -623,6 +623,7 @@ static int tcf_fill_node(struct net *net, struct sk_buff *skb,
static int tfilter_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp,
+ struct Qdisc *q, u32 parent,
void *fh, int event, bool unicast)
{
struct sk_buff *skb;
@@ -632,7 +633,7 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
if (!skb)
return -ENOBUFS;
- if (tcf_fill_node(net, skb, tp, fh, portid, n->nlmsg_seq,
+ if (tcf_fill_node(net, skb, tp, q, parent, fh, portid, n->nlmsg_seq,
n->nlmsg_flags, event) <= 0) {
kfree_skb(skb);
return -EINVAL;
@@ -647,6 +648,7 @@ static int tfilter_notify(struct net *net, struct sk_buff *oskb,
static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
struct nlmsghdr *n, struct tcf_proto *tp,
+ struct Qdisc *q, u32 parent,
void *fh, bool unicast, bool *last)
{
struct sk_buff *skb;
@@ -657,7 +659,7 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
if (!skb)
return -ENOBUFS;
- if (tcf_fill_node(net, skb, tp, fh, portid, n->nlmsg_seq,
+ if (tcf_fill_node(net, skb, tp, q, parent, fh, portid, n->nlmsg_seq,
n->nlmsg_flags, RTM_DELTFILTER) <= 0) {
kfree_skb(skb);
return -EINVAL;
@@ -677,6 +679,7 @@ static int tfilter_del_notify(struct net *net, struct sk_buff *oskb,
}
static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
+ struct Qdisc *q, u32 parent,
struct nlmsghdr *n,
struct tcf_chain *chain, int event)
{
@@ -684,7 +687,7 @@ static void tfilter_notify_chain(struct net *net, struct sk_buff *oskb,
for (tp = rtnl_dereference(chain->filter_chain);
tp; tp = rtnl_dereference(tp->next))
- tfilter_notify(net, oskb, n, tp, 0, event, false);
+ tfilter_notify(net, oskb, n, tp, q, parent, 0, event, false);
}
/* Add/change/delete/get a filter node */
@@ -803,7 +806,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
}
if (n->nlmsg_type == RTM_DELTFILTER && prio == 0) {
- tfilter_notify_chain(net, skb, n, chain, RTM_DELTFILTER);
+ tfilter_notify_chain(net, skb, q, parent, n,
+ chain, RTM_DELTFILTER);
tcf_chain_flush(chain);
err = 0;
goto errout;
@@ -850,7 +854,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
if (!fh) {
if (n->nlmsg_type == RTM_DELTFILTER && t->tcm_handle == 0) {
tcf_chain_tp_remove(chain, &chain_info, tp);
- tfilter_notify(net, skb, n, tp, fh,
+ tfilter_notify(net, skb, n, tp, q, parent, fh,
RTM_DELTFILTER, false);
tcf_proto_destroy(tp);
err = 0;
@@ -875,8 +879,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
}
break;
case RTM_DELTFILTER:
- err = tfilter_del_notify(net, skb, n, tp, fh, false,
- &last);
+ err = tfilter_del_notify(net, skb, n, tp, q, parent,
+ fh, false, &last);
if (err)
goto errout;
if (last) {
@@ -885,7 +889,7 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
}
goto errout;
case RTM_GETTFILTER:
- err = tfilter_notify(net, skb, n, tp, fh,
+ err = tfilter_notify(net, skb, n, tp, q, parent, fh,
RTM_NEWTFILTER, true);
goto errout;
default:
@@ -899,7 +903,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
if (err == 0) {
if (tp_created)
tcf_chain_tp_insert(chain, &chain_info, tp);
- tfilter_notify(net, skb, n, tp, fh, RTM_NEWTFILTER, false);
+ tfilter_notify(net, skb, n, tp, q, parent, fh,
+ RTM_NEWTFILTER, false);
} else {
if (tp_created)
tcf_proto_destroy(tp);
@@ -918,6 +923,8 @@ struct tcf_dump_args {
struct tcf_walker w;
struct sk_buff *skb;
struct netlink_callback *cb;
+ struct Qdisc *q;
+ u32 parent;
};
static int tcf_node_dump(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
@@ -925,13 +932,14 @@ static int tcf_node_dump(struct tcf_proto *tp, void *n, struct tcf_walker *arg)
struct tcf_dump_args *a = (void *)arg;
struct net *net = sock_net(a->skb->sk);
- return tcf_fill_node(net, a->skb, tp, n, NETLINK_CB(a->cb->skb).portid,
+ return tcf_fill_node(net, a->skb, tp, a->q, a->parent,
+ n, NETLINK_CB(a->cb->skb).portid,
a->cb->nlh->nlmsg_seq, NLM_F_MULTI,
RTM_NEWTFILTER);
}
-static bool tcf_chain_dump(struct tcf_chain *chain, struct sk_buff *skb,
- struct netlink_callback *cb,
+static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent,
+ struct sk_buff *skb, struct netlink_callback *cb,
long index_start, long *p_index)
{
struct net *net = sock_net(skb->sk);
@@ -953,7 +961,7 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct sk_buff *skb,
memset(&cb->args[1], 0,
sizeof(cb->args) - sizeof(cb->args[0]));
if (cb->args[1] == 0) {
- if (tcf_fill_node(net, skb, tp, 0,
+ if (tcf_fill_node(net, skb, tp, q, parent, 0,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
RTM_NEWTFILTER) <= 0)
@@ -966,6 +974,8 @@ static bool tcf_chain_dump(struct tcf_chain *chain, struct sk_buff *skb,
arg.w.fn = tcf_node_dump;
arg.skb = skb;
arg.cb = cb;
+ arg.q = q;
+ arg.parent = parent;
arg.w.stop = 0;
arg.w.skip = cb->args[1] - 1;
arg.w.count = 0;
@@ -991,6 +1001,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
const struct Qdisc_class_ops *cops;
long index_start;
long index;
+ u32 parent;
int err;
if (nlmsg_len(cb->nlh) < sizeof(*tcm))
@@ -1004,10 +1015,13 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
if (!dev)
return skb->len;
- if (!tcm->tcm_parent)
+ parent = tcm->tcm_parent;
+ if (!parent) {
q = dev->qdisc;
- else
+ parent = q->handle;
+ } else {
q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
+ }
if (!q)
goto out;
cops = q->ops->cl_ops;
@@ -1031,7 +1045,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
if (tca[TCA_CHAIN] &&
nla_get_u32(tca[TCA_CHAIN]) != chain->index)
continue;
- if (!tcf_chain_dump(chain, skb, cb, index_start, &index))
+ if (!tcf_chain_dump(chain, q, parent, skb, cb,
+ index_start, &index))
break;
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 12/34] net: sched: add block bind/unbind notification to drivers
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (10 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 11/34] net: sched: propagate q and parent from caller down to tcf_fill_node Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 13/34] net: sched: introduce per-block callbacks Jiri Pirko
` (23 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Introduce new type of ndo_setup_tc message to propage binding/unbinding
of a block to binder.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/linux/netdevice.h | 1 +
include/net/pkt_cls.h | 21 +++++++++++++++++++--
include/net/sch_generic.h | 1 +
net/sched/cls_api.c | 33 +++++++++++++++++++++++++++++++--
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 31bb301..062a4f5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -771,6 +771,7 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
enum tc_setup_type {
TC_SETUP_MQPRIO,
+ TC_SETUP_BLOCK,
TC_SETUP_CLSU32,
TC_SETUP_CLSFLOWER,
TC_SETUP_CLSMATCHALL,
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 05bc999..104326fc 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -17,9 +17,15 @@ struct tcf_walker {
int register_tcf_proto_ops(struct tcf_proto_ops *ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
+enum tcf_block_binder_type {
+ TCF_BLOCK_BINDER_TYPE_UNSPEC,
+};
+
struct tcf_block_ext_info {
bool shareable;
u32 block_index;
+ enum tcf_block_binder_type binder_type;
+ bool bound;
};
#ifdef CONFIG_NET_CLS
@@ -34,7 +40,7 @@ int tcf_block_get_ext(struct tcf_block **p_block,
struct tcf_block_ext_info *ei);
void tcf_block_put(struct tcf_block *block);
void tcf_block_put_ext(struct tcf_block *block,
- struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
struct tcf_block_ext_info *ei);
static inline bool tcf_is_block_shared(const struct tcf_block *block)
@@ -79,7 +85,7 @@ void tcf_block_put(struct tcf_block *block)
static inline
void tcf_block_put_ext(struct tcf_block *block,
- struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
struct tcf_block_ext_info *ei)
{
}
@@ -468,6 +474,17 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
int tc_setup_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
void *type_data, bool err_stop);
+enum tc_block_command {
+ TC_BLOCK_BIND,
+ TC_BLOCK_UNBIND,
+};
+
+struct tc_block_offload {
+ enum tc_block_command command;
+ enum tcf_block_binder_type binder_type;
+ struct tcf_block *block;
+};
+
struct tc_cls_common_offload {
u32 chain_index;
__be16 protocol;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index a4926c9..e210452 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -69,6 +69,7 @@ struct Qdisc {
* qdisc_tree_decrease_qlen() should stop.
*/
#define TCQ_F_INVISIBLE 0x80 /* invisible by default in dump */
+#define TCQ_F_BOUNDOFFLOAD 0x100 /* bound to the offload driver */
u32 limit;
const struct Qdisc_ops *ops;
struct qdisc_size_table __rcu *stab;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 908b38a..8f6e2c9 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -377,6 +377,33 @@ static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block)
return list_first_entry(&block->chain_list, struct tcf_chain, list);
}
+static void tcf_block_offload_cmd(struct tcf_block *block, struct Qdisc *q,
+ struct tcf_block_ext_info *ei,
+ enum tc_block_command command)
+{
+ struct net_device *dev = q->dev_queue->dev;
+ struct tc_block_offload bo = {};
+
+ if (!tc_can_offload(dev))
+ return;
+ bo.command = command;
+ bo.binder_type = ei->binder_type;
+ bo.block = block;
+ dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+}
+
+static void tcf_block_offload_bind(struct tcf_block *block, struct Qdisc *q,
+ struct tcf_block_ext_info *ei)
+{
+ tcf_block_offload_cmd(block, q, ei, TC_BLOCK_BIND);
+}
+
+static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
+ struct tcf_block_ext_info *ei)
+{
+ tcf_block_offload_cmd(block, q, ei, TC_BLOCK_UNBIND);
+}
+
int tcf_block_get_ext(struct tcf_block **p_block,
struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
struct tcf_block_ext_info *ei)
@@ -409,6 +436,7 @@ int tcf_block_get_ext(struct tcf_block **p_block,
if (err)
goto err_chain_filter_chain_ptr_add;
+ tcf_block_offload_bind(block, q, ei);
*p_block = block;
return 0;
@@ -435,12 +463,13 @@ int tcf_block_get(struct tcf_block **p_block,
EXPORT_SYMBOL(tcf_block_get);
void tcf_block_put_ext(struct tcf_block *block,
- struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
struct tcf_block_ext_info *ei)
{
if (!block)
return;
+ tcf_block_offload_unbind(block, q, ei);
tcf_chain_filter_chain_ptr_del(tcf_block_chain_zero(block),
p_filter_chain);
@@ -456,7 +485,7 @@ void tcf_block_put(struct tcf_block *block)
{
struct tcf_block_ext_info ei = {0, };
- tcf_block_put_ext(block, NULL, &ei);
+ tcf_block_put_ext(block, NULL, block->q, &ei);
}
EXPORT_SYMBOL(tcf_block_put);
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 13/34] net: sched: introduce per-block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (11 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 12/34] net: sched: add block bind/unbind notification to drivers Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 14/34] net: sched: use extended variants of block get and put in ingress and clsact qdiscs Jiri Pirko
` (22 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Introduce infrastructure that allows drivers to register callbacks that
are called whenever tc would offload inserted rule for a specific block.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 81 ++++++++++++++++++++++++++++++++++++
include/net/sch_generic.h | 1 +
net/sched/cls_api.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 186 insertions(+)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 104326fc..febd52e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -28,6 +28,8 @@ struct tcf_block_ext_info {
bool bound;
};
+struct tcf_block_cb;
+
#ifdef CONFIG_NET_CLS
struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
bool create);
@@ -59,6 +61,21 @@ static inline struct net_device *tcf_block_dev(struct tcf_block *block)
return tcf_block_q(block)->dev_queue->dev;
}
+void *tcf_block_cb_priv(struct tcf_block_cb *block_cb);
+struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident);
+void tcf_block_cb_incref(struct tcf_block_cb *block_cb);
+unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb);
+struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv);
+int tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv);
+void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb);
+void tcf_block_cb_unregister(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident);
+
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode);
@@ -100,6 +117,70 @@ static inline bool tcf_is_block_shared(const struct tcf_block *block)
return false;
}
+static inline
+int tc_setup_cb_block_register(struct tcf_block *block, tc_setup_cb_t *cb,
+ void *cb_priv)
+{
+ return 0;
+}
+
+static inline
+void tc_setup_cb_block_unregister(struct tcf_block *block, tc_setup_cb_t *cb,
+ void *cb_priv)
+{
+}
+
+static inline
+void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
+{
+ return NULL;
+}
+
+static inline
+struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{
+ return NULL;
+}
+
+static inline
+void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
+{
+}
+
+static inline
+unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
+{
+ return 0;
+}
+
+static inline
+struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv)
+{
+ return NULL;
+}
+
+static inline
+int tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv)
+{
+ return 0;
+}
+
+static inline
+void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
+{
+}
+
+static inline
+void tcf_block_cb_unregister(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{
+}
+
static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res, bool compat_mode)
{
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index e210452..dfa9617 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -275,6 +275,7 @@ struct tcf_block {
unsigned int refcnt;
struct net *net;
struct Qdisc *q;
+ struct list_head cb_list;
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 8f6e2c9..7837c8a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -319,6 +319,7 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q)
block->refcnt = 1;
block->net = net;
block->q = q;
+ INIT_LIST_HEAD(&block->cb_list);
/* Create chain 0 by default, it has to be always present. */
chain = tcf_chain_create(block, 0);
@@ -489,6 +490,109 @@ void tcf_block_put(struct tcf_block *block)
}
EXPORT_SYMBOL(tcf_block_put);
+struct tcf_block_cb {
+ struct list_head list;
+ tc_setup_cb_t *cb;
+ void *cb_ident;
+ void *cb_priv;
+ unsigned int refcnt;
+};
+
+void *tcf_block_cb_priv(struct tcf_block_cb *block_cb)
+{
+ return block_cb->cb_priv;
+}
+EXPORT_SYMBOL(tcf_block_cb_priv);
+
+struct tcf_block_cb *tcf_block_cb_lookup(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{ struct tcf_block_cb *block_cb;
+
+ list_for_each_entry(block_cb, &block->cb_list, list)
+ if (block_cb->cb == cb && block_cb->cb_ident == cb_ident)
+ return block_cb;
+ return NULL;
+}
+EXPORT_SYMBOL(tcf_block_cb_lookup);
+
+void tcf_block_cb_incref(struct tcf_block_cb *block_cb)
+{
+ block_cb->refcnt++;
+}
+EXPORT_SYMBOL(tcf_block_cb_incref);
+
+unsigned int tcf_block_cb_decref(struct tcf_block_cb *block_cb)
+{
+ return --block_cb->refcnt;
+}
+EXPORT_SYMBOL(tcf_block_cb_decref);
+
+struct tcf_block_cb *__tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
+ if (!block_cb)
+ return NULL;
+ block_cb->cb = cb;
+ block_cb->cb_ident = cb_ident;
+ block_cb->cb_priv = cb_priv;
+ list_add(&block_cb->list, &block->cb_list);
+ return block_cb;
+}
+EXPORT_SYMBOL(__tcf_block_cb_register);
+
+int tcf_block_cb_register(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident,
+ void *cb_priv)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = __tcf_block_cb_register(block, cb, cb_ident, cb_priv);
+ return block_cb ? 0 : -ENOMEM;
+}
+EXPORT_SYMBOL(tcf_block_cb_register);
+
+void __tcf_block_cb_unregister(struct tcf_block_cb *block_cb)
+{
+ list_del(&block_cb->list);
+ kfree(block_cb);
+}
+EXPORT_SYMBOL(__tcf_block_cb_unregister);
+
+void tcf_block_cb_unregister(struct tcf_block *block,
+ tc_setup_cb_t *cb, void *cb_ident)
+{
+ struct tcf_block_cb *block_cb;
+
+ block_cb = tcf_block_cb_lookup(block, cb, cb_ident);
+ if (!block_cb)
+ return;
+ __tcf_block_cb_unregister(block_cb);
+}
+EXPORT_SYMBOL(tcf_block_cb_unregister);
+
+static int tcf_block_cb_call(struct tcf_block *block, enum tc_setup_type type,
+ void *type_data, bool err_stop)
+{
+ struct tcf_block_cb *block_cb;
+ int ok_count = 0;
+ int err;
+
+ list_for_each_entry(block_cb, &block->cb_list, list) {
+ err = block_cb->cb(type, type_data, block_cb->cb_priv);
+ if (err) {
+ if (err_stop)
+ return err;
+ } else {
+ ok_count++;
+ }
+ }
+ return ok_count;
+}
+
/* Main classifier routine: scans classifier chain attached
* to this qdisc, (optionally) tests for protocol and asks
* specific classifiers.
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 14/34] net: sched: use extended variants of block get and put in ingress and clsact qdiscs
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (12 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 13/34] net: sched: introduce per-block callbacks Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 15/34] net: sched: use tc_setup_cb_call to call per-block callbacks Jiri Pirko
` (21 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Use previously introduced extended variants of block get and put
functions. This allows to specify a binder types specific to clsact
ingress/egress which is useful for drivers to distinguish who actually
got the block.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 2 ++
net/sched/sch_ingress.c | 36 +++++++++++++++++++++++++++++-------
2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index febd52e..4e6cdf4 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -19,6 +19,8 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
enum tcf_block_binder_type {
TCF_BLOCK_BINDER_TYPE_UNSPEC,
+ TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS,
+ TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS,
};
struct tcf_block_ext_info {
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 9ccc1b8..b599db2 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -20,6 +20,7 @@
struct ingress_sched_data {
struct tcf_block *block;
+ struct tcf_block_ext_info block_info;
};
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
@@ -59,7 +60,10 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
struct net_device *dev = qdisc_dev(sch);
int err;
- err = tcf_block_get(&q->block, &dev->ingress_cl_list, sch);
+ q->block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+
+ err = tcf_block_get_ext(&q->block, &dev->ingress_cl_list,
+ sch, &q->block_info);
if (err)
return err;
@@ -72,8 +76,10 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
static void ingress_destroy(struct Qdisc *sch)
{
struct ingress_sched_data *q = qdisc_priv(sch);
+ struct net_device *dev = qdisc_dev(sch);
- tcf_block_put(q->block);
+ tcf_block_put_ext(q->block, &dev->ingress_cl_list,
+ sch, &q->block_info);
net_dec_ingress_queue();
}
@@ -114,6 +120,8 @@ static struct Qdisc_ops ingress_qdisc_ops __read_mostly = {
struct clsact_sched_data {
struct tcf_block *ingress_block;
struct tcf_block *egress_block;
+ struct tcf_block_ext_info ingress_block_info;
+ struct tcf_block_ext_info egress_block_info;
};
static unsigned long clsact_find(struct Qdisc *sch, u32 classid)
@@ -153,13 +161,19 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
struct net_device *dev = qdisc_dev(sch);
int err;
- err = tcf_block_get(&q->ingress_block, &dev->ingress_cl_list, sch);
+ q->ingress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+
+ err = tcf_block_get_ext(&q->ingress_block, &dev->ingress_cl_list,
+ sch, &q->ingress_block_info);
if (err)
return err;
- err = tcf_block_get(&q->egress_block, &dev->egress_cl_list, sch);
+ q->egress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS;
+
+ err = tcf_block_get_ext(&q->egress_block, &dev->egress_cl_list,
+ sch, &q->egress_block_info);
if (err)
- return err;
+ goto err_egress_block_get;
net_inc_ingress_queue();
net_inc_egress_queue();
@@ -167,14 +181,22 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
sch->flags |= TCQ_F_CPUSTATS;
return 0;
+
+err_egress_block_get:
+ tcf_block_put_ext(q->ingress_block, &dev->ingress_cl_list,
+ sch, &q->ingress_block_info);
+ return err;
}
static void clsact_destroy(struct Qdisc *sch)
{
struct clsact_sched_data *q = qdisc_priv(sch);
+ struct net_device *dev = qdisc_dev(sch);
- tcf_block_put(q->egress_block);
- tcf_block_put(q->ingress_block);
+ tcf_block_put_ext(q->egress_block, &dev->egress_cl_list,
+ sch, &q->egress_block_info);
+ tcf_block_put_ext(q->ingress_block, &dev->ingress_cl_list,
+ sch, &q->ingress_block_info);
net_dec_ingress_queue();
net_dec_egress_queue();
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 15/34] net: sched: use tc_setup_cb_call to call per-block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (13 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 14/34] net: sched: use extended variants of block get and put in ingress and clsact qdiscs Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 16/34] net: sched: cls_matchall: call block callbacks for offload Jiri Pirko
` (20 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Extend the tc_setup_cb_call entrypoint function originally used only for
action egress devices callbacks to call per-block callbacks as well.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 4 ++--
net/sched/cls_api.c | 21 ++++++++++++++++++---
net/sched/cls_flower.c | 9 ++++++---
3 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 4e6cdf4..2e73832 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -554,8 +554,8 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
}
#endif /* CONFIG_NET_CLS_IND */
-int tc_setup_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
- void *type_data, bool err_stop);
+int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
+ enum tc_setup_type type, void *type_data, bool err_stop);
enum tc_block_command {
TC_BLOCK_BIND,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 7837c8a..5a647e0 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -1349,10 +1349,25 @@ static int tc_exts_setup_cb_egdev_call(struct tcf_exts *exts,
return ok_count;
}
-int tc_setup_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
- void *type_data, bool err_stop)
+int tc_setup_cb_call(struct tcf_block *block, struct tcf_exts *exts,
+ enum tc_setup_type type, void *type_data, bool err_stop)
{
- return tc_exts_setup_cb_egdev_call(exts, type, type_data, err_stop);
+ int ok_count;
+ int ret;
+
+ ret = tcf_block_cb_call(block, type, type_data, err_stop);
+ if (ret < 0)
+ return ret;
+ ok_count = ret;
+
+ if (!exts)
+ return ok_count;
+ ret = tc_exts_setup_cb_egdev_call(exts, type, type_data, err_stop);
+ if (ret < 0)
+ return ret;
+ ok_count += ret;
+
+ return ok_count;
}
EXPORT_SYMBOL(tc_setup_cb_call);
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 5b7bb96..76b4e0a 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -201,6 +201,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
{
struct tc_cls_flower_offload cls_flower = {};
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
tc_cls_common_offload_init(&cls_flower.common, tp);
cls_flower.command = TC_CLSFLOWER_DESTROY;
@@ -209,7 +210,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
if (tc_can_offload(dev))
dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
&cls_flower);
- tc_setup_cb_call(&f->exts, TC_SETUP_CLSFLOWER,
+ tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, false);
}
@@ -220,6 +221,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_flower_offload cls_flower = {};
+ struct tcf_block *block = tp->chain->block;
bool skip_sw = tc_skip_sw(f->flags);
int err;
@@ -242,7 +244,7 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
}
}
- err = tc_setup_cb_call(&f->exts, TC_SETUP_CLSFLOWER,
+ err = tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, skip_sw);
if (err < 0) {
fl_hw_destroy_filter(tp, f);
@@ -261,6 +263,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
{
struct tc_cls_flower_offload cls_flower = {};
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
tc_cls_common_offload_init(&cls_flower.common, tp);
cls_flower.command = TC_CLSFLOWER_STATS;
@@ -270,7 +273,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
if (tc_can_offload(dev))
dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
&cls_flower);
- tc_setup_cb_call(&f->exts, TC_SETUP_CLSFLOWER,
+ tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, false);
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 16/34] net: sched: cls_matchall: call block callbacks for offload
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (14 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 15/34] net: sched: use tc_setup_cb_call to call per-block callbacks Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 17/34] net: sched: cls_u32: swap u32_remove_hw_knode and u32_remove_hw_hnode Jiri Pirko
` (19 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Use the newly introduced callbacks infrastructure and call block
callbacks alongside with the existing per-netdev ndo_setup_tc.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_matchall.c | 72 ++++++++++++++++++++++++++++++------------------
1 file changed, 45 insertions(+), 27 deletions(-)
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index eeac606..5278534 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -50,50 +50,73 @@ static void mall_destroy_rcu(struct rcu_head *rcu)
kfree(head);
}
-static int mall_replace_hw_filter(struct tcf_proto *tp,
- struct cls_mall_head *head,
- unsigned long cookie)
+static void mall_destroy_hw_filter(struct tcf_proto *tp,
+ struct cls_mall_head *head,
+ unsigned long cookie)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_matchall_offload cls_mall = {};
- int err;
+ struct tcf_block *block = tp->chain->block;
tc_cls_common_offload_init(&cls_mall.common, tp);
- cls_mall.command = TC_CLSMATCHALL_REPLACE;
- cls_mall.exts = &head->exts;
+ cls_mall.command = TC_CLSMATCHALL_DESTROY;
cls_mall.cookie = cookie;
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSMATCHALL,
- &cls_mall);
- if (!err)
- head->flags |= TCA_CLS_FLAGS_IN_HW;
-
- return err;
+ if (tc_can_offload(dev))
+ dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSMATCHALL,
+ &cls_mall);
+ tc_setup_cb_call(block, NULL, TC_SETUP_CLSMATCHALL, &cls_mall, false);
}
-static void mall_destroy_hw_filter(struct tcf_proto *tp,
- struct cls_mall_head *head,
- unsigned long cookie)
+static int mall_replace_hw_filter(struct tcf_proto *tp,
+ struct cls_mall_head *head,
+ unsigned long cookie)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_matchall_offload cls_mall = {};
+ struct tcf_block *block = tp->chain->block;
+ bool skip_sw = tc_skip_sw(head->flags);
+ int err;
tc_cls_common_offload_init(&cls_mall.common, tp);
- cls_mall.command = TC_CLSMATCHALL_DESTROY;
+ cls_mall.command = TC_CLSMATCHALL_REPLACE;
+ cls_mall.exts = &head->exts;
cls_mall.cookie = cookie;
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSMATCHALL, &cls_mall);
+ if (tc_can_offload(dev)) {
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSMATCHALL,
+ &cls_mall);
+ if (err) {
+ if (skip_sw)
+ return err;
+ } else {
+ head->flags |= TCA_CLS_FLAGS_IN_HW;
+ }
+ }
+
+ err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSMATCHALL,
+ &cls_mall, skip_sw);
+ if (err < 0) {
+ mall_destroy_hw_filter(tp, head, cookie);
+ return err;
+ } else if (err > 0) {
+ head->flags |= TCA_CLS_FLAGS_IN_HW;
+ }
+
+ if (skip_sw && !(head->flags & TCA_CLS_FLAGS_IN_HW))
+ return -EINVAL;
+
+ return 0;
}
static void mall_destroy(struct tcf_proto *tp)
{
struct cls_mall_head *head = rtnl_dereference(tp->root);
- struct net_device *dev = tp->q->dev_queue->dev;
if (!head)
return;
- if (tc_should_offload(dev, head->flags))
+ if (!tc_skip_hw(head->flags))
mall_destroy_hw_filter(tp, head, (unsigned long) head);
call_rcu(&head->rcu, mall_destroy_rcu);
@@ -133,7 +156,6 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
void **arg, bool ovr)
{
struct cls_mall_head *head = rtnl_dereference(tp->root);
- struct net_device *dev = tp->q->dev_queue->dev;
struct nlattr *tb[TCA_MATCHALL_MAX + 1];
struct cls_mall_head *new;
u32 flags = 0;
@@ -173,14 +195,10 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
if (err)
goto err_set_parms;
- if (tc_should_offload(dev, flags)) {
+ if (!tc_skip_hw(new->flags)) {
err = mall_replace_hw_filter(tp, new, (unsigned long) new);
- if (err) {
- if (tc_skip_sw(flags))
- goto err_replace_hw_filter;
- else
- err = 0;
- }
+ if (err)
+ goto err_replace_hw_filter;
}
if (!tc_in_hw(new->flags))
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 17/34] net: sched: cls_u32: swap u32_remove_hw_knode and u32_remove_hw_hnode
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (15 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 16/34] net: sched: cls_matchall: call block callbacks for offload Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 18/34] net: sched: cls_u32: call block callbacks for offload Jiri Pirko
` (18 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_u32.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index b6d4606..f407f13 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -462,7 +462,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
return 0;
}
-static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
+static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_u32_offload cls_u32 = {};
@@ -471,8 +471,10 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
return;
tc_cls_common_offload_init(&cls_u32.common, tp);
- cls_u32.command = TC_CLSU32_DELETE_KNODE;
- cls_u32.knode.handle = handle;
+ cls_u32.command = TC_CLSU32_DELETE_HNODE;
+ cls_u32.hnode.divisor = h->divisor;
+ cls_u32.hnode.handle = h->handle;
+ cls_u32.hnode.prio = h->prio;
dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
}
@@ -500,7 +502,7 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
return 0;
}
-static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
+static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
{
struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_u32_offload cls_u32 = {};
@@ -509,10 +511,8 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
return;
tc_cls_common_offload_init(&cls_u32.common, tp);
- cls_u32.command = TC_CLSU32_DELETE_HNODE;
- cls_u32.hnode.divisor = h->divisor;
- cls_u32.hnode.handle = h->handle;
- cls_u32.hnode.prio = h->prio;
+ cls_u32.command = TC_CLSU32_DELETE_KNODE;
+ cls_u32.knode.handle = handle;
dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 18/34] net: sched: cls_u32: call block callbacks for offload
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (16 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 17/34] net: sched: cls_u32: swap u32_remove_hw_knode and u32_remove_hw_hnode Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 19/34] net: sched: cls_bpf: " Jiri Pirko
` (17 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Use the newly introduced callbacks infrastructure and call block
callbacks alongside with the existing per-netdev ndo_setup_tc.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_u32.c | 72 ++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 52 insertions(+), 20 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index f407f13..24cc429 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -465,39 +465,57 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
{
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
- if (!tc_should_offload(dev, 0))
- return;
-
tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_DELETE_HNODE;
cls_u32.hnode.divisor = h->divisor;
cls_u32.hnode.handle = h->handle;
cls_u32.hnode.prio = h->prio;
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
+ if (tc_can_offload(dev))
+ dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
+ tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
}
static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
u32 flags)
{
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
+ bool skip_sw = tc_skip_sw(flags);
+ bool offloaded = false;
int err;
- if (!tc_should_offload(dev, flags))
- return tc_skip_sw(flags) ? -EINVAL : 0;
-
tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_NEW_HNODE;
cls_u32.hnode.divisor = h->divisor;
cls_u32.hnode.handle = h->handle;
cls_u32.hnode.prio = h->prio;
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
- if (tc_skip_sw(flags))
+ if (tc_can_offload(dev)) {
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32,
+ &cls_u32);
+ if (err) {
+ if (skip_sw)
+ return err;
+ } else {
+ offloaded = true;
+ }
+ }
+
+ err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
+ if (err < 0) {
+ u32_clear_hw_hnode(tp, h);
return err;
+ } else if (err > 0) {
+ offloaded = true;
+ }
+
+ if (skip_sw && !offloaded)
+ return -EINVAL;
return 0;
}
@@ -505,28 +523,27 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
{
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
- if (!tc_should_offload(dev, 0))
- return;
-
tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_DELETE_KNODE;
cls_u32.knode.handle = handle;
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
+ if (tc_can_offload(dev))
+ dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
+ tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
}
static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
u32 flags)
{
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
+ bool skip_sw = tc_skip_sw(flags);
int err;
- if (!tc_should_offload(dev, flags))
- return tc_skip_sw(flags) ? -EINVAL : 0;
-
tc_cls_common_offload_init(&cls_u32.common, tp);
cls_u32.command = TC_CLSU32_REPLACE_KNODE;
cls_u32.knode.handle = n->handle;
@@ -543,13 +560,28 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
if (n->ht_down)
cls_u32.knode.link_handle = n->ht_down->handle;
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
- if (!err)
- n->flags |= TCA_CLS_FLAGS_IN_HW;
+ if (tc_can_offload(dev)) {
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32,
+ &cls_u32);
+ if (err) {
+ if (skip_sw)
+ return err;
+ } else {
+ n->flags |= TCA_CLS_FLAGS_IN_HW;
+ }
+ }
- if (tc_skip_sw(flags))
+ err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
+ if (err < 0) {
+ u32_remove_hw_knode(tp, n->handle);
return err;
+ } else if (err > 0) {
+ n->flags |= TCA_CLS_FLAGS_IN_HW;
+ }
+
+ if (skip_sw && !(n->flags && TCA_CLS_FLAGS_IN_HW))
+ return -EINVAL;
return 0;
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 19/34] net: sched: cls_bpf: call block callbacks for offload
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (17 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 18/34] net: sched: cls_u32: call block callbacks for offload Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 20/34] mlxsw: spectrum: Convert ndo_setup_tc offloads to block callbacks Jiri Pirko
` (16 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Use the newly introduced callbacks infrastructure and call block
callbacks alongside with the existing per-netdev ndo_setup_tc.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_bpf.c | 40 ++++++++++++++++++++++++++++++++--------
1 file changed, 32 insertions(+), 8 deletions(-)
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 6c6b21f..e379fdf 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -147,7 +147,10 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)
static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
enum tc_clsbpf_command cmd)
{
+ bool addorrep = cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE;
struct net_device *dev = tp->q->dev_queue->dev;
+ struct tcf_block *block = tp->chain->block;
+ bool skip_sw = tc_skip_sw(prog->gen_flags);
struct tc_cls_bpf_offload cls_bpf = {};
int err;
@@ -159,17 +162,38 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_flags;
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSBPF, &cls_bpf);
- if (!err && (cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE))
- prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
+ if (tc_can_offload(dev)) {
+ err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSBPF,
+ &cls_bpf);
+ if (addorrep) {
+ if (err) {
+ if (skip_sw)
+ return err;
+ } else {
+ prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
+ }
+ }
+ }
+
+ err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw);
+ if (addorrep) {
+ if (err < 0) {
+ cls_bpf_offload_cmd(tp, prog, TC_CLSBPF_DESTROY);
+ return err;
+ } else if (err > 0) {
+ prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
+ }
+ }
- return err;
+ if (addorrep && skip_sw && !(prog->gen_flags && TCA_CLS_FLAGS_IN_HW))
+ return -EINVAL;
+
+ return 0;
}
static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
struct cls_bpf_prog *oldprog)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct cls_bpf_prog *obj = prog;
enum tc_clsbpf_command cmd;
bool skip_sw;
@@ -179,7 +203,7 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
(oldprog && tc_skip_sw(oldprog->gen_flags));
if (oldprog && oldprog->offloaded) {
- if (tc_should_offload(dev, prog->gen_flags)) {
+ if (!tc_skip_hw(prog->gen_flags)) {
cmd = TC_CLSBPF_REPLACE;
} else if (!tc_skip_sw(prog->gen_flags)) {
obj = oldprog;
@@ -188,14 +212,14 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,
return -EINVAL;
}
} else {
- if (!tc_should_offload(dev, prog->gen_flags))
+ if (tc_skip_hw(prog->gen_flags))
return skip_sw ? -EINVAL : 0;
cmd = TC_CLSBPF_ADD;
}
ret = cls_bpf_offload_cmd(tp, obj, cmd);
if (ret)
- return skip_sw ? ret : 0;
+ return ret;
obj->offloaded = true;
if (oldprog)
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 20/34] mlxsw: spectrum: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (18 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 19/34] net: sched: cls_bpf: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 21/34] mlx5e: " Jiri Pirko
` (15 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for matchall and flower offloads to block
callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 82 +++++++++++++++++++-------
1 file changed, 60 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 4328ace..ad1f651 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1697,17 +1697,9 @@ static void mlxsw_sp_port_del_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
}
static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tc_cls_matchall_offload *f)
+ struct tc_cls_matchall_offload *f,
+ bool ingress)
{
- bool ingress;
-
- if (is_classid_clsact_ingress(f->common.classid))
- ingress = true;
- else if (is_classid_clsact_egress(f->common.classid))
- ingress = false;
- else
- return -EOPNOTSUPP;
-
if (f->common.chain_index)
return -EOPNOTSUPP;
@@ -1725,17 +1717,9 @@ static int mlxsw_sp_setup_tc_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
static int
mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_port *mlxsw_sp_port,
- struct tc_cls_flower_offload *f)
+ struct tc_cls_flower_offload *f,
+ bool ingress)
{
- bool ingress;
-
- if (is_classid_clsact_ingress(f->common.classid))
- ingress = true;
- else if (is_classid_clsact_egress(f->common.classid))
- ingress = false;
- else
- return -EOPNOTSUPP;
-
switch (f->command) {
case TC_CLSFLOWER_REPLACE:
return mlxsw_sp_flower_replace(mlxsw_sp_port, ingress, f);
@@ -1749,6 +1733,59 @@ mlxsw_sp_setup_tc_cls_flower(struct mlxsw_sp_port *mlxsw_sp_port,
}
}
+static int mlxsw_sp_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv, bool ingress)
+{
+ struct mlxsw_sp_port *mlxsw_sp_port = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSMATCHALL:
+ return mlxsw_sp_setup_tc_cls_matchall(mlxsw_sp_port, type_data,
+ ingress);
+ case TC_SETUP_CLSFLOWER:
+ return mlxsw_sp_setup_tc_cls_flower(mlxsw_sp_port, type_data,
+ ingress);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int mlxsw_sp_setup_tc_block_cb_ig(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ return mlxsw_sp_setup_tc_block_cb(type, type_data, cb_priv, true);
+}
+
+static int mlxsw_sp_setup_tc_block_cb_eg(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ return mlxsw_sp_setup_tc_block_cb(type, type_data, cb_priv, false);
+}
+
+static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct tc_block_offload *f)
+{
+ tc_setup_cb_t *cb;
+
+ if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ cb = mlxsw_sp_setup_tc_block_cb_ig;
+ else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
+ cb = mlxsw_sp_setup_tc_block_cb_eg;
+ else
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, cb, mlxsw_sp_port,
+ mlxsw_sp_port);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, cb, mlxsw_sp_port);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -1756,9 +1793,10 @@ static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
case TC_SETUP_CLSMATCHALL:
- return mlxsw_sp_setup_tc_cls_matchall(mlxsw_sp_port, type_data);
case TC_SETUP_CLSFLOWER:
- return mlxsw_sp_setup_tc_cls_flower(mlxsw_sp_port, type_data);
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return mlxsw_sp_setup_tc_block(mlxsw_sp_port, type_data);
default:
return -EOPNOTSUPP;
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 21/34] mlx5e: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (19 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 20/34] mlxsw: spectrum: Convert ndo_setup_tc offloads to block callbacks Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 22/34] bnxt: " Jiri Pirko
` (14 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for flower offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 45 ++++++++++++++++++++---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 24 +++++-------
3 files changed, 51 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 5ec6d3e..ca07a60 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -1081,8 +1081,8 @@ int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
struct ethtool_flash *flash);
-int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
- void *type_data);
+int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv);
/* mlx5e generic netdev management API */
struct net_device*
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 2a32102..da67217 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3086,13 +3086,10 @@ static int mlx5e_setup_tc_mqprio(struct net_device *netdev,
}
#ifdef CONFIG_MLX5_ESWITCH
-static int mlx5e_setup_tc_cls_flower(struct net_device *dev,
+static int mlx5e_setup_tc_cls_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *cls_flower)
{
- struct mlx5e_priv *priv = netdev_priv(dev);
-
- if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
- cls_flower->common.chain_index)
+ if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
@@ -3106,6 +3103,40 @@ static int mlx5e_setup_tc_cls_flower(struct net_device *dev,
return -EOPNOTSUPP;
}
}
+
+int mlx5e_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv)
+{
+ struct mlx5e_priv *priv = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return mlx5e_setup_tc_cls_flower(priv, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int mlx5e_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, mlx5e_setup_tc_block_cb,
+ priv, priv);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, mlx5e_setup_tc_block_cb,
+ priv);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
#endif
int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
@@ -3114,7 +3145,9 @@ int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
switch (type) {
#ifdef CONFIG_MLX5_ESWITCH
case TC_SETUP_CLSFLOWER:
- return mlx5e_setup_tc_cls_flower(dev, type_data);
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return mlx5e_setup_tc_block(dev, type_data);
#endif
case TC_SETUP_MQPRIO:
return mlx5e_setup_tc_mqprio(dev, type_data);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 765fc74..4edd92d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -691,14 +691,6 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
}
}
-static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
- void *cb_priv)
-{
- struct net_device *dev = cb_priv;
-
- return mlx5e_setup_tc(dev, type, type_data);
-}
-
bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
{
struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -987,6 +979,7 @@ mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
{
struct mlx5e_rep_priv *rpriv;
struct net_device *netdev;
+ struct mlx5e_priv *upriv;
int err;
rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
@@ -1018,8 +1011,9 @@ mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
goto err_detach_netdev;
}
- err = tc_setup_cb_egdev_register(netdev, mlx5e_rep_setup_tc_cb,
- mlx5_eswitch_get_uplink_netdev(esw));
+ upriv = netdev_priv(mlx5_eswitch_get_uplink_netdev(esw));
+ err = tc_setup_cb_egdev_register(netdev, mlx5e_setup_tc_block_cb,
+ upriv);
if (err)
goto err_neigh_cleanup;
@@ -1033,8 +1027,8 @@ mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
return 0;
err_egdev_cleanup:
- tc_setup_cb_egdev_unregister(netdev, mlx5e_rep_setup_tc_cb,
- mlx5_eswitch_get_uplink_netdev(esw));
+ tc_setup_cb_egdev_unregister(netdev, mlx5e_setup_tc_block_cb,
+ upriv);
err_neigh_cleanup:
mlx5e_rep_neigh_cleanup(rpriv);
@@ -1055,10 +1049,12 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
struct mlx5e_priv *priv = netdev_priv(netdev);
struct mlx5e_rep_priv *rpriv = priv->ppriv;
void *ppriv = priv->ppriv;
+ struct mlx5e_priv *upriv;
unregister_netdev(rep->netdev);
- tc_setup_cb_egdev_unregister(netdev, mlx5e_rep_setup_tc_cb,
- mlx5_eswitch_get_uplink_netdev(esw));
+ upriv = netdev_priv(mlx5_eswitch_get_uplink_netdev(esw));
+ tc_setup_cb_egdev_unregister(netdev, mlx5e_setup_tc_block_cb,
+ upriv);
mlx5e_rep_neigh_cleanup(rpriv);
mlx5e_detach_netdev(priv);
mlx5e_destroy_netdev(priv);
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 22/34] bnxt: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (20 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 21/34] mlx5e: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 23/34] cxgb4: " Jiri Pirko
` (13 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for flower offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 37 +++++++++++++++++++----
drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 3 +-
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 43 +++++++++++++++++++++++++--
3 files changed, 73 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 5ba4993..4dde2b8 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -7295,15 +7295,40 @@ int bnxt_setup_mq_tc(struct net_device *dev, u8 tc)
return 0;
}
-static int bnxt_setup_flower(struct net_device *dev,
- struct tc_cls_flower_offload *cls_flower)
+static int bnxt_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv)
{
- struct bnxt *bp = netdev_priv(dev);
+ struct bnxt *bp = cb_priv;
if (BNXT_VF(bp))
return -EOPNOTSUPP;
- return bnxt_tc_setup_flower(bp, bp->pf.fw_fid, cls_flower);
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return bnxt_tc_setup_flower(bp, bp->pf.fw_fid, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int bnxt_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct bnxt *bp = netdev_priv(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, bnxt_setup_tc_block_cb,
+ bp, bp);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, bnxt_setup_tc_block_cb, bp);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
}
static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
@@ -7311,7 +7336,9 @@ static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
{
switch (type) {
case TC_SETUP_CLSFLOWER:
- return bnxt_setup_flower(dev, type_data);
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return bnxt_setup_tc_block(dev, type_data);
case TC_SETUP_MQPRIO: {
struct tc_mqprio_qopt *mqprio = type_data;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 4730c04..a9cb653 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -748,8 +748,7 @@ int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
{
int rc = 0;
- if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
- cls_flower->common.chain_index)
+ if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index e75db04..cc278d7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -115,10 +115,11 @@ bnxt_vf_rep_get_stats64(struct net_device *dev,
stats->tx_bytes = vf_rep->tx_stats.bytes;
}
-static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
- void *type_data)
+static int bnxt_vf_rep_setup_tc_block_cb(enum tc_setup_type type,
+ void *type_data,
+ void *cb_priv)
{
- struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
+ struct bnxt_vf_rep *vf_rep = cb_priv;
struct bnxt *bp = vf_rep->bp;
int vf_fid = bp->pf.vf[vf_rep->vf_idx].fw_fid;
@@ -130,6 +131,42 @@ static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
}
}
+static int bnxt_vf_rep_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct bnxt_vf_rep *vf_rep = netdev_priv(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block,
+ bnxt_vf_rep_setup_tc_block_cb,
+ vf_rep, vf_rep);
+ return 0;
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block,
+ bnxt_vf_rep_setup_tc_block_cb, vf_rep);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
+ void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return bnxt_vf_rep_setup_tc_block(dev, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
struct net_device *bnxt_get_vf_rep(struct bnxt *bp, u16 cfa_code)
{
u16 vf_idx;
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 23/34] cxgb4: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (21 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 22/34] bnxt: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 24/34] ixgbe: " Jiri Pirko
` (12 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for flower and u32 offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 45 +++++++++++++++++++++----
1 file changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index fe4cbe2..1e27aca 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2883,8 +2883,7 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
static int cxgb_setup_tc_flower(struct net_device *dev,
struct tc_cls_flower_offload *cls_flower)
{
- if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
- cls_flower->common.chain_index)
+ if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
@@ -2902,8 +2901,7 @@ static int cxgb_setup_tc_flower(struct net_device *dev,
static int cxgb_setup_tc_cls_u32(struct net_device *dev,
struct tc_cls_u32_offload *cls_u32)
{
- if (!is_classid_clsact_ingress(cls_u32->common.classid) ||
- cls_u32->common.chain_index)
+ if (cls_u32->common.chain_index)
return -EOPNOTSUPP;
switch (cls_u32->command) {
@@ -2917,9 +2915,10 @@ static int cxgb_setup_tc_cls_u32(struct net_device *dev,
}
}
-static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
- void *type_data)
+static int cxgb_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv)
{
+ struct net_device *dev = cb_priv;
struct port_info *pi = netdev2pinfo(dev);
struct adapter *adap = netdev2adap(dev);
@@ -2940,6 +2939,40 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
}
}
+static int cxgb_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct port_info *pi = netdev2pinfo(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, cxgb_setup_tc_block_cb,
+ pi, dev);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, cxgb_setup_tc_block_cb, pi);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
+ void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_CLSU32:
+ case TC_SETUP_CLSFLOWER:
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return cxgb_setup_tc_block(dev, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static netdev_features_t cxgb_fix_features(struct net_device *dev,
netdev_features_t features)
{
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 24/34] ixgbe: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (22 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 23/34] cxgb4: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 25/34] mlx5e_rep: " Jiri Pirko
` (11 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for u32 offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 45 +++++++++++++++++++++++----
1 file changed, 39 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 7683c14..6b52cfd 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9365,13 +9365,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter,
return err;
}
-static int ixgbe_setup_tc_cls_u32(struct net_device *dev,
+static int ixgbe_setup_tc_cls_u32(struct ixgbe_adapter *adapter,
struct tc_cls_u32_offload *cls_u32)
{
- struct ixgbe_adapter *adapter = netdev_priv(dev);
-
- if (!is_classid_clsact_ingress(cls_u32->common.classid) ||
- cls_u32->common.chain_index)
+ if (cls_u32->common.chain_index)
return -EOPNOTSUPP;
switch (cls_u32->command) {
@@ -9390,6 +9387,40 @@ static int ixgbe_setup_tc_cls_u32(struct net_device *dev,
}
}
+static int ixgbe_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv)
+{
+ struct ixgbe_adapter *adapter = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSU32:
+ return ixgbe_setup_tc_cls_u32(adapter, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int ixgbe_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, ixgbe_setup_tc_block_cb,
+ adapter, adapter);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, ixgbe_setup_tc_block_cb,
+ adapter);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int ixgbe_setup_tc_mqprio(struct net_device *dev,
struct tc_mqprio_qopt *mqprio)
{
@@ -9402,7 +9433,9 @@ static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
{
switch (type) {
case TC_SETUP_CLSU32:
- return ixgbe_setup_tc_cls_u32(dev, type_data);
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return ixgbe_setup_tc_block(dev, type_data);
case TC_SETUP_MQPRIO:
return ixgbe_setup_tc_mqprio(dev, type_data);
default:
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 25/34] mlx5e_rep: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (23 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 24/34] ixgbe: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 26/34] nfp: flower: " Jiri Pirko
` (10 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for flower offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 44 ++++++++++++++++++++----
1 file changed, 38 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 4edd92d..f59d81a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -659,13 +659,10 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
}
static int
-mlx5e_rep_setup_tc_cls_flower(struct net_device *dev,
+mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
struct tc_cls_flower_offload *cls_flower)
{
- struct mlx5e_priv *priv = netdev_priv(dev);
-
- if (!is_classid_clsact_ingress(cls_flower->common.classid) ||
- cls_flower->common.chain_index)
+ if (cls_flower->common.chain_index)
return -EOPNOTSUPP;
switch (cls_flower->command) {
@@ -680,12 +677,47 @@ mlx5e_rep_setup_tc_cls_flower(struct net_device *dev,
}
}
+static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv)
+{
+ struct mlx5e_priv *priv = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return mlx5e_rep_setup_tc_cls_flower(priv, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int mlx5e_rep_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, mlx5e_rep_setup_tc_cb,
+ priv, priv);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, mlx5e_rep_setup_tc_cb, priv);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
case TC_SETUP_CLSFLOWER:
- return mlx5e_rep_setup_tc_cls_flower(dev, type_data);
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return mlx5e_rep_setup_tc_block(dev, type_data);
default:
return -EOPNOTSUPP;
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 26/34] nfp: flower: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (24 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 25/34] mlx5e_rep: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 27/34] nfp: bpf: " Jiri Pirko
` (9 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for flower offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/netronome/nfp/flower/offload.c | 56 ++++++++++++++++++----
1 file changed, 48 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 6f239c2..f8523df 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -449,6 +449,10 @@ static int
nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
struct tc_cls_flower_offload *flower)
{
+ if (!eth_proto_is_802_3(flower->common.protocol) ||
+ flower->common.chain_index)
+ return -EOPNOTSUPP;
+
switch (flower->command) {
case TC_CLSFLOWER_REPLACE:
return nfp_flower_add_offload(app, netdev, flower);
@@ -461,16 +465,52 @@ nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev,
return -EOPNOTSUPP;
}
-int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
- enum tc_setup_type type, void *type_data)
+static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ struct nfp_net *nn = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return nfp_flower_repr_offload(nn->app, nn->port->netdev,
+ type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int nfp_flower_setup_tc_block(struct net_device *netdev,
+ struct tc_block_offload *f)
{
- struct tc_cls_flower_offload *cls_flower = type_data;
+ struct nfp_net *nn = netdev_priv(netdev);
- if (type != TC_SETUP_CLSFLOWER ||
- !is_classid_clsact_ingress(cls_flower->common.classid) ||
- !eth_proto_is_802_3(cls_flower->common.protocol) ||
- cls_flower->common.chain_index)
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
- return nfp_flower_repr_offload(app, netdev, cls_flower);
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block,
+ nfp_flower_setup_tc_block_cb,
+ nn, nn);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block,
+ nfp_flower_setup_tc_block_cb,
+ nn);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
+ enum tc_setup_type type, void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_CLSFLOWER:
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return nfp_flower_setup_tc_block(netdev, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 27/34] nfp: bpf: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (25 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 26/34] nfp: flower: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-13 1:08 ` Jakub Kicinski
2017-10-12 17:18 ` [patch net-next 28/34] dsa: " Jiri Pirko
` (8 subsequent siblings)
35 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for bpf offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/netronome/nfp/bpf/main.c | 53 +++++++++++++++++++-----
drivers/net/ethernet/netronome/nfp/bpf/offload.c | 4 ++
2 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index 0747269..be7607b 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -112,22 +112,55 @@ static void nfp_bpf_vnic_free(struct nfp_app *app, struct nfp_net *nn)
kfree(nn->app_priv);
}
-static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
- enum tc_setup_type type, void *type_data)
+static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ struct nfp_net *nn = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSBPF:
+ if (!nfp_net_ebpf_capable(nn))
+ return -EOPNOTSUPP;
+ return nfp_net_bpf_offload(nn, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int nfp_bpf_setup_tc_block(struct net_device *netdev,
+ struct tc_block_offload *f)
{
- struct tc_cls_bpf_offload *cls_bpf = type_data;
struct nfp_net *nn = netdev_priv(netdev);
- if (type != TC_SETUP_CLSBPF || !nfp_net_ebpf_capable(nn) ||
- !is_classid_clsact_ingress(cls_bpf->common.classid) ||
- cls_bpf->common.protocol != htons(ETH_P_ALL) ||
- cls_bpf->common.chain_index)
+ if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
return -EOPNOTSUPP;
- if (nn->dp.bpf_offload_xdp)
- return -EBUSY;
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block,
+ nfp_bpf_setup_tc_block_cb,
+ nn, nn);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block,
+ nfp_bpf_setup_tc_block_cb,
+ nn);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
- return nfp_net_bpf_offload(nn, cls_bpf);
+static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
+ enum tc_setup_type type, void *type_data)
+{
+ switch (type) {
+ case TC_SETUP_CLSBPF:
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return nfp_bpf_setup_tc_block(netdev, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
}
static bool nfp_bpf_tc_busy(struct nfp_app *app, struct nfp_net *nn)
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
index a88bb5b..9e9af88 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
@@ -246,6 +246,10 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
void *code;
int err;
+ if (cls_bpf->common.protocol != htons(ETH_P_ALL) ||
+ cls_bpf->common.chain_index)
+ return -EOPNOTSUPP;
+
max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
switch (cls_bpf->command) {
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 28/34] dsa: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (26 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 27/34] nfp: bpf: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 29/34] net: sched: avoid ndo_setup_tc calls for TC_SETUP_CLS* Jiri Pirko
` (7 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
Benefit from the newly introduced block callback infrastructure and
convert ndo_setup_tc calls for matchall offloads to block callbacks.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/dsa/slave.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 53 insertions(+), 11 deletions(-)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index fb2954f..4633c56 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -788,17 +788,9 @@ static void dsa_slave_del_cls_matchall(struct net_device *dev,
}
static int dsa_slave_setup_tc_cls_matchall(struct net_device *dev,
- struct tc_cls_matchall_offload *cls)
+ struct tc_cls_matchall_offload *cls,
+ bool ingress)
{
- bool ingress;
-
- if (is_classid_clsact_ingress(cls->common.classid))
- ingress = true;
- else if (is_classid_clsact_egress(cls->common.classid))
- ingress = false;
- else
- return -EOPNOTSUPP;
-
if (cls->common.chain_index)
return -EOPNOTSUPP;
@@ -813,12 +805,62 @@ static int dsa_slave_setup_tc_cls_matchall(struct net_device *dev,
}
}
+static int dsa_slave_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
+ void *cb_priv, bool ingress)
+{
+ struct net_device *dev = cb_priv;
+
+ switch (type) {
+ case TC_SETUP_CLSMATCHALL:
+ return dsa_slave_setup_tc_cls_matchall(dev, type_data, ingress);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int dsa_slave_setup_tc_block_cb_ig(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ return dsa_slave_setup_tc_block_cb(type, type_data, cb_priv, true);
+}
+
+static int dsa_slave_setup_tc_block_cb_eg(enum tc_setup_type type,
+ void *type_data, void *cb_priv)
+{
+ return dsa_slave_setup_tc_block_cb(type, type_data, cb_priv, false);
+}
+
+static int dsa_slave_setup_tc_block(struct net_device *dev,
+ struct tc_block_offload *f)
+{
+ tc_setup_cb_t *cb;
+
+ if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ cb = dsa_slave_setup_tc_block_cb_ig;
+ else if (f->binder_type == TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
+ cb = dsa_slave_setup_tc_block_cb_eg;
+ else
+ return -EOPNOTSUPP;
+
+ switch (f->command) {
+ case TC_BLOCK_BIND:
+ return tcf_block_cb_register(f->block, cb, dev, dev);
+ case TC_BLOCK_UNBIND:
+ tcf_block_cb_unregister(f->block, cb, dev);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int dsa_slave_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
case TC_SETUP_CLSMATCHALL:
- return dsa_slave_setup_tc_cls_matchall(dev, type_data);
+ return 0; /* will be removed after conversion from ndo */
+ case TC_SETUP_BLOCK:
+ return dsa_slave_setup_tc_block(dev, type_data);
default:
return -EOPNOTSUPP;
}
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 29/34] net: sched: avoid ndo_setup_tc calls for TC_SETUP_CLS*
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (27 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 28/34] dsa: " Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 30/34] net: sched: remove unused classid field from tc_cls_common_offload Jiri Pirko
` (6 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
All drivers are converted to use block callbacks for TC_SETUP_CLS*.
So it is now safe to remove the calls to ndo_setup_tc from cls_*
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 --
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c | 2 --
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 ---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 --
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 --
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 --
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 3 ---
drivers/net/ethernet/netronome/nfp/bpf/main.c | 2 --
.../net/ethernet/netronome/nfp/flower/offload.c | 2 --
net/dsa/slave.c | 2 --
net/sched/cls_bpf.c | 14 ----------
net/sched/cls_flower.c | 20 --------------
net/sched/cls_matchall.c | 16 -----------
net/sched/cls_u32.c | 31 ----------------------
14 files changed, 103 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 4dde2b8..22a94b1 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -7335,8 +7335,6 @@ static int bnxt_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return bnxt_setup_tc_block(dev, type_data);
case TC_SETUP_MQPRIO: {
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index cc278d7..6dff5aa 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -158,8 +158,6 @@ static int bnxt_vf_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return bnxt_vf_rep_setup_tc_block(dev, type_data);
default:
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 1e27aca..bb38ff5 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2963,9 +2963,6 @@ static int cxgb_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
- case TC_SETUP_CLSU32:
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return cxgb_setup_tc_block(dev, type_data);
default:
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 6b52cfd..3c85120 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9432,8 +9432,6 @@ static int __ixgbe_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
- case TC_SETUP_CLSU32:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return ixgbe_setup_tc_block(dev, type_data);
case TC_SETUP_MQPRIO:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index da67217..3356a39 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3144,8 +3144,6 @@ int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
{
switch (type) {
#ifdef CONFIG_MLX5_ESWITCH
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return mlx5e_setup_tc_block(dev, type_data);
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index f59d81a..0edb706 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -714,8 +714,6 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return mlx5e_rep_setup_tc_block(dev, type_data);
default:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index ad1f651..852181d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1792,9 +1792,6 @@ static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
switch (type) {
- case TC_SETUP_CLSMATCHALL:
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return mlxsw_sp_setup_tc_block(mlxsw_sp_port, type_data);
default:
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index be7607b..4a48a7c 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -154,8 +154,6 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
enum tc_setup_type type, void *type_data)
{
switch (type) {
- case TC_SETUP_CLSBPF:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return nfp_bpf_setup_tc_block(netdev, type_data);
default:
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index f8523df..c47753f 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -506,8 +506,6 @@ int nfp_flower_setup_tc(struct nfp_app *app, struct net_device *netdev,
enum tc_setup_type type, void *type_data)
{
switch (type) {
- case TC_SETUP_CLSFLOWER:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return nfp_flower_setup_tc_block(netdev, type_data);
default:
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 4633c56..d672fed 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -857,8 +857,6 @@ static int dsa_slave_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
switch (type) {
- case TC_SETUP_CLSMATCHALL:
- return 0; /* will be removed after conversion from ndo */
case TC_SETUP_BLOCK:
return dsa_slave_setup_tc_block(dev, type_data);
default:
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index e379fdf..0f8b510 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -148,7 +148,6 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
enum tc_clsbpf_command cmd)
{
bool addorrep = cmd == TC_CLSBPF_ADD || cmd == TC_CLSBPF_REPLACE;
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
bool skip_sw = tc_skip_sw(prog->gen_flags);
struct tc_cls_bpf_offload cls_bpf = {};
@@ -162,19 +161,6 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog,
cls_bpf.exts_integrated = prog->exts_integrated;
cls_bpf.gen_flags = prog->gen_flags;
- if (tc_can_offload(dev)) {
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSBPF,
- &cls_bpf);
- if (addorrep) {
- if (err) {
- if (skip_sw)
- return err;
- } else {
- prog->gen_flags |= TCA_CLS_FLAGS_IN_HW;
- }
- }
- }
-
err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSBPF, &cls_bpf, skip_sw);
if (addorrep) {
if (err < 0) {
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 76b4e0a..16f58ab 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -200,16 +200,12 @@ static void fl_destroy_filter(struct rcu_head *head)
static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
{
struct tc_cls_flower_offload cls_flower = {};
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
tc_cls_common_offload_init(&cls_flower.common, tp);
cls_flower.command = TC_CLSFLOWER_DESTROY;
cls_flower.cookie = (unsigned long) f;
- if (tc_can_offload(dev))
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
- &cls_flower);
tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, false);
}
@@ -219,7 +215,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
struct fl_flow_key *mask,
struct cls_fl_filter *f)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_flower_offload cls_flower = {};
struct tcf_block *block = tp->chain->block;
bool skip_sw = tc_skip_sw(f->flags);
@@ -233,17 +228,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
cls_flower.key = &f->mkey;
cls_flower.exts = &f->exts;
- if (tc_can_offload(dev)) {
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
- &cls_flower);
- if (err) {
- if (skip_sw)
- return err;
- } else {
- f->flags |= TCA_CLS_FLAGS_IN_HW;
- }
- }
-
err = tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, skip_sw);
if (err < 0) {
@@ -262,7 +246,6 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
{
struct tc_cls_flower_offload cls_flower = {};
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
tc_cls_common_offload_init(&cls_flower.common, tp);
@@ -270,9 +253,6 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
cls_flower.cookie = (unsigned long) f;
cls_flower.exts = &f->exts;
- if (tc_can_offload(dev))
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
- &cls_flower);
tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
&cls_flower, false);
}
diff --git a/net/sched/cls_matchall.c b/net/sched/cls_matchall.c
index 5278534..70e78d7 100644
--- a/net/sched/cls_matchall.c
+++ b/net/sched/cls_matchall.c
@@ -54,7 +54,6 @@ static void mall_destroy_hw_filter(struct tcf_proto *tp,
struct cls_mall_head *head,
unsigned long cookie)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_matchall_offload cls_mall = {};
struct tcf_block *block = tp->chain->block;
@@ -62,9 +61,6 @@ static void mall_destroy_hw_filter(struct tcf_proto *tp,
cls_mall.command = TC_CLSMATCHALL_DESTROY;
cls_mall.cookie = cookie;
- if (tc_can_offload(dev))
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSMATCHALL,
- &cls_mall);
tc_setup_cb_call(block, NULL, TC_SETUP_CLSMATCHALL, &cls_mall, false);
}
@@ -72,7 +68,6 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
struct cls_mall_head *head,
unsigned long cookie)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tc_cls_matchall_offload cls_mall = {};
struct tcf_block *block = tp->chain->block;
bool skip_sw = tc_skip_sw(head->flags);
@@ -83,17 +78,6 @@ static int mall_replace_hw_filter(struct tcf_proto *tp,
cls_mall.exts = &head->exts;
cls_mall.cookie = cookie;
- if (tc_can_offload(dev)) {
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSMATCHALL,
- &cls_mall);
- if (err) {
- if (skip_sw)
- return err;
- } else {
- head->flags |= TCA_CLS_FLAGS_IN_HW;
- }
- }
-
err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSMATCHALL,
&cls_mall, skip_sw);
if (err < 0) {
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 24cc429..0e4bd30 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -464,7 +464,6 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
@@ -474,15 +473,12 @@ static void u32_clear_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h)
cls_u32.hnode.handle = h->handle;
cls_u32.hnode.prio = h->prio;
- if (tc_can_offload(dev))
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
}
static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
u32 flags)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
bool skip_sw = tc_skip_sw(flags);
@@ -495,17 +491,6 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
cls_u32.hnode.handle = h->handle;
cls_u32.hnode.prio = h->prio;
- if (tc_can_offload(dev)) {
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32,
- &cls_u32);
- if (err) {
- if (skip_sw)
- return err;
- } else {
- offloaded = true;
- }
- }
-
err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
if (err < 0) {
u32_clear_hw_hnode(tp, h);
@@ -522,7 +507,6 @@ static int u32_replace_hw_hnode(struct tcf_proto *tp, struct tc_u_hnode *h,
static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
@@ -530,15 +514,12 @@ static void u32_remove_hw_knode(struct tcf_proto *tp, u32 handle)
cls_u32.command = TC_CLSU32_DELETE_KNODE;
cls_u32.knode.handle = handle;
- if (tc_can_offload(dev))
- dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32, &cls_u32);
tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, false);
}
static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
u32 flags)
{
- struct net_device *dev = tp->q->dev_queue->dev;
struct tcf_block *block = tp->chain->block;
struct tc_cls_u32_offload cls_u32 = {};
bool skip_sw = tc_skip_sw(flags);
@@ -560,18 +541,6 @@ static int u32_replace_hw_knode(struct tcf_proto *tp, struct tc_u_knode *n,
if (n->ht_down)
cls_u32.knode.link_handle = n->ht_down->handle;
-
- if (tc_can_offload(dev)) {
- err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSU32,
- &cls_u32);
- if (err) {
- if (skip_sw)
- return err;
- } else {
- n->flags |= TCA_CLS_FLAGS_IN_HW;
- }
- }
-
err = tc_setup_cb_call(block, NULL, TC_SETUP_CLSU32, &cls_u32, skip_sw);
if (err < 0) {
u32_remove_hw_knode(tp, n->handle);
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 30/34] net: sched: remove unused classid field from tc_cls_common_offload
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (28 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 29/34] net: sched: avoid ndo_setup_tc calls for TC_SETUP_CLS* Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 31/34] net: sched: remove unused is_classid_clsact_ingress/egress helpers Jiri Pirko
` (5 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
It is no longer used by the drivers, so remove it.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_cls.h | 2 --
1 file changed, 2 deletions(-)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 2e73832..1c8ef4f 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -572,7 +572,6 @@ struct tc_cls_common_offload {
u32 chain_index;
__be16 protocol;
u32 prio;
- u32 classid;
};
static inline void
@@ -582,7 +581,6 @@ tc_cls_common_offload_init(struct tc_cls_common_offload *cls_common,
cls_common->chain_index = tp->chain->index;
cls_common->protocol = tp->protocol;
cls_common->prio = tp->prio;
- cls_common->classid = tp->classid;
}
struct tc_cls_u32_knode {
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 31/34] net: sched: remove unused is_classid_clsact_ingress/egress helpers
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (29 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 30/34] net: sched: remove unused classid field from tc_cls_common_offload Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 32/34] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
` (4 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@mellanox.com>
These helpers are no longer in use by drivers, so remove them.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/pkt_sched.h | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 2d234af..b8ecafc 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -135,19 +135,6 @@ static inline unsigned int psched_mtu(const struct net_device *dev)
return dev->mtu + dev->hard_header_len;
}
-static inline bool is_classid_clsact_ingress(u32 classid)
-{
- /* This also returns true for ingress qdisc */
- return TC_H_MAJ(classid) == TC_H_MAJ(TC_H_CLSACT) &&
- TC_H_MIN(classid) != TC_H_MIN(TC_H_MIN_EGRESS);
-}
-
-static inline bool is_classid_clsact_egress(u32 classid)
-{
- return TC_H_MAJ(classid) == TC_H_MAJ(TC_H_CLSACT) &&
- TC_H_MIN(classid) == TC_H_MIN(TC_H_MIN_EGRESS);
-}
-
static inline struct net *qdisc_net(struct Qdisc *q)
{
return dev_net(q->dev_queue->dev);
--
2.9.5
^ permalink raw reply related [flat|nested] 53+ messages in thread
* [patch net-next 32/34] net: sched: introduce block mechanism to handle netif_keep_dst calls
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (30 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 31/34] net: sched: remove unused is_classid_clsact_ingress/egress helpers Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 33/34] net: sched: remove classid and q fields from tcf_proto Jiri Pirko
` (3 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
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 1c8ef4f..66d4e71 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -37,6 +37,7 @@ 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,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index dfa9617..17c908a 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -276,6 +276,8 @@ struct tcf_block {
struct net *net;
struct Qdisc *q;
struct list_head cb_list;
+ struct list_head owner_list;
+ bool keep_dst;
};
static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 5a647e0..fba6a85 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -320,6 +320,7 @@ static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q)
block->net = net;
block->q = q;
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);
@@ -405,6 +406,64 @@ static void tcf_block_offload_unbind(struct tcf_block *block, struct Qdisc *q,
tcf_block_offload_cmd(block, q, ei, TC_BLOCK_UNBIND);
}
+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 tcf_proto __rcu **p_filter_chain, struct Qdisc *q,
struct tcf_block_ext_info *ei)
@@ -432,6 +491,12 @@ int tcf_block_get_ext(struct tcf_block **p_block,
}
}
+ 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_filter_chain_ptr_add(tcf_block_chain_zero(block),
p_filter_chain);
if (err)
@@ -442,6 +507,8 @@ int tcf_block_get_ext(struct tcf_block **p_block,
return 0;
err_chain_filter_chain_ptr_add:
+ tcf_block_owner_del(block, q, ei->binder_type);
+err_block_owner_add:
if (created) {
if (ei->shareable)
tcf_block_remove(block, net);
@@ -473,6 +540,7 @@ void tcf_block_put_ext(struct tcf_block *block,
tcf_block_offload_unbind(block, q, ei);
tcf_chain_filter_chain_ptr_del(tcf_block_chain_zero(block),
p_filter_chain);
+ 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 0f8b510..e21cdd0 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -383,8 +383,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 f3be666..4b5ce2e 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -508,7 +508,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
setup_deferrable_timer(&fnew->perturb_timer, flow_perturbation,
(unsigned long)fnew);
- 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 9ddde65..cd2cd0d 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -504,7 +504,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] 53+ messages in thread
* [patch net-next 33/34] net: sched: remove classid and q fields from tcf_proto
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (31 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 32/34] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 34/34] net: sched: allow ingress and clsact qdiscs to share filter blocks Jiri Pirko
` (2 subsequent siblings)
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
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 17c908a..df4a1e9 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 fba6a85..4b0c051 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -114,8 +114,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;
@@ -149,8 +148,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);
@@ -1039,7 +1036,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] 53+ messages in thread
* [patch net-next 34/34] net: sched: allow ingress and clsact qdiscs to share filter blocks
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (32 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 33/34] net: sched: remove classid and q fields from tcf_proto Jiri Pirko
@ 2017-10-12 17:18 ` Jiri Pirko
2017-10-12 17:21 ` [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances David Miller
2017-10-12 21:37 ` David Ahern
35 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-12 17:18 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
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 | 12 ++++++
net/sched/sch_ingress.c | 89 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 099bf55..a684087 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -871,4 +871,16 @@ struct tc_pie_xstats {
__u32 maxq; /* maximum queue size */
__u32 ecn_mark; /* packets marked with ecn*/
};
+
+/* 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 b599db2..59625e8 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -54,12 +54,40 @@ static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl)
return q->block;
}
+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)
{
struct ingress_sched_data *q = qdisc_priv(sch);
struct net_device *dev = qdisc_dev(sch);
int err;
+ 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;
err = tcf_block_get_ext(&q->block, &dev->ingress_cl_list,
@@ -85,11 +113,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);
@@ -155,12 +186,47 @@ 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);
struct net_device *dev = qdisc_dev(sch);
int err;
+ 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;
err = tcf_block_get_ext(&q->ingress_block, &dev->ingress_cl_list,
@@ -168,6 +234,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
if (err)
return err;
+ q->egress_block_info.shareable = true;
q->egress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS;
err = tcf_block_get_ext(&q->egress_block, &dev->egress_cl_list,
@@ -202,6 +269,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,
@@ -217,7 +304,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] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (33 preceding siblings ...)
2017-10-12 17:18 ` [patch net-next 34/34] net: sched: allow ingress and clsact qdiscs to share filter blocks Jiri Pirko
@ 2017-10-12 17:21 ` David Miller
2017-10-13 6:21 ` Jiri Pirko
2017-10-12 21:37 ` David Ahern
35 siblings, 1 reply; 53+ messages in thread
From: David Miller @ 2017-10-12 17:21 UTC (permalink / raw)
To: jiri
Cc: netdev, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
Jiri I'm not looking at a 34 patch set, it's too large.
Break this up into groups of a dozen or so patches each, no
more. Submit them one at a time and wait for each series
to be fully reviewed and integrated before moving onto the
next one.
Thanks.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
` (34 preceding siblings ...)
2017-10-12 17:21 ` [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances David Miller
@ 2017-10-12 21:37 ` David Ahern
2017-10-13 6:26 ` Jiri Pirko
35 siblings, 1 reply; 53+ messages in thread
From: David Ahern @ 2017-10-12 21:37 UTC (permalink / raw)
To: Jiri Pirko, netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, alexander.h.duyck,
john.fastabend, willemb
On 10/12/17 11:17 AM, Jiri Pirko wrote:
> 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 parent ffff: 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
This seems like really odd semantics to me ... a filter added to one
device shows up on another.
Why not make the shared block a standalone object that is configured
through its own set of commands and then referenced by both devices?
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-12 17:17 ` [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q Jiri Pirko
@ 2017-10-12 21:45 ` Daniel Borkmann
2017-10-13 6:30 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: Daniel Borkmann @ 2017-10-12 21:45 UTC (permalink / raw)
To: Jiri Pirko, netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
On 10/12/2017 07:17 PM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
> dev->ingress_queue which stores the same pointer instead.
>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
> net/core/dev.c | 21 +++++++++++++++------
> 1 file changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index fcddccb..cb9e5e5 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
> static struct sk_buff *
> sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
> {
> + struct netdev_queue *netdev_queue =
> + rcu_dereference_bh(dev->ingress_queue);
> struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
> struct tcf_result cl_res;
> + struct Qdisc *q;
>
> - if (!cl)
> + if (!cl || !netdev_queue)
> return skb;
> + q = netdev_queue->qdisc;
NAK, no additional overhead in the software fast-path of
sch_handle_{ingress,egress}() like this. There are users out there
that use tc in software only, so performance is critical here.
> /* qdisc_skb_cb(skb)->pkt_len was already set by the caller. */
> - qdisc_bstats_cpu_update(cl->q, skb);
> + qdisc_bstats_cpu_update(q, skb);
>
> switch (tcf_classify(skb, cl, &cl_res, false)) {
> case TC_ACT_OK:
> @@ -3288,7 +3292,7 @@ sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
> skb->tc_index = TC_H_MIN(cl_res.classid);
> break;
> case TC_ACT_SHOT:
> - qdisc_qstats_cpu_drop(cl->q);
> + qdisc_qstats_cpu_drop(q);
> *ret = NET_XMIT_DROP;
> kfree_skb(skb);
> return NULL;
> @@ -4188,16 +4192,21 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
> struct net_device *orig_dev)
> {
> #ifdef CONFIG_NET_CLS_ACT
> + struct netdev_queue *netdev_queue =
> + rcu_dereference_bh(skb->dev->ingress_queue);
> struct tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list);
> struct tcf_result cl_res;
> + struct Qdisc *q;
>
> /* If there's at least one ingress present somewhere (so
> * we get here via enabled static key), remaining devices
> * that are not configured with an ingress qdisc will bail
> * out here.
> */
> - if (!cl)
> + if (!cl || !netdev_queue)
> return skb;
> + q = netdev_queue->qdisc;
> +
> if (*pt_prev) {
> *ret = deliver_skb(skb, *pt_prev, orig_dev);
> *pt_prev = NULL;
> @@ -4205,7 +4214,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
>
> qdisc_skb_cb(skb)->pkt_len = skb->len;
> skb->tc_at_ingress = 1;
> - qdisc_bstats_cpu_update(cl->q, skb);
> + qdisc_bstats_cpu_update(q, skb);
>
> switch (tcf_classify(skb, cl, &cl_res, false)) {
> case TC_ACT_OK:
> @@ -4213,7 +4222,7 @@ sch_handle_ingress(struct sk_buff *skb, struct packet_type **pt_prev, int *ret,
> skb->tc_index = TC_H_MIN(cl_res.classid);
> break;
> case TC_ACT_SHOT:
> - qdisc_qstats_cpu_drop(cl->q);
> + qdisc_qstats_cpu_drop(q);
> kfree_skb(skb);
> return NULL;
> case TC_ACT_STOLEN:
>
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 27/34] nfp: bpf: Convert ndo_setup_tc offloads to block callbacks
2017-10-12 17:18 ` [patch net-next 27/34] nfp: bpf: " Jiri Pirko
@ 2017-10-13 1:08 ` Jakub Kicinski
2017-10-17 12:48 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: Jakub Kicinski @ 2017-10-13 1:08 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, Daniel Borkmann
On Thu, 12 Oct 2017 19:18:16 +0200, Jiri Pirko wrote:
> diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> index a88bb5b..9e9af88 100644
> --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> @@ -246,6 +246,10 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
> void *code;
> int err;
>
> + if (cls_bpf->common.protocol != htons(ETH_P_ALL) ||
> + cls_bpf->common.chain_index)
> + return -EOPNOTSUPP;
> +
> max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
>
> switch (cls_bpf->command) {
It is certainly very ugly but I send a fake struct tc_cls_bpf_offload
here for XDP. Refactoring this mess is pretty high on my priority list
but one way or the other this function will be called from XDP so TC
checks must stay in the TC handler... :(
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-12 17:21 ` [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances David Miller
@ 2017-10-13 6:21 ` Jiri Pirko
2017-10-13 6:31 ` David Miller
0 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-13 6:21 UTC (permalink / raw)
To: David Miller
Cc: netdev, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
Thu, Oct 12, 2017 at 07:21:48PM CEST, davem@davemloft.net wrote:
>
>Jiri I'm not looking at a 34 patch set, it's too large.
>
>Break this up into groups of a dozen or so patches each, no
>more. Submit them one at a time and wait for each series
>to be fully reviewed and integrated before moving onto the
>next one.
Yeah. As I stated in the beginning of the cover letter, I did not find a
way to do it. I could split into 2 of 3 patchsets, problem is that I
would introduce interfaces in first patchset that would be only used in
patchset 2 or 3. I believe that is not ok. Do you think that I can do it
like this this time?
Thanks
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-12 21:37 ` David Ahern
@ 2017-10-13 6:26 ` Jiri Pirko
2017-10-13 14:20 ` David Ahern
0 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-13 6:26 UTC (permalink / raw)
To: David Ahern
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, alexander.h.duyck,
john.fastabend, willemb
Thu, Oct 12, 2017 at 11:37:30PM CEST, dsahern@gmail.com wrote:
>On 10/12/17 11:17 AM, Jiri Pirko wrote:
>> 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 parent ffff: 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
>
>This seems like really odd semantics to me ... a filter added to one
>device shows up on another.
Why is it odd? They share the same block, so it is natural that rule
added to one shows in list of rules for all devices that share the same
block.
>
>Why not make the shared block a standalone object that is configured
>through its own set of commands and then referenced by both devices?
I was thinking about that for a long time. That would require entirely
new set of netlink api and internal kernel handling just for this. Lots
of duplications. The reason is, the current API is strictly build around
ifindex. But the new API would not solve anything. As a user, I still
want so see shared rules in individial device listing, because they
would get processed for the device. So I believe that the proposed
behaviour is correct.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-12 21:45 ` Daniel Borkmann
@ 2017-10-13 6:30 ` Jiri Pirko
2017-10-14 23:18 ` Daniel Borkmann
0 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-13 6:30 UTC (permalink / raw)
To: Daniel Borkmann
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
Thu, Oct 12, 2017 at 11:45:43PM CEST, daniel@iogearbox.net wrote:
>On 10/12/2017 07:17 PM, Jiri Pirko wrote:
>> From: Jiri Pirko <jiri@mellanox.com>
>>
>> In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
>> dev->ingress_queue which stores the same pointer instead.
>>
>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> ---
>> net/core/dev.c | 21 +++++++++++++++------
>> 1 file changed, 15 insertions(+), 6 deletions(-)
>>
>> diff --git a/net/core/dev.c b/net/core/dev.c
>> index fcddccb..cb9e5e5 100644
>> --- a/net/core/dev.c
>> +++ b/net/core/dev.c
>> @@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
>> static struct sk_buff *
>> sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
>> {
>> + struct netdev_queue *netdev_queue =
>> + rcu_dereference_bh(dev->ingress_queue);
>> struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
>> struct tcf_result cl_res;
>> + struct Qdisc *q;
>>
>> - if (!cl)
>> + if (!cl || !netdev_queue)
>> return skb;
>> + q = netdev_queue->qdisc;
>
>NAK, no additional overhead in the software fast-path of
>sch_handle_{ingress,egress}() like this. There are users out there
>that use tc in software only, so performance is critical here.
Okay, how else do you suggest I can avoid the need to use tp->q?
I was thinking about storing q directly to net_device, which would safe
one dereference, resulting in the same amount as current cl->q.
Thanks.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-13 6:21 ` Jiri Pirko
@ 2017-10-13 6:31 ` David Miller
2017-10-13 7:39 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: David Miller @ 2017-10-13 6:31 UTC (permalink / raw)
To: jiri
Cc: netdev, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
From: Jiri Pirko <jiri@resnulli.us>
Date: Fri, 13 Oct 2017 08:21:01 +0200
> Thu, Oct 12, 2017 at 07:21:48PM CEST, davem@davemloft.net wrote:
>>
>>Jiri I'm not looking at a 34 patch set, it's too large.
>>
>>Break this up into groups of a dozen or so patches each, no
>>more. Submit them one at a time and wait for each series
>>to be fully reviewed and integrated before moving onto the
>>next one.
>
> Yeah. As I stated in the beginning of the cover letter, I did not find a
> way to do it. I could split into 2 of 3 patchsets, problem is that I
> would introduce interfaces in first patchset that would be only used in
> patchset 2 or 3. I believe that is not ok. Do you think that I can do it
> like this this time?
Jiri, please try harder.
Thank you.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-13 6:31 ` David Miller
@ 2017-10-13 7:39 ` Jiri Pirko
0 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-13 7:39 UTC (permalink / raw)
To: David Miller
Cc: netdev, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
Fri, Oct 13, 2017 at 08:31:53AM CEST, davem@davemloft.net wrote:
>From: Jiri Pirko <jiri@resnulli.us>
>Date: Fri, 13 Oct 2017 08:21:01 +0200
>
>> Thu, Oct 12, 2017 at 07:21:48PM CEST, davem@davemloft.net wrote:
>>>
>>>Jiri I'm not looking at a 34 patch set, it's too large.
>>>
>>>Break this up into groups of a dozen or so patches each, no
>>>more. Submit them one at a time and wait for each series
>>>to be fully reviewed and integrated before moving onto the
>>>next one.
>>
>> Yeah. As I stated in the beginning of the cover letter, I did not find a
>> way to do it. I could split into 2 of 3 patchsets, problem is that I
>> would introduce interfaces in first patchset that would be only used in
>> patchset 2 or 3. I believe that is not ok. Do you think that I can do it
>> like this this time?
>
>Jiri, please try harder.
Hmm. Okay. The reviewer would miss the big picture. But as you wish :)
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-13 6:26 ` Jiri Pirko
@ 2017-10-13 14:20 ` David Ahern
2017-10-13 14:24 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: David Ahern @ 2017-10-13 14:20 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, alexander.h.duyck,
john.fastabend, willemb
On 10/13/17 12:26 AM, Jiri Pirko wrote:
> Thu, Oct 12, 2017 at 11:37:30PM CEST, dsahern@gmail.com wrote:
>> On 10/12/17 11:17 AM, Jiri Pirko wrote:
>>> 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 parent ffff: 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
>>
>> This seems like really odd semantics to me ... a filter added to one
>> device shows up on another.
>
> Why is it odd? They share the same block, so it is natural that rule
> added to one shows in list of rules for all devices that share the same
> block.
>
>
>>
>> Why not make the shared block a standalone object that is configured
>> through its own set of commands and then referenced by both devices?
>
> I was thinking about that for a long time. That would require entirely
> new set of netlink api and internal kernel handling just for this. Lots
> of duplications. The reason is, the current API is strictly build around
> ifindex. But the new API would not solve anything. As a user, I still
> want so see shared rules in individial device listing, because they
> would get processed for the device. So I believe that the proposed
> behaviour is correct.
>
netconf has NETCONFA_IFINDEX_ALL to keep the device concept but to relay
information that applies to more than 1 device. You could have something
similar for tc and shared blocks. Admin is done on this device index
(e.g., your shared block 22 becomes dev index -22) and the filters are
attached to another device for sharing using the 'qdisc add' command above.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances
2017-10-13 14:20 ` David Ahern
@ 2017-10-13 14:24 ` Jiri Pirko
0 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-13 14:24 UTC (permalink / raw)
To: David Ahern
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, daniel, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, alexander.h.duyck,
john.fastabend, willemb
Fri, Oct 13, 2017 at 04:20:38PM CEST, dsahern@gmail.com wrote:
>On 10/13/17 12:26 AM, Jiri Pirko wrote:
>> Thu, Oct 12, 2017 at 11:37:30PM CEST, dsahern@gmail.com wrote:
>>> On 10/12/17 11:17 AM, Jiri Pirko wrote:
>>>> 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 parent ffff: 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
>>>
>>> This seems like really odd semantics to me ... a filter added to one
>>> device shows up on another.
>>
>> Why is it odd? They share the same block, so it is natural that rule
>> added to one shows in list of rules for all devices that share the same
>> block.
>>
>>
>>>
>>> Why not make the shared block a standalone object that is configured
>>> through its own set of commands and then referenced by both devices?
>>
>> I was thinking about that for a long time. That would require entirely
>> new set of netlink api and internal kernel handling just for this. Lots
>> of duplications. The reason is, the current API is strictly build around
>> ifindex. But the new API would not solve anything. As a user, I still
>> want so see shared rules in individial device listing, because they
>> would get processed for the device. So I believe that the proposed
>> behaviour is correct.
>>
>
>netconf has NETCONFA_IFINDEX_ALL to keep the device concept but to relay
>information that applies to more than 1 device. You could have something
>similar for tc and shared blocks. Admin is done on this device index
>(e.g., your shared block 22 becomes dev index -22) and the filters are
>attached to another device for sharing using the 'qdisc add' command above.
It can be extended like this I guess. But still, the original rule adding
has to work.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-13 6:30 ` Jiri Pirko
@ 2017-10-14 23:18 ` Daniel Borkmann
2017-10-15 6:45 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: Daniel Borkmann @ 2017-10-14 23:18 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
On 10/13/2017 08:30 AM, Jiri Pirko wrote:
> Thu, Oct 12, 2017 at 11:45:43PM CEST, daniel@iogearbox.net wrote:
>> On 10/12/2017 07:17 PM, Jiri Pirko wrote:
>>> From: Jiri Pirko <jiri@mellanox.com>
>>>
>>> In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
>>> dev->ingress_queue which stores the same pointer instead.
>>>
>>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>>> ---
>>> net/core/dev.c | 21 +++++++++++++++------
>>> 1 file changed, 15 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/net/core/dev.c b/net/core/dev.c
>>> index fcddccb..cb9e5e5 100644
>>> --- a/net/core/dev.c
>>> +++ b/net/core/dev.c
>>> @@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
>>> static struct sk_buff *
>>> sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
>>> {
>>> + struct netdev_queue *netdev_queue =
>>> + rcu_dereference_bh(dev->ingress_queue);
>>> struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
>>> struct tcf_result cl_res;
>>> + struct Qdisc *q;
>>>
>>> - if (!cl)
>>> + if (!cl || !netdev_queue)
>>> return skb;
>>> + q = netdev_queue->qdisc;
>>
>> NAK, no additional overhead in the software fast-path of
>> sch_handle_{ingress,egress}() like this. There are users out there
>> that use tc in software only, so performance is critical here.
>
> Okay, how else do you suggest I can avoid the need to use tp->q?
> I was thinking about storing q directly to net_device, which would safe
> one dereference, resulting in the same amount as current cl->q.
Sorry for late reply, mostly off for few days. netdev struct has different
cachelines which are hot on rx and tx (see also the location of the two
lists, ingress_cl_list and egress_cl_list), if you add only one qdisc
pointer there, then you'd at least penalize one of the two w/ potential
cache miss. Can we leave it in cl?
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-14 23:18 ` Daniel Borkmann
@ 2017-10-15 6:45 ` Jiri Pirko
2017-10-16 20:20 ` Daniel Borkmann
0 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-15 6:45 UTC (permalink / raw)
To: Daniel Borkmann
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
Sun, Oct 15, 2017 at 01:18:54AM CEST, daniel@iogearbox.net wrote:
>On 10/13/2017 08:30 AM, Jiri Pirko wrote:
>> Thu, Oct 12, 2017 at 11:45:43PM CEST, daniel@iogearbox.net wrote:
>> > On 10/12/2017 07:17 PM, Jiri Pirko wrote:
>> > > From: Jiri Pirko <jiri@mellanox.com>
>> > >
>> > > In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
>> > > dev->ingress_queue which stores the same pointer instead.
>> > >
>> > > Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> > > ---
>> > > net/core/dev.c | 21 +++++++++++++++------
>> > > 1 file changed, 15 insertions(+), 6 deletions(-)
>> > >
>> > > diff --git a/net/core/dev.c b/net/core/dev.c
>> > > index fcddccb..cb9e5e5 100644
>> > > --- a/net/core/dev.c
>> > > +++ b/net/core/dev.c
>> > > @@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
>> > > static struct sk_buff *
>> > > sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
>> > > {
>> > > + struct netdev_queue *netdev_queue =
>> > > + rcu_dereference_bh(dev->ingress_queue);
>> > > struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
>> > > struct tcf_result cl_res;
>> > > + struct Qdisc *q;
>> > >
>> > > - if (!cl)
>> > > + if (!cl || !netdev_queue)
>> > > return skb;
>> > > + q = netdev_queue->qdisc;
>> >
>> > NAK, no additional overhead in the software fast-path of
>> > sch_handle_{ingress,egress}() like this. There are users out there
>> > that use tc in software only, so performance is critical here.
>>
>> Okay, how else do you suggest I can avoid the need to use tp->q?
>> I was thinking about storing q directly to net_device, which would safe
>> one dereference, resulting in the same amount as current cl->q.
>
>Sorry for late reply, mostly off for few days. netdev struct has different
>cachelines which are hot on rx and tx (see also the location of the two
>lists, ingress_cl_list and egress_cl_list), if you add only one qdisc
>pointer there, then you'd at least penalize one of the two w/ potential
>cache miss. Can we leave it in cl?
Well that is the whole point of this excercise, to remove it from cl.
The thing is, for the shared blocks, cls are shared between multiple
qdisc instances, so cl->q makes no longer any sense.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-15 6:45 ` Jiri Pirko
@ 2017-10-16 20:20 ` Daniel Borkmann
2017-10-17 7:42 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: Daniel Borkmann @ 2017-10-16 20:20 UTC (permalink / raw)
To: Jiri Pirko
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
On 10/15/2017 08:45 AM, Jiri Pirko wrote:
> Sun, Oct 15, 2017 at 01:18:54AM CEST, daniel@iogearbox.net wrote:
>> On 10/13/2017 08:30 AM, Jiri Pirko wrote:
>>> Thu, Oct 12, 2017 at 11:45:43PM CEST, daniel@iogearbox.net wrote:
>>>> On 10/12/2017 07:17 PM, Jiri Pirko wrote:
>>>>> From: Jiri Pirko <jiri@mellanox.com>
>>>>>
>>>>> In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
>>>>> dev->ingress_queue which stores the same pointer instead.
>>>>>
>>>>> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>>>>> ---
>>>>> net/core/dev.c | 21 +++++++++++++++------
>>>>> 1 file changed, 15 insertions(+), 6 deletions(-)
>>>>>
>>>>> diff --git a/net/core/dev.c b/net/core/dev.c
>>>>> index fcddccb..cb9e5e5 100644
>>>>> --- a/net/core/dev.c
>>>>> +++ b/net/core/dev.c
>>>>> @@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
>>>>> static struct sk_buff *
>>>>> sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
>>>>> {
>>>>> + struct netdev_queue *netdev_queue =
>>>>> + rcu_dereference_bh(dev->ingress_queue);
>>>>> struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
>>>>> struct tcf_result cl_res;
>>>>> + struct Qdisc *q;
>>>>>
>>>>> - if (!cl)
>>>>> + if (!cl || !netdev_queue)
>>>>> return skb;
>>>>> + q = netdev_queue->qdisc;
>>>>
>>>> NAK, no additional overhead in the software fast-path of
>>>> sch_handle_{ingress,egress}() like this. There are users out there
>>>> that use tc in software only, so performance is critical here.
>>>
>>> Okay, how else do you suggest I can avoid the need to use tp->q?
>>> I was thinking about storing q directly to net_device, which would safe
>>> one dereference, resulting in the same amount as current cl->q.
>>
>> Sorry for late reply, mostly off for few days. netdev struct has different
>> cachelines which are hot on rx and tx (see also the location of the two
>> lists, ingress_cl_list and egress_cl_list), if you add only one qdisc
>> pointer there, then you'd at least penalize one of the two w/ potential
>> cache miss. Can we leave it in cl?
>
> Well that is the whole point of this excercise, to remove it from cl.
> The thing is, for the shared blocks, cls are shared between multiple
> qdisc instances, so cl->q makes no longer any sense.
I don't really mind if you want to remove cl->q, but lets do it without
adding any cost to the fast path. The primary motivation for this set
is hw offload, but it shouldn't be at the expense to make sw fast path
slower. cl->q is only used here for updating stats, one possible option
could be to take them out for the clsact case into dev at the expense
for two pointers (e.g. getting rid of ingress_queue would reduce it to
only one pointer), such that you have percpu {ingress,egress}_cl_stats
that control path can fetch instead when dumping qdiscs. Could be one,
but there are probably other options as well to explore.
Thanks,
Daniel
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q
2017-10-16 20:20 ` Daniel Borkmann
@ 2017-10-17 7:42 ` Jiri Pirko
0 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-17 7:42 UTC (permalink / raw)
To: Daniel Borkmann
Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
f.fainelli, michael.chan, ganeshgr, jeffrey.t.kirsher, saeedm,
matanb, leonro, idosch, jakub.kicinski, ast, simon.horman,
pieter.jansenvanvuuren, john.hurley, edumazet, dsahern,
alexander.h.duyck, john.fastabend, willemb
Mon, Oct 16, 2017 at 10:20:04PM CEST, daniel@iogearbox.net wrote:
>On 10/15/2017 08:45 AM, Jiri Pirko wrote:
>> Sun, Oct 15, 2017 at 01:18:54AM CEST, daniel@iogearbox.net wrote:
>> > On 10/13/2017 08:30 AM, Jiri Pirko wrote:
>> > > Thu, Oct 12, 2017 at 11:45:43PM CEST, daniel@iogearbox.net wrote:
>> > > > On 10/12/2017 07:17 PM, Jiri Pirko wrote:
>> > > > > From: Jiri Pirko <jiri@mellanox.com>
>> > > > >
>> > > > > In sch_handle_egress and sch_handle_ingress, don't use tp->q and use
>> > > > > dev->ingress_queue which stores the same pointer instead.
>> > > > >
>> > > > > Signed-off-by: Jiri Pirko <jiri@mellanox.com>
>> > > > > ---
>> > > > > net/core/dev.c | 21 +++++++++++++++------
>> > > > > 1 file changed, 15 insertions(+), 6 deletions(-)
>> > > > >
>> > > > > diff --git a/net/core/dev.c b/net/core/dev.c
>> > > > > index fcddccb..cb9e5e5 100644
>> > > > > --- a/net/core/dev.c
>> > > > > +++ b/net/core/dev.c
>> > > > > @@ -3273,14 +3273,18 @@ EXPORT_SYMBOL(dev_loopback_xmit);
>> > > > > static struct sk_buff *
>> > > > > sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
>> > > > > {
>> > > > > + struct netdev_queue *netdev_queue =
>> > > > > + rcu_dereference_bh(dev->ingress_queue);
>> > > > > struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
>> > > > > struct tcf_result cl_res;
>> > > > > + struct Qdisc *q;
>> > > > >
>> > > > > - if (!cl)
>> > > > > + if (!cl || !netdev_queue)
>> > > > > return skb;
>> > > > > + q = netdev_queue->qdisc;
>> > > >
>> > > > NAK, no additional overhead in the software fast-path of
>> > > > sch_handle_{ingress,egress}() like this. There are users out there
>> > > > that use tc in software only, so performance is critical here.
>> > >
>> > > Okay, how else do you suggest I can avoid the need to use tp->q?
>> > > I was thinking about storing q directly to net_device, which would safe
>> > > one dereference, resulting in the same amount as current cl->q.
>> >
>> > Sorry for late reply, mostly off for few days. netdev struct has different
>> > cachelines which are hot on rx and tx (see also the location of the two
>> > lists, ingress_cl_list and egress_cl_list), if you add only one qdisc
>> > pointer there, then you'd at least penalize one of the two w/ potential
>> > cache miss. Can we leave it in cl?
>>
>> Well that is the whole point of this excercise, to remove it from cl.
>> The thing is, for the shared blocks, cls are shared between multiple
>> qdisc instances, so cl->q makes no longer any sense.
>
>I don't really mind if you want to remove cl->q, but lets do it without
>adding any cost to the fast path. The primary motivation for this set
>is hw offload, but it shouldn't be at the expense to make sw fast path
That is not precise. The reason is not only hw offload. User could use
the block sharing for pure sw solution as well and benefit from that.
>slower. cl->q is only used here for updating stats, one possible option
>could be to take them out for the clsact case into dev at the expense
>for two pointers (e.g. getting rid of ingress_queue would reduce it to
>only one pointer), such that you have percpu {ingress,egress}_cl_stats
>that control path can fetch instead when dumping qdiscs. Could be one,
>but there are probably other options as well to explore.
I'm currently looking at that. Thanks.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 27/34] nfp: bpf: Convert ndo_setup_tc offloads to block callbacks
2017-10-13 1:08 ` Jakub Kicinski
@ 2017-10-17 12:48 ` Jiri Pirko
2017-10-17 14:39 ` Jakub Kicinski
0 siblings, 1 reply; 53+ messages in thread
From: Jiri Pirko @ 2017-10-17 12:48 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev, Daniel Borkmann
Fri, Oct 13, 2017 at 03:08:24AM CEST, jakub.kicinski@netronome.com wrote:
>On Thu, 12 Oct 2017 19:18:16 +0200, Jiri Pirko wrote:
>> diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
>> index a88bb5b..9e9af88 100644
>> --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
>> +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
>> @@ -246,6 +246,10 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
>> void *code;
>> int err;
>>
>> + if (cls_bpf->common.protocol != htons(ETH_P_ALL) ||
>> + cls_bpf->common.chain_index)
>> + return -EOPNOTSUPP;
>> +
>> max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
>>
>> switch (cls_bpf->command) {
>
>It is certainly very ugly but I send a fake struct tc_cls_bpf_offload
>here for XDP. Refactoring this mess is pretty high on my priority list
>but one way or the other this function will be called from XDP so TC
>checks must stay in the TC handler... :(
Okay. But currently, why is it a problem? You don't need the checks for
xdp path.
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 27/34] nfp: bpf: Convert ndo_setup_tc offloads to block callbacks
2017-10-17 12:48 ` Jiri Pirko
@ 2017-10-17 14:39 ` Jakub Kicinski
2017-10-17 18:16 ` Jiri Pirko
0 siblings, 1 reply; 53+ messages in thread
From: Jakub Kicinski @ 2017-10-17 14:39 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, Daniel Borkmann
On Tue, 17 Oct 2017 14:48:12 +0200, Jiri Pirko wrote:
> Fri, Oct 13, 2017 at 03:08:24AM CEST, jakub.kicinski@netronome.com wrote:
> >On Thu, 12 Oct 2017 19:18:16 +0200, Jiri Pirko wrote:
> >> diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> >> index a88bb5b..9e9af88 100644
> >> --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> >> +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
> >> @@ -246,6 +246,10 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
> >> void *code;
> >> int err;
> >>
> >> + if (cls_bpf->common.protocol != htons(ETH_P_ALL) ||
> >> + cls_bpf->common.chain_index)
> >> + return -EOPNOTSUPP;
> >> +
> >> max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
> >>
> >> switch (cls_bpf->command) {
> >
> >It is certainly very ugly but I send a fake struct tc_cls_bpf_offload
> >here for XDP. Refactoring this mess is pretty high on my priority list
> >but one way or the other this function will be called from XDP so TC
> >checks must stay in the TC handler... :(
>
> Okay. But currently, why is it a problem? You don't need the checks for
> xdp path.
>
static int
nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
struct bpf_prog *prog)
{
struct tc_cls_bpf_offload cmd = {
.prog = prog,
};
int ret;
if (!nfp_net_ebpf_capable(nn))
return -EINVAL;
if (nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF) {
if (!nn->dp.bpf_offload_xdp)
return prog ? -EBUSY : 0;
cmd.command = prog ? TC_CLSBPF_REPLACE : TC_CLSBPF_DESTROY;
} else {
if (!prog)
return 0;
cmd.command = TC_CLSBPF_ADD;
}
ret = nfp_net_bpf_offload(nn, &cmd);
/* Stop offload if replace not possible */
if (ret && cmd.command == TC_CLSBPF_REPLACE)
nfp_bpf_xdp_offload(app, nn, NULL);
nn->dp.bpf_offload_xdp = prog && !ret;
return ret;
}
The fake offload struct is at the top of this function. Dereferencing
cls_bpf->common in nfp_net_bpf_offload() will crash the kernel. Or am
I missing something?
^ permalink raw reply [flat|nested] 53+ messages in thread
* Re: [patch net-next 27/34] nfp: bpf: Convert ndo_setup_tc offloads to block callbacks
2017-10-17 14:39 ` Jakub Kicinski
@ 2017-10-17 18:16 ` Jiri Pirko
0 siblings, 0 replies; 53+ messages in thread
From: Jiri Pirko @ 2017-10-17 18:16 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: netdev, Daniel Borkmann
Tue, Oct 17, 2017 at 04:39:59PM CEST, jakub.kicinski@netronome.com wrote:
>On Tue, 17 Oct 2017 14:48:12 +0200, Jiri Pirko wrote:
>> Fri, Oct 13, 2017 at 03:08:24AM CEST, jakub.kicinski@netronome.com wrote:
>> >On Thu, 12 Oct 2017 19:18:16 +0200, Jiri Pirko wrote:
>> >> diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
>> >> index a88bb5b..9e9af88 100644
>> >> --- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
>> >> +++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
>> >> @@ -246,6 +246,10 @@ int nfp_net_bpf_offload(struct nfp_net *nn, struct tc_cls_bpf_offload *cls_bpf)
>> >> void *code;
>> >> int err;
>> >>
>> >> + if (cls_bpf->common.protocol != htons(ETH_P_ALL) ||
>> >> + cls_bpf->common.chain_index)
>> >> + return -EOPNOTSUPP;
>> >> +
>> >> max_instr = nn_readw(nn, NFP_NET_CFG_BPF_MAX_LEN);
>> >>
>> >> switch (cls_bpf->command) {
>> >
>> >It is certainly very ugly but I send a fake struct tc_cls_bpf_offload
>> >here for XDP. Refactoring this mess is pretty high on my priority list
>> >but one way or the other this function will be called from XDP so TC
>> >checks must stay in the TC handler... :(
>>
>> Okay. But currently, why is it a problem? You don't need the checks for
>> xdp path.
>>
>
>static int
>nfp_bpf_xdp_offload(struct nfp_app *app, struct nfp_net *nn,
> struct bpf_prog *prog)
>{
> struct tc_cls_bpf_offload cmd = {
> .prog = prog,
> };
> int ret;
>
> if (!nfp_net_ebpf_capable(nn))
> return -EINVAL;
>
> if (nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF) {
> if (!nn->dp.bpf_offload_xdp)
> return prog ? -EBUSY : 0;
> cmd.command = prog ? TC_CLSBPF_REPLACE : TC_CLSBPF_DESTROY;
> } else {
> if (!prog)
> return 0;
> cmd.command = TC_CLSBPF_ADD;
> }
>
> ret = nfp_net_bpf_offload(nn, &cmd);
> /* Stop offload if replace not possible */
> if (ret && cmd.command == TC_CLSBPF_REPLACE)
> nfp_bpf_xdp_offload(app, nn, NULL);
> nn->dp.bpf_offload_xdp = prog && !ret;
> return ret;
>}
>
>The fake offload struct is at the top of this function. Dereferencing
>cls_bpf->common in nfp_net_bpf_offload() will crash the kernel. Or am
>I missing something?
We just have to init it. Should not be a problem. Will add it.
^ permalink raw reply [flat|nested] 53+ messages in thread
end of thread, other threads:[~2017-10-17 18:16 UTC | newest]
Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-12 17:17 [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances Jiri Pirko
2017-10-12 17:17 ` [patch net-next 01/34] net: sched: store Qdisc pointer in struct block Jiri Pirko
2017-10-12 17:17 ` [patch net-next 02/34] net: sched: introduce support for multiple filter chain pointers registration Jiri Pirko
2017-10-12 17:17 ` [patch net-next 03/34] net: sched: introduce shared filter blocks infrastructure Jiri Pirko
2017-10-12 17:17 ` [patch net-next 04/34] net: sched: teach tcf_bind/unbind_filter to use block->q Jiri Pirko
2017-10-12 17:17 ` [patch net-next 05/34] net: sched: ematch: obtain net pointer from blocks Jiri Pirko
2017-10-12 17:17 ` [patch net-next 06/34] net: core: use dev->ingress_queue instead of tp->q Jiri Pirko
2017-10-12 21:45 ` Daniel Borkmann
2017-10-13 6:30 ` Jiri Pirko
2017-10-14 23:18 ` Daniel Borkmann
2017-10-15 6:45 ` Jiri Pirko
2017-10-16 20:20 ` Daniel Borkmann
2017-10-17 7:42 ` Jiri Pirko
2017-10-12 17:17 ` [patch net-next 07/34] net: sched: cls_u32: use block instead of q in tc_u_common Jiri Pirko
2017-10-12 17:17 ` [patch net-next 08/34] net: sched: avoid usage of tp->q in tcf_classify Jiri Pirko
2017-10-12 17:17 ` [patch net-next 09/34] net: sched: tcindex, fw, flow: use tcf_block_q helper to get struct Qdisc Jiri Pirko
2017-10-12 17:17 ` [patch net-next 10/34] net: sched: use tcf_block_q helper to get q pointer for sch_tree_lock Jiri Pirko
2017-10-12 17:18 ` [patch net-next 11/34] net: sched: propagate q and parent from caller down to tcf_fill_node Jiri Pirko
2017-10-12 17:18 ` [patch net-next 12/34] net: sched: add block bind/unbind notification to drivers Jiri Pirko
2017-10-12 17:18 ` [patch net-next 13/34] net: sched: introduce per-block callbacks Jiri Pirko
2017-10-12 17:18 ` [patch net-next 14/34] net: sched: use extended variants of block get and put in ingress and clsact qdiscs Jiri Pirko
2017-10-12 17:18 ` [patch net-next 15/34] net: sched: use tc_setup_cb_call to call per-block callbacks Jiri Pirko
2017-10-12 17:18 ` [patch net-next 16/34] net: sched: cls_matchall: call block callbacks for offload Jiri Pirko
2017-10-12 17:18 ` [patch net-next 17/34] net: sched: cls_u32: swap u32_remove_hw_knode and u32_remove_hw_hnode Jiri Pirko
2017-10-12 17:18 ` [patch net-next 18/34] net: sched: cls_u32: call block callbacks for offload Jiri Pirko
2017-10-12 17:18 ` [patch net-next 19/34] net: sched: cls_bpf: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 20/34] mlxsw: spectrum: Convert ndo_setup_tc offloads to block callbacks Jiri Pirko
2017-10-12 17:18 ` [patch net-next 21/34] mlx5e: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 22/34] bnxt: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 23/34] cxgb4: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 24/34] ixgbe: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 25/34] mlx5e_rep: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 26/34] nfp: flower: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 27/34] nfp: bpf: " Jiri Pirko
2017-10-13 1:08 ` Jakub Kicinski
2017-10-17 12:48 ` Jiri Pirko
2017-10-17 14:39 ` Jakub Kicinski
2017-10-17 18:16 ` Jiri Pirko
2017-10-12 17:18 ` [patch net-next 28/34] dsa: " Jiri Pirko
2017-10-12 17:18 ` [patch net-next 29/34] net: sched: avoid ndo_setup_tc calls for TC_SETUP_CLS* Jiri Pirko
2017-10-12 17:18 ` [patch net-next 30/34] net: sched: remove unused classid field from tc_cls_common_offload Jiri Pirko
2017-10-12 17:18 ` [patch net-next 31/34] net: sched: remove unused is_classid_clsact_ingress/egress helpers Jiri Pirko
2017-10-12 17:18 ` [patch net-next 32/34] net: sched: introduce block mechanism to handle netif_keep_dst calls Jiri Pirko
2017-10-12 17:18 ` [patch net-next 33/34] net: sched: remove classid and q fields from tcf_proto Jiri Pirko
2017-10-12 17:18 ` [patch net-next 34/34] net: sched: allow ingress and clsact qdiscs to share filter blocks Jiri Pirko
2017-10-12 17:21 ` [patch net-next 00/34] net: sched: allow qdiscs to share filter block instances David Miller
2017-10-13 6:21 ` Jiri Pirko
2017-10-13 6:31 ` David Miller
2017-10-13 7:39 ` Jiri Pirko
2017-10-12 21:37 ` David Ahern
2017-10-13 6:26 ` Jiri Pirko
2017-10-13 14:20 ` David Ahern
2017-10-13 14:24 ` Jiri Pirko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).