* [Patch net 03/15] net_sched: remove RCU callbacks in flower filter
From: Cong Wang @ 2017-10-23 22:02 UTC (permalink / raw)
To: netdev
Cc: paulmck, jhs, john.fastabend, Chris Mi, Cong Wang,
Daniel Borkmann, Jiri Pirko
In-Reply-To: <20171023220304.2268-1-xiyou.wangcong@gmail.com>
Replace call_rcu() with synchronize_rcu(), except
in fl_destroy() we have to use list_splice_init_rcu().
As a bonus, this also drops the ugly code in commit
d936377414fa ("net, sched: respect rcu grace period on cls destruction").
Reported-by: Chris Mi <chrism@mellanox.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Jiri Pirko <jiri@resnulli.us>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
net/sched/cls_flower.c | 46 ++++++++++++++--------------------------------
1 file changed, 14 insertions(+), 32 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index b480d7c792ba..ad33bd00b4f0 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -61,7 +61,6 @@ struct fl_flow_mask_range {
struct fl_flow_mask {
struct fl_flow_key key;
struct fl_flow_mask_range range;
- struct rcu_head rcu;
};
struct cls_fl_head {
@@ -71,10 +70,6 @@ struct cls_fl_head {
bool mask_assigned;
struct list_head filters;
struct rhashtable_params ht_params;
- union {
- struct work_struct work;
- struct rcu_head rcu;
- };
struct idr handle_idr;
};
@@ -87,7 +82,6 @@ struct cls_fl_filter {
struct list_head list;
u32 handle;
u32 flags;
- struct rcu_head rcu;
struct net_device *hw_dev;
};
@@ -215,10 +209,8 @@ static int fl_init(struct tcf_proto *tp)
return 0;
}
-static void fl_destroy_filter(struct rcu_head *head)
+static void fl_destroy_filter(struct cls_fl_filter *f)
{
- struct cls_fl_filter *f = container_of(head, struct cls_fl_filter, rcu);
-
tcf_exts_destroy(&f->exts);
kfree(f);
}
@@ -305,38 +297,25 @@ static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
if (!tc_skip_hw(f->flags))
fl_hw_destroy_filter(tp, f);
tcf_unbind_filter(tp, &f->res);
- call_rcu(&f->rcu, fl_destroy_filter);
-}
-
-static void fl_destroy_sleepable(struct work_struct *work)
-{
- struct cls_fl_head *head = container_of(work, struct cls_fl_head,
- work);
- if (head->mask_assigned)
- rhashtable_destroy(&head->ht);
- kfree(head);
- module_put(THIS_MODULE);
-}
-
-static void fl_destroy_rcu(struct rcu_head *rcu)
-{
- struct cls_fl_head *head = container_of(rcu, struct cls_fl_head, rcu);
-
- INIT_WORK(&head->work, fl_destroy_sleepable);
- schedule_work(&head->work);
}
static void fl_destroy(struct tcf_proto *tp)
{
struct cls_fl_head *head = rtnl_dereference(tp->root);
struct cls_fl_filter *f, *next;
+ LIST_HEAD(local);
+
+ list_splice_init_rcu(&head->filters, &local, synchronize_rcu);
- list_for_each_entry_safe(f, next, &head->filters, list)
+ list_for_each_entry_safe(f, next, &local, list) {
__fl_delete(tp, f);
+ fl_destroy_filter(f);
+ }
idr_destroy(&head->handle_idr);
- __module_get(THIS_MODULE);
- call_rcu(&head->rcu, fl_destroy_rcu);
+ if (head->mask_assigned)
+ rhashtable_destroy(&head->ht);
+ kfree(head);
}
static void *fl_get(struct tcf_proto *tp, u32 handle)
@@ -975,7 +954,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
idr_replace_ext(&head->handle_idr, fnew, fnew->handle);
list_replace_rcu(&fold->list, &fnew->list);
tcf_unbind_filter(tp, &fold->res);
- call_rcu(&fold->rcu, fl_destroy_filter);
+ synchronize_rcu();
+ fl_destroy_filter(fold);
} else {
list_add_tail_rcu(&fnew->list, &head->filters);
}
@@ -1003,6 +983,8 @@ static int fl_delete(struct tcf_proto *tp, void *arg, bool *last)
rhashtable_remove_fast(&head->ht, &f->ht_node,
head->ht_params);
__fl_delete(tp, f);
+ synchronize_rcu();
+ fl_destroy_filter(f);
*last = list_empty(&head->filters);
return 0;
}
--
2.13.0
^ permalink raw reply related
* [Patch net 02/15] net_sched: remove RCU callbacks in bpf filter
From: Cong Wang @ 2017-10-23 22:02 UTC (permalink / raw)
To: netdev; +Cc: paulmck, jhs, john.fastabend, Chris Mi, Cong Wang,
Daniel Borkmann
In-Reply-To: <20171023220304.2268-1-xiyou.wangcong@gmail.com>
Replace call_rcu() with synchronize_rcu(), except in
cls_bpf_destroy() we have to use list_splice_init_rcu().
Reported-by: Chris Mi <chrism@mellanox.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
net/sched/cls_bpf.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index 520c5027646a..11571b6539f2 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -33,7 +33,6 @@ MODULE_DESCRIPTION("TC BPF based classifier");
struct cls_bpf_head {
struct list_head plist;
u32 hgen;
- struct rcu_head rcu;
};
struct cls_bpf_prog {
@@ -49,7 +48,6 @@ struct cls_bpf_prog {
struct sock_filter *bpf_ops;
const char *bpf_name;
struct tcf_proto *tp;
- struct rcu_head rcu;
};
static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = {
@@ -257,17 +255,11 @@ static void __cls_bpf_delete_prog(struct cls_bpf_prog *prog)
kfree(prog);
}
-static void cls_bpf_delete_prog_rcu(struct rcu_head *rcu)
-{
- __cls_bpf_delete_prog(container_of(rcu, struct cls_bpf_prog, rcu));
-}
-
static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog)
{
cls_bpf_stop_offload(tp, prog);
list_del_rcu(&prog->link);
tcf_unbind_filter(tp, &prog->res);
- call_rcu(&prog->rcu, cls_bpf_delete_prog_rcu);
}
static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last)
@@ -275,6 +267,8 @@ static int cls_bpf_delete(struct tcf_proto *tp, void *arg, bool *last)
struct cls_bpf_head *head = rtnl_dereference(tp->root);
__cls_bpf_delete(tp, arg);
+ synchronize_rcu();
+ __cls_bpf_delete_prog((struct cls_bpf_prog *)arg);
*last = list_empty(&head->plist);
return 0;
}
@@ -283,11 +277,16 @@ static void cls_bpf_destroy(struct tcf_proto *tp)
{
struct cls_bpf_head *head = rtnl_dereference(tp->root);
struct cls_bpf_prog *prog, *tmp;
+ LIST_HEAD(local);
- list_for_each_entry_safe(prog, tmp, &head->plist, link)
+ list_splice_init_rcu(&head->plist, &local, synchronize_rcu);
+
+ list_for_each_entry_safe(prog, tmp, &local, link) {
__cls_bpf_delete(tp, prog);
+ __cls_bpf_delete_prog(prog);
+ }
- kfree_rcu(head, rcu);
+ kfree(head);
}
static void *cls_bpf_get(struct tcf_proto *tp, u32 handle)
@@ -501,7 +500,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
if (oldprog) {
list_replace_rcu(&oldprog->link, &prog->link);
tcf_unbind_filter(tp, &oldprog->res);
- call_rcu(&oldprog->rcu, cls_bpf_delete_prog_rcu);
+ synchronize_rcu();
+ __cls_bpf_delete_prog(oldprog);
} else {
list_add_rcu(&prog->link, &head->plist);
}
--
2.13.0
^ permalink raw reply related
* [Patch net 01/15] net_sched: remove RCU callbacks in basic filter
From: Cong Wang @ 2017-10-23 22:02 UTC (permalink / raw)
To: netdev; +Cc: paulmck, jhs, john.fastabend, Chris Mi, Cong Wang,
Daniel Borkmann
In-Reply-To: <20171023220304.2268-1-xiyou.wangcong@gmail.com>
Replace call_rcu() with synchronize_rcu(), except
in basic_destroy() we have to use list_splice_init_rcu().
Reported-by: Chris Mi <chrism@mellanox.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
---
net/sched/cls_basic.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index d89ebafd2239..11bca8346e0f 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -24,7 +24,6 @@
struct basic_head {
u32 hgenerator;
struct list_head flist;
- struct rcu_head rcu;
};
struct basic_filter {
@@ -34,7 +33,6 @@ struct basic_filter {
struct tcf_result res;
struct tcf_proto *tp;
struct list_head link;
- struct rcu_head rcu;
};
static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -82,10 +80,8 @@ static int basic_init(struct tcf_proto *tp)
return 0;
}
-static void basic_delete_filter(struct rcu_head *head)
+static void basic_delete_filter(struct basic_filter *f)
{
- struct basic_filter *f = container_of(head, struct basic_filter, rcu);
-
tcf_exts_destroy(&f->exts);
tcf_em_tree_destroy(&f->ematches);
kfree(f);
@@ -95,13 +91,16 @@ static void basic_destroy(struct tcf_proto *tp)
{
struct basic_head *head = rtnl_dereference(tp->root);
struct basic_filter *f, *n;
+ LIST_HEAD(local);
+
+ list_splice_init_rcu(&head->flist, &local, synchronize_rcu);
- list_for_each_entry_safe(f, n, &head->flist, link) {
- list_del_rcu(&f->link);
+ list_for_each_entry_safe(f, n, &local, link) {
+ list_del(&f->link);
tcf_unbind_filter(tp, &f->res);
- call_rcu(&f->rcu, basic_delete_filter);
+ basic_delete_filter(f);
}
- kfree_rcu(head, rcu);
+ kfree(head);
}
static int basic_delete(struct tcf_proto *tp, void *arg, bool *last)
@@ -111,7 +110,8 @@ static int basic_delete(struct tcf_proto *tp, void *arg, bool *last)
list_del_rcu(&f->link);
tcf_unbind_filter(tp, &f->res);
- call_rcu(&f->rcu, basic_delete_filter);
+ synchronize_rcu();
+ basic_delete_filter(f);
*last = list_empty(&head->flist);
return 0;
}
@@ -205,7 +205,8 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
if (fold) {
list_replace_rcu(&fold->link, &fnew->link);
tcf_unbind_filter(tp, &fold->res);
- call_rcu(&fold->rcu, basic_delete_filter);
+ synchronize_rcu();
+ basic_delete_filter(fold);
} else {
list_add_rcu(&fnew->link, &head->flist);
}
--
2.13.0
^ permalink raw reply related
* [Patch net 00/15] net_sched: remove RCU callbacks from TC
From: Cong Wang @ 2017-10-23 22:02 UTC (permalink / raw)
To: netdev; +Cc: paulmck, jhs, john.fastabend, Chris Mi, Cong Wang
Recently, the RCU callbacks used in TC filters and TC actions keep
drawing my attention, they introduce at least 4 race condition bugs:
1. A simple one fixed by Daniel:
commit c78e1746d3ad7d548bdf3fe491898cc453911a49
Author: Daniel Borkmann <daniel@iogearbox.net>
Date: Wed May 20 17:13:33 2015 +0200
net: sched: fix call_rcu() race on classifier module unloads
2. A very nasty one fixed by me:
commit 1697c4bb5245649a23f06a144cc38c06715e1b65
Author: Cong Wang <xiyou.wangcong@gmail.com>
Date: Mon Sep 11 16:33:32 2017 -0700
net_sched: carefully handle tcf_block_put()
3. Two more bugs found by Chris:
https://patchwork.ozlabs.org/patch/826696/
https://patchwork.ozlabs.org/patch/826695/
Usually RCU callbacks are simple, however for TC filters and actions,
they are complex because at least TC actions could be destroyed
together with the TC filter in one callback. And RCU callbacks are
invoked in BH context, without locking they are parallel too. All of
these contribute to the cause of these nasty bugs. It looks like they
bring us more troubles than benefits.
Alternatively, we could also:
a) Introduce a spinlock to serialize these RCU callbacks. But as I
said in commit 1697c4bb5245 ("net_sched: carefully handle
tcf_block_put()"), it is very hard to do because of tcf_chain_dump().
Potentially we need to do a lot of work to make it possible, if not
impossible.
b) As suggested by Paul, we could defer the work to a workqueue and
gain the permission of holding RTNL again without any performance
impact, however, this seems impossible too, because as lockdep
complains we have a deadlock when flushing workqueue while hodling
RTNL lock, see the rcu_barrier() in tcf_block_put().
Therefore, the simplest solution we have is probably just getting
rid of these RCU callbacks, because they are not necessary at all,
callers of these call_rcu() are all on slow paths and have RTNL
lock, so blocking is allowed in their contexts.
The downside is this could hurt the performance of deleting TC
filters, but again it is not a hot path and I already batch
synchronize_rcu() whenever needed.
Different filters have different data structures, so please also
see each patch for details.
Chris Mi (2):
selftests: Introduce a new script to generate tc batch file
selftests: Introduce a new test case to tc testsuite
Cong Wang (13):
net_sched: remove RCU callbacks in basic filter
net_sched: remove RCU callbacks in bpf filter
net_sched: remove RCU callbacks in flower filter
net_sched: remove RCU callbacks in matchall filter
net_sched: remove RCU callbacks in cgroup filter
net_sched: remove RCU callbacks in rsvp filter
net_sched: remove RCU callbacks in flow filter
net_sched: remove RCU callbacks in tcindex filter
net_sched: remove RCU callbacks in u32 filter
net_sched: remove RCU callbacks in fw filter
net_sched: remove RCU callbacks in route filter
net_sched: remove RCU callbacks in sample action
net_sched: add rtnl assertion to tcf_exts_destroy()
include/net/tc_act/tc_sample.h | 1 -
net/sched/act_sample.c | 12 +---
net/sched/cls_api.c | 1 +
net/sched/cls_basic.c | 23 ++++----
net/sched/cls_bpf.c | 22 ++++----
net/sched/cls_cgroup.c | 18 +++---
net/sched/cls_flow.c | 24 ++++----
net/sched/cls_flower.c | 46 +++++-----------
net/sched/cls_fw.c | 18 +++---
net/sched/cls_matchall.c | 9 +--
net/sched/cls_route.c | 21 +++----
net/sched/cls_rsvp.h | 13 +----
net/sched/cls_tcindex.c | 35 +++++-------
net/sched/cls_u32.c | 64 ++++++----------------
.../tc-testing/tc-tests/filters/tests.json | 23 +++++++-
tools/testing/selftests/tc-testing/tdc.py | 20 +++++--
tools/testing/selftests/tc-testing/tdc_batch.py | 62 +++++++++++++++++++++
tools/testing/selftests/tc-testing/tdc_config.py | 2 +
18 files changed, 222 insertions(+), 192 deletions(-)
create mode 100644 tools/testing/selftests/tc-testing/tdc_batch.py
--
2.13.0
^ permalink raw reply
* [PATCH net-next] ipv6: add ip6_null_entry check in rt6_select()
From: Wei Wang @ 2017-10-23 21:59 UTC (permalink / raw)
To: David Miller, netdev; +Cc: Eric Dumazet, Martin KaFai Lau, Wei Wang
From: Wei Wang <weiwan@google.com>
In rt6_select(), fn->leaf could be pointing to net->ipv6.ip6_null_entry.
In this case, we should directly return instead of trying to carry on
with the rest of the process.
If not, we could crash at:
spin_lock_bh(&leaf->rt6i_table->rt6_lock);
because net->ipv6.ip6_null_entry does not have rt6i_table set.
Syzkaller recently reported following issue on net-next:
Use struct sctp_sack_info instead
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] SMP KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in:
sctp: [Deprecated]: syz-executor4 (pid 26496) Use of struct sctp_assoc_value in delayed_ack socket option.
Use struct sctp_sack_info instead
CPU: 1 PID: 26523 Comm: syz-executor6 Not tainted 4.14.0-rc4+ #85
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
task: ffff8801d147e3c0 task.stack: ffff8801a4328000
RIP: 0010:debug_spin_lock_before kernel/locking/spinlock_debug.c:83 [inline]
RIP: 0010:do_raw_spin_lock+0x23/0x1e0 kernel/locking/spinlock_debug.c:112
RSP: 0018:ffff8801a432ed70 EFLAGS: 00010207
RAX: dffffc0000000000 RBX: 0000000000000018 RCX: 0000000000000000
RDX: 0000000000000003 RSI: 0000000000000000 RDI: 000000000000001c
RBP: ffff8801a432ed90 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000000 R11: ffffffff8482b279 R12: ffff8801ce2ff3a0
sctp: [Deprecated]: syz-executor1 (pid 26546) Use of int in maxseg socket option.
Use struct sctp_assoc_value instead
R13: dffffc0000000000 R14: ffff8801d971e000 R15: ffff8801ce2ff0d8
FS: 00007f56e82f5700(0000) GS:ffff8801db300000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000001ddbc22000 CR3: 00000001a4a04000 CR4: 00000000001406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
__raw_spin_lock_bh include/linux/spinlock_api_smp.h:136 [inline]
_raw_spin_lock_bh+0x39/0x40 kernel/locking/spinlock.c:175
spin_lock_bh include/linux/spinlock.h:321 [inline]
rt6_select net/ipv6/route.c:786 [inline]
ip6_pol_route+0x1be3/0x3bd0 net/ipv6/route.c:1650
sctp: [Deprecated]: syz-executor1 (pid 26576) Use of int in maxseg socket option.
Use struct sctp_assoc_value instead
TCP: request_sock_TCPv6: Possible SYN flooding on port 20002. Sending cookies. Check SNMP counters.
ip6_pol_route_output+0x4c/0x60 net/ipv6/route.c:1843
fib6_rule_lookup+0x9e/0x2a0 net/ipv6/ip6_fib.c:309
ip6_route_output_flags+0x1f1/0x2b0 net/ipv6/route.c:1871
ip6_route_output include/net/ip6_route.h:80 [inline]
ip6_dst_lookup_tail+0x4ea/0x970 net/ipv6/ip6_output.c:953
ip6_dst_lookup_flow+0xc8/0x270 net/ipv6/ip6_output.c:1076
sctp_v6_get_dst+0x675/0x1c30 net/sctp/ipv6.c:274
sctp_transport_route+0xa8/0x430 net/sctp/transport.c:287
sctp_assoc_add_peer+0x4fe/0x1100 net/sctp/associola.c:656
__sctp_connect+0x251/0xc80 net/sctp/socket.c:1187
sctp_connect+0xb4/0xf0 net/sctp/socket.c:4209
inet_dgram_connect+0x16b/0x1f0 net/ipv4/af_inet.c:541
SYSC_connect+0x20a/0x480 net/socket.c:1642
SyS_connect+0x24/0x30 net/socket.c:1623
entry_SYSCALL_64_fastpath+0x1f/0xbe
Fixes: 66f5d6ce53e6 ("ipv6: replace rwlock with rcu and spinlock in fib6_table")
Signed-off-by: Wei Wang <weiwan@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
---
net/ipv6/route.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 46c59a53c53f..605e5dc1c010 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -752,7 +752,7 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
bool do_rr = false;
int key_plen;
- if (!leaf)
+ if (!leaf || leaf == net->ipv6.ip6_null_entry)
return net->ipv6.ip6_null_entry;
rt0 = rcu_dereference(fn->rr_ptr);
--
2.15.0.rc0.271.g36b669edcc-goog
^ permalink raw reply related
* Re: [PATCH v8 01/10] dt-bindings: net: Restore sun8i dwmac binding
From: Rob Herring @ 2017-10-23 21:58 UTC (permalink / raw)
To: Corentin Labbe
Cc: mark.rutland-5wv7dgnIgG8,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, peppe.cavallaro-qxv4g6HH51o,
alexandre.torgue-qxv4g6HH51o, andrew-g2DYL2Zd6BY,
f.fainelli-Re5JQEeQqe8AvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171023185626.31793-2-clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Mon, Oct 23, 2017 at 08:56:17PM +0200, Corentin Labbe wrote:
> The original dwmac-sun8i DT bindings have some issue on how to handle
> integrated PHY and was reverted in last RC of 4.13.
> But now we have a solution so we need to get back that was reverted.
>
> This patch restore dt-bindings documentation about dwmac-sun8i
> This reverts commit 8aa33ec2f481 ("dt-bindings: net: Revert sun8i dwmac binding")
>
> Signed-off-by: Corentin Labbe <clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
> .../devicetree/bindings/net/dwmac-sun8i.txt | 84 ++++++++++++++++++++++
> 1 file changed, 84 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/dwmac-sun8i.txt
Please add acks when posting new versions.
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [patch net-next] net: core: introduce mini_Qdisc and eliminate usage of tp->q for clsact fastpath
From: Jiri Pirko @ 2017-10-23 21:28 UTC (permalink / raw)
To: netdev
Cc: davem, jhs, xiyou.wangcong, mlxsw, edumazet, daniel,
alexander.h.duyck, willemb, john.fastabend
From: Jiri Pirko <jiri@mellanox.com>
In sch_handle_egress and sch_handle_ingress tp->q is used only in order
to update stats. So stats and filter list are the only things that are
needed in clsact qdisc fastpath processing. Introduce new mini_Qdisc
struct to hold those items. This removes need for tp->q usage without
added overhead.
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/linux/netdevice.h | 9 ++++++---
include/net/pkt_cls.h | 1 +
include/net/sch_generic.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
net/core/dev.c | 21 +++++++++++++--------
net/sched/cls_api.c | 23 ++++++++++++++++++-----
net/sched/sch_ingress.c | 40 +++++++++++++++++++++++++++++++---------
6 files changed, 114 insertions(+), 25 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6c7960c8..f0bdaf7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1558,6 +1558,8 @@ enum netdev_priv_flags {
*
* @rx_handler: handler for received packets
* @rx_handler_data: XXX: need comments on this one
+ * @miniq_ingress: ingress/clsact qdisc specific data for
+ * ingress processing
* @ingress_queue: XXX: need comments on this one
* @broadcast: hw bcast address
*
@@ -1575,7 +1577,8 @@ enum netdev_priv_flags {
* @tx_global_lock: XXX: need comments on this one
*
* @xps_maps: XXX: need comments on this one
- *
+ * @miniq_egress: clsact qdisc specific data for
+ * egress processing
* @watchdog_timeo: Represents the timeout that is used by
* the watchdog (see dev_watchdog())
* @watchdog_timer: List of timers
@@ -1794,7 +1797,7 @@ struct net_device {
void __rcu *rx_handler_data;
#ifdef CONFIG_NET_CLS_ACT
- struct tcf_proto __rcu *ingress_cl_list;
+ struct mini_Qdisc __rcu *miniq_ingress;
#endif
struct netdev_queue __rcu *ingress_queue;
#ifdef CONFIG_NETFILTER_INGRESS
@@ -1825,7 +1828,7 @@ struct net_device {
struct xps_dev_maps __rcu *xps_maps;
#endif
#ifdef CONFIG_NET_CLS_ACT
- struct tcf_proto __rcu *egress_cl_list;
+ struct mini_Qdisc __rcu *miniq_egress;
#endif
/* These may be needed for future network-power-down code. */
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 04caa24..0b2e3a7 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -25,6 +25,7 @@ enum tcf_block_binder_type {
struct tcf_block_ext_info {
enum tcf_block_binder_type binder_type;
+ tcf_chain_change_empty_t *chain_change_empty;
};
struct tcf_block_cb;
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 031dffd..c7ddbdb 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -143,6 +143,36 @@ static inline int qdisc_avail_bulklimit(const struct netdev_queue *txq)
#endif
}
+/* Mini Qdisc serves for specific needs of ingress/clsact Qdisc.
+ * The fast path only needs to access filter list and to update stats
+ */
+struct mini_Qdisc {
+ struct tcf_proto __rcu *filter_list;
+ struct gnet_stats_basic_cpu __percpu *cpu_bstats;
+ struct gnet_stats_queue __percpu *cpu_qstats;
+ struct mini_Qdisc __rcu **p_miniq;
+};
+
+static inline void mini_qdisc_init(struct mini_Qdisc *miniq,
+ struct Qdisc *qdisc,
+ struct mini_Qdisc __rcu **p_miniq)
+{
+ miniq->cpu_bstats = qdisc->cpu_bstats;
+ miniq->cpu_qstats = qdisc->cpu_qstats;
+ miniq->p_miniq = p_miniq;
+}
+
+static inline void mini_qdisc_enable(struct mini_Qdisc *miniq)
+{
+ rcu_assign_pointer(*miniq->p_miniq, miniq);
+}
+
+static inline void mini_qdisc_disable(struct mini_Qdisc *miniq)
+{
+ RCU_INIT_POINTER(*miniq->p_miniq, NULL);
+ rcu_barrier();
+}
+
struct Qdisc_class_ops {
/* Child qdisc manipulation */
struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *);
@@ -259,9 +289,13 @@ struct qdisc_skb_cb {
unsigned char data[QDISC_CB_PRIV_LEN];
};
+typedef void tcf_chain_change_empty_t(struct tcf_proto __rcu **p_filter_chain,
+ bool empty);
+
struct tcf_chain {
struct tcf_proto __rcu *filter_chain;
struct tcf_proto __rcu **p_filter_chain;
+ tcf_chain_change_empty_t *chain_change_empty;
struct list_head list;
struct tcf_block *block;
u32 index; /* chain index */
@@ -605,6 +639,12 @@ static inline void qdisc_bstats_cpu_update(struct Qdisc *sch,
bstats_cpu_update(this_cpu_ptr(sch->cpu_bstats), skb);
}
+static inline void mini_qdisc_bstats_cpu_update(struct mini_Qdisc *miniq,
+ const struct sk_buff *skb)
+{
+ bstats_cpu_update(this_cpu_ptr(miniq->cpu_bstats), skb);
+}
+
static inline void qdisc_bstats_update(struct Qdisc *sch,
const struct sk_buff *skb)
{
@@ -648,6 +688,11 @@ static inline void qdisc_qstats_cpu_drop(struct Qdisc *sch)
this_cpu_inc(sch->cpu_qstats->drops);
}
+static inline void mini_qdisc_qstats_cpu_drop(struct mini_Qdisc *miniq)
+{
+ this_cpu_inc(miniq->cpu_qstats->drops);
+}
+
static inline void qdisc_qstats_overlimit(struct Qdisc *sch)
{
sch->qstats.overlimits++;
diff --git a/net/core/dev.c b/net/core/dev.c
index 24ac908..b4a5812 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3274,14 +3274,16 @@ EXPORT_SYMBOL(dev_loopback_xmit);
static struct sk_buff *
sch_handle_egress(struct sk_buff *skb, int *ret, struct net_device *dev)
{
- struct tcf_proto *cl = rcu_dereference_bh(dev->egress_cl_list);
+ struct mini_Qdisc *miniq = rcu_dereference_bh(skb->dev->miniq_egress);
struct tcf_result cl_res;
+ struct tcf_proto *cl;
- if (!cl)
+ if (!miniq)
return skb;
+ cl = rcu_dereference_bh(miniq->filter_list);
/* qdisc_skb_cb(skb)->pkt_len was already set by the caller. */
- qdisc_bstats_cpu_update(cl->q, skb);
+ mini_qdisc_bstats_cpu_update(miniq, skb);
switch (tcf_classify(skb, cl, &cl_res, false)) {
case TC_ACT_OK:
@@ -3289,7 +3291,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);
+ mini_qdisc_qstats_cpu_drop(miniq);
*ret = NET_XMIT_DROP;
kfree_skb(skb);
return NULL;
@@ -4189,16 +4191,19 @@ 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 tcf_proto *cl = rcu_dereference_bh(skb->dev->ingress_cl_list);
+ struct mini_Qdisc *miniq = rcu_dereference_bh(skb->dev->miniq_ingress);
struct tcf_result cl_res;
+ struct tcf_proto *cl;
/* 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 (!miniq)
return skb;
+ cl = rcu_dereference_bh(miniq->filter_list);
+
if (*pt_prev) {
*ret = deliver_skb(skb, *pt_prev, orig_dev);
*pt_prev = NULL;
@@ -4206,7 +4211,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);
+ mini_qdisc_bstats_cpu_update(miniq, skb);
switch (tcf_classify(skb, cl, &cl_res, false)) {
case TC_ACT_OK:
@@ -4214,7 +4219,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);
+ mini_qdisc_qstats_cpu_drop(miniq);
kfree_skb(skb);
return NULL;
case TC_ACT_STOLEN:
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index cdfdc24..f1e6fe7 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -190,8 +190,11 @@ static void tcf_chain_flush(struct tcf_chain *chain)
{
struct tcf_proto *tp;
- if (chain->p_filter_chain)
+ if (chain->p_filter_chain) {
+ if (chain->chain_change_empty)
+ chain->chain_change_empty(chain->p_filter_chain, true);
RCU_INIT_POINTER(*chain->p_filter_chain, NULL);
+ }
while ((tp = rtnl_dereference(chain->filter_chain)) != NULL) {
RCU_INIT_POINTER(chain->filter_chain, tp->next);
tcf_chain_put(chain);
@@ -235,9 +238,11 @@ EXPORT_SYMBOL(tcf_chain_put);
static void
tcf_chain_filter_chain_ptr_set(struct tcf_chain *chain,
- struct tcf_proto __rcu **p_filter_chain)
+ struct tcf_proto __rcu **p_filter_chain,
+ struct tcf_block_ext_info *ei)
{
chain->p_filter_chain = p_filter_chain;
+ chain->chain_change_empty = ei->chain_change_empty;
}
static void tcf_block_offload_cmd(struct tcf_block *block, struct Qdisc *q,
@@ -286,7 +291,7 @@ int tcf_block_get_ext(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_set(chain, p_filter_chain, ei);
block->net = qdisc_net(q);
block->q = q;
tcf_block_offload_bind(block, q, ei);
@@ -528,8 +533,13 @@ static void tcf_chain_tp_insert(struct tcf_chain *chain,
struct tcf_proto *tp)
{
if (chain->p_filter_chain &&
- *chain_info->pprev == chain->filter_chain)
+ *chain_info->pprev == chain->filter_chain) {
+ bool was_null = *chain->p_filter_chain == NULL;
+
rcu_assign_pointer(*chain->p_filter_chain, tp);
+ if (was_null && chain->chain_change_empty)
+ chain->chain_change_empty(chain->p_filter_chain, false);
+ }
RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain_info));
rcu_assign_pointer(*chain_info->pprev, tp);
tcf_chain_hold(chain);
@@ -541,8 +551,11 @@ 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)
+ if (chain->p_filter_chain && tp == chain->filter_chain) {
+ if (!next && chain->chain_change_empty)
+ chain->chain_change_empty(chain->p_filter_chain, true);
RCU_INIT_POINTER(*chain->p_filter_chain, next);
+ }
RCU_INIT_POINTER(*chain_info->pprev, next);
tcf_chain_put(chain);
}
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index b599db2..45f6e43 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -21,6 +21,7 @@
struct ingress_sched_data {
struct tcf_block *block;
struct tcf_block_ext_info block_info;
+ struct mini_Qdisc miniq;
};
static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
@@ -54,6 +55,19 @@ static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl)
return q->block;
}
+static void clsact_chain_change_empty(struct tcf_proto __rcu **p_filter_list,
+ bool empty)
+{
+ struct mini_Qdisc *miniq = container_of(p_filter_list,
+ struct mini_Qdisc,
+ filter_list);
+
+ if (empty)
+ mini_qdisc_disable(miniq);
+ else
+ mini_qdisc_enable(miniq);
+}
+
static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
{
struct ingress_sched_data *q = qdisc_priv(sch);
@@ -61,8 +75,10 @@ static int ingress_init(struct Qdisc *sch, struct nlattr *opt)
int err;
q->block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+ q->block_info.chain_change_empty = clsact_chain_change_empty;
- err = tcf_block_get_ext(&q->block, &dev->ingress_cl_list,
+ mini_qdisc_init(&q->miniq, sch, &dev->miniq_ingress);
+ err = tcf_block_get_ext(&q->block, &q->miniq.filter_list,
sch, &q->block_info);
if (err)
return err;
@@ -76,9 +92,8 @@ 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_ext(q->block, &dev->ingress_cl_list,
+ tcf_block_put_ext(q->block, &q->miniq.filter_list,
sch, &q->block_info);
net_dec_ingress_queue();
}
@@ -122,6 +137,8 @@ struct clsact_sched_data {
struct tcf_block *egress_block;
struct tcf_block_ext_info ingress_block_info;
struct tcf_block_ext_info egress_block_info;
+ struct mini_Qdisc miniq_ingress;
+ struct mini_Qdisc miniq_egress;
};
static unsigned long clsact_find(struct Qdisc *sch, u32 classid)
@@ -162,15 +179,21 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
int err;
q->ingress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS;
+ q->ingress_block_info.chain_change_empty = clsact_chain_change_empty;
- err = tcf_block_get_ext(&q->ingress_block, &dev->ingress_cl_list,
+ mini_qdisc_init(&q->miniq_ingress, sch, &dev->miniq_ingress);
+ err = tcf_block_get_ext(&q->ingress_block,
+ &q->miniq_ingress.filter_list,
sch, &q->ingress_block_info);
if (err)
return err;
q->egress_block_info.binder_type = TCF_BLOCK_BINDER_TYPE_CLSACT_EGRESS;
+ q->egress_block_info.chain_change_empty = clsact_chain_change_empty;
- err = tcf_block_get_ext(&q->egress_block, &dev->egress_cl_list,
+ mini_qdisc_init(&q->miniq_egress, sch, &dev->miniq_egress);
+ err = tcf_block_get_ext(&q->egress_block,
+ &q->miniq_egress.filter_list,
sch, &q->egress_block_info);
if (err)
goto err_egress_block_get;
@@ -183,7 +206,7 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
return 0;
err_egress_block_get:
- tcf_block_put_ext(q->ingress_block, &dev->ingress_cl_list,
+ tcf_block_put_ext(q->ingress_block, &q->miniq_ingress.filter_list,
sch, &q->ingress_block_info);
return err;
}
@@ -191,11 +214,10 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt)
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_ext(q->egress_block, &dev->egress_cl_list,
+ tcf_block_put_ext(q->egress_block, &q->miniq_egress.filter_list,
sch, &q->egress_block_info);
- tcf_block_put_ext(q->ingress_block, &dev->ingress_cl_list,
+ tcf_block_put_ext(q->ingress_block, &q->miniq_ingress.filter_list,
sch, &q->ingress_block_info);
net_dec_ingress_queue();
--
2.9.5
^ permalink raw reply related
* Re: [PATCH net-next 0/2] net: dsa: don't unmask port bitmaps
From: Vivien Didelot @ 2017-10-23 21:26 UTC (permalink / raw)
To: Andrew Lunn
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <20171023211109.GA23689@lunn.ch>
Hi Andrew,
Andrew Lunn <andrew@lunn.ch> writes:
> On Mon, Oct 23, 2017 at 02:17:29PM -0400, Vivien Didelot wrote:
>> DSA has several bitmaps to store the type of ports: cpu_port_mask,
>> dsa_port_mask and enabled_port_mask. But the code is inconsistently
>> unmasking them.
>>
>> The legacy code tries to unmask cpu_port_mask and dsa_port_mask but
>> skips enabled_port_mask.
>>
>> The new bindings unmasks cpu_port_mask and enabled_port_mask but skips
>> dsa_port_mask.
>>
>> In fact there is no need to unmask them because we are in the error
>> path, and they won't be used after. Instead of fixing the unmasking,
>> simply remove them.
>
> I'm not looked at the code, travelling and don't have time.
heu, ok.
> What happens if the failure is -PROBE_DEFERRED, and it tried again
> later. Will these masks be set back to 0? Or will they retain the old
> values? I think there is supposed to be symmetry here, so that we undo
> what we did, and so the next time we try again, we start from a good
> state.
The type of a port is a static information parsed either from device
tree or from platform data. Thus there is no symmetry needed here.
The fact that the unmasking of these bitmaps is currently erroneous also
shows that it is unnecessary.
Thanks,
Vivien
^ permalink raw reply
* Re: [PATCH net-next 0/2] net: dsa: don't unmask port bitmaps
From: Andrew Lunn @ 2017-10-23 21:11 UTC (permalink / raw)
To: Vivien Didelot
Cc: netdev, linux-kernel, kernel, David S. Miller, Florian Fainelli
In-Reply-To: <20171023181731.7977-1-vivien.didelot@savoirfairelinux.com>
On Mon, Oct 23, 2017 at 02:17:29PM -0400, Vivien Didelot wrote:
> DSA has several bitmaps to store the type of ports: cpu_port_mask,
> dsa_port_mask and enabled_port_mask. But the code is inconsistently
> unmasking them.
>
> The legacy code tries to unmask cpu_port_mask and dsa_port_mask but
> skips enabled_port_mask.
>
> The new bindings unmasks cpu_port_mask and enabled_port_mask but skips
> dsa_port_mask.
>
> In fact there is no need to unmask them because we are in the error
> path, and they won't be used after. Instead of fixing the unmasking,
> simply remove them.
Hi Vivien
I'm not looked at the code, travelling and don't have time.
What happens if the failure is -PROBE_DEFERRED, and it tried again
later. Will these masks be set back to 0? Or will they retain the old
values? I think there is supposed to be symmetry here, so that we undo
what we did, and so the next time we try again, we start from a good
state.
Andrew
^ permalink raw reply
* Re: [PATCH net-next 2/3] bpf: permit multiple bpf attachments for a single perf event
From: Yonghong Song @ 2017-10-23 21:00 UTC (permalink / raw)
To: Daniel Borkmann, peterz, rostedt, ast, kafai, netdev; +Cc: kernel-team
In-Reply-To: <59EE568D.7040204@iogearbox.net>
On 10/23/17 1:52 PM, Daniel Borkmann wrote:
> On 10/23/2017 07:58 PM, Yonghong Song wrote:
> [...]
>> __this_cpu_dec(bpf_prog_active);
>> @@ -741,3 +754,63 @@ const struct bpf_verifier_ops
>> perf_event_verifier_ops = {
>>
>> const struct bpf_prog_ops perf_event_prog_ops = {
>> };
>> +
>> +static DEFINE_MUTEX(bpf_event_mutex);
>> +
>> +int perf_event_attach_bpf_prog(struct perf_event *event,
>> + struct bpf_prog *prog)
>> +{
>> + struct bpf_prog_array __rcu *old_array;
>> + struct bpf_prog_array *new_array;
>> + int ret;
>> +
>> + mutex_lock(&bpf_event_mutex);
>> +
>> + if (event->prog)
>> + return -EEXIST;
>
> Needs to go to out here, otherwise deadlock.
Thanks for catching this! Will fix this and the below one as well in the
new revision.
>
>> +
>> + old_array = rcu_dereference_protected(event->tp_event->prog_array,
>> + lockdep_is_held(&bpf_event_mutex));
>> + ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array);
>> + if (ret < 0)
>> + goto out;
>> +
>> + /* set the new array to event->tp_event and set event->prog */
>> + event->prog = prog;
>> + rcu_assign_pointer(event->tp_event->prog_array, new_array);
>> +
>> + if (old_array)
>> + bpf_prog_array_free(old_array);
>> +
>> +out:
>> + mutex_unlock(&bpf_event_mutex);
>> + return ret;
>> +}
>> +
>> +void perf_event_detach_bpf_prog(struct perf_event *event)
>> +{
>> + struct bpf_prog_array __rcu *old_array;
>> + struct bpf_prog_array *new_array;
>> + int ret;
>> +
>> + mutex_lock(&bpf_event_mutex);
>> +
>> + if (!event->prog)
>> + return;
>
> Ditto.
>
>> +
>> + old_array = rcu_dereference_protected(event->tp_event->prog_array,
>> + lockdep_is_held(&bpf_event_mutex));
>> +
>> + ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array);
>> + if (ret < 0) {
>> + bpf_prog_array_delete_safe(old_array, event->prog);
>> + } else {
>> + rcu_assign_pointer(event->tp_event->prog_array, new_array);
>> + bpf_prog_array_free(old_array);
>> + }
>> +
>> + bpf_prog_put(event->prog);
>> + event->prog = NULL;
>> +
>> + mutex_unlock(&bpf_event_mutex);
>> +}
> [...]
^ permalink raw reply
* Re: [PATCH net-next 2/3] bpf: permit multiple bpf attachments for a single perf event
From: Daniel Borkmann @ 2017-10-23 20:52 UTC (permalink / raw)
To: Yonghong Song, peterz, rostedt, ast, kafai, netdev; +Cc: kernel-team
In-Reply-To: <20171023175805.2898366-3-yhs@fb.com>
On 10/23/2017 07:58 PM, Yonghong Song wrote:
[...]
> __this_cpu_dec(bpf_prog_active);
> @@ -741,3 +754,63 @@ const struct bpf_verifier_ops perf_event_verifier_ops = {
>
> const struct bpf_prog_ops perf_event_prog_ops = {
> };
> +
> +static DEFINE_MUTEX(bpf_event_mutex);
> +
> +int perf_event_attach_bpf_prog(struct perf_event *event,
> + struct bpf_prog *prog)
> +{
> + struct bpf_prog_array __rcu *old_array;
> + struct bpf_prog_array *new_array;
> + int ret;
> +
> + mutex_lock(&bpf_event_mutex);
> +
> + if (event->prog)
> + return -EEXIST;
Needs to go to out here, otherwise deadlock.
> +
> + old_array = rcu_dereference_protected(event->tp_event->prog_array,
> + lockdep_is_held(&bpf_event_mutex));
> + ret = bpf_prog_array_copy(old_array, NULL, prog, &new_array);
> + if (ret < 0)
> + goto out;
> +
> + /* set the new array to event->tp_event and set event->prog */
> + event->prog = prog;
> + rcu_assign_pointer(event->tp_event->prog_array, new_array);
> +
> + if (old_array)
> + bpf_prog_array_free(old_array);
> +
> +out:
> + mutex_unlock(&bpf_event_mutex);
> + return ret;
> +}
> +
> +void perf_event_detach_bpf_prog(struct perf_event *event)
> +{
> + struct bpf_prog_array __rcu *old_array;
> + struct bpf_prog_array *new_array;
> + int ret;
> +
> + mutex_lock(&bpf_event_mutex);
> +
> + if (!event->prog)
> + return;
Ditto.
> +
> + old_array = rcu_dereference_protected(event->tp_event->prog_array,
> + lockdep_is_held(&bpf_event_mutex));
> +
> + ret = bpf_prog_array_copy(old_array, event->prog, NULL, &new_array);
> + if (ret < 0) {
> + bpf_prog_array_delete_safe(old_array, event->prog);
> + } else {
> + rcu_assign_pointer(event->tp_event->prog_array, new_array);
> + bpf_prog_array_free(old_array);
> + }
> +
> + bpf_prog_put(event->prog);
> + event->prog = NULL;
> +
> + mutex_unlock(&bpf_event_mutex);
> +}
[...]
^ permalink raw reply
* Re: [net-next PATCH] bpf: cpumap fix potential lost wake-up problem
From: Daniel Borkmann @ 2017-10-23 20:34 UTC (permalink / raw)
To: Jesper Dangaard Brouer, netdev, Michael S. Tsirkin
Cc: Rik van Riel, Daniel Borkmann, Alexei Starovoitov
In-Reply-To: <150878036830.4768.8540758939081367484.stgit@firesoul>
On 10/23/2017 07:39 PM, Jesper Dangaard Brouer wrote:
> As pointed out by Michael, commit 1c601d829ab0 ("bpf: cpumap xdp_buff
> to skb conversion and allocation") contains a classical example of the
> potential lost wake-up problem.
>
> We need to recheck the condition __ptr_ring_empty() after changing
> current->state to TASK_INTERRUPTIBLE, this avoids a race between
> wake_up_process() and schedule(). After this, a race with
> wake_up_process() will simply change the state to TASK_RUNNING, and
> the schedule() call not really put us to sleep.
>
> Fixes: 1c601d829ab0 ("bpf: cpumap xdp_buff to skb conversion and allocation")
> Reported-by: "Michael S. Tsirkin" <mst@redhat.com>
SOB missing ...
^ permalink raw reply
* Re: [PATCH net-next 12/12] tools: bpftool: update documentation for --json and --pretty usage
From: Daniel Borkmann @ 2017-10-23 20:34 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-13-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Update the documentation to provide help about JSON output generation,
> and add an example in bpftool-prog manual page.
>
> Also reintroduce an example that was left aside when the tool was moved
> from GitHub to the kernel sources, in order to show how to mount the
> bpffs file system (to pin programs) inside the bpftool-prog manual page.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 11/12] tools: bpftool: add cosmetic changes for the manual pages
From: Daniel Borkmann @ 2017-10-23 20:33 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-12-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Make the look-and-feel of the manual pages somewhat closer to other
> manual pages, such as the ones from the utilities from iproute2, by
> highlighting more keywords.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
> Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 10/12] tools: bpftool: provide JSON output for all possible commands
From: Daniel Borkmann @ 2017-10-23 20:33 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-11-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> As all commands can now return JSON output (possibly just a "null"
> value), output of `bpftool --json batch file FILE` should also be fully
> JSON compliant.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 09/12] tools: bpftool: turn err() and info() macros into functions
From: Daniel Borkmann @ 2017-10-23 20:33 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-10-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Turn err() and info() macros into functions.
>
> In order to avoid naming conflicts with variables in the code, rename
> them as p_err() and p_info() respectively.
>
> The behavior of these functions is similar to the one of the macros for
> plain output. However, when JSON output is requested, these macros
> return a JSON-formatted "error" object instead of printing a message to
> stderr.
>
> To handle error messages correctly with JSON, a modification was brought
> to their behavior nonetheless: the functions now append a end-of-line
> character at the end of the message. This way, we can remove end-of-line
> characters at the end of the argument strings, and not have them in the
> JSON output.
>
> All error messages are formatted to hold in a single call to p_err(), in
> order to produce a single JSON field.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
> Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 08/12] tools: bpftool: add JSON output for `bpftool batch file FILE` command
From: Daniel Borkmann @ 2017-10-23 20:32 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-9-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> `bpftool batch file FILE` takes FILE as an argument and executes all the
> bpftool commands it finds inside (or stops if an error occurs).
>
> To obtain a consistent JSON output, create a root JSON array, then for
> each command create a new object containing two fields: one with the
> command arguments, the other with the output (which is the JSON object
> that the command would have produced, if called on its own).
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 07/12] tools: bpftool: add JSON output for `bpftool map *` commands
From: Daniel Borkmann @ 2017-10-23 20:32 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-8-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Reuse the json_writer API introduced in an earlier commit to make
> bpftool able to generate JSON output on
> `bpftool map { show | dump | lookup | getnext }` commands. Remaining
> commands produce no output.
>
> Some functions have been spit into plain-output and JSON versions in
> order to remain readable.
>
> Outputs for sample maps have been successfully tested against a JSON
> validator.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 06/12] tools: bpftool: add JSON output for `bpftool prog dump xlated *` command
From: Daniel Borkmann @ 2017-10-23 20:32 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-7-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Add a new printing function to dump translated eBPF instructions as
> JSON. As for plain output, opcodes are printed only on request (when
> `opcodes` is provided on the command line).
>
> The disassembled output is generated by the same code that is used by
> the kernel verifier.
>
> Example output:
>
> $ bpftool --json --pretty prog dump xlated id 1
> [{
> "disasm": "(bf) r6 = r1"
> },{
> "disasm": "(61) r7 = *(u32 *)(r6 +16)"
> },{
> "disasm": "(95) exit"
> }
> ]
>
> $ bpftool --json --pretty prog dump xlated id 1 opcodes
> [{
> "disasm": "(bf) r6 = r1",
> "opcodes": {
> "code": "0xbf",
> "src_reg": "0x1",
> "dst_reg": "0x6",
> "off": ["0x00","0x00"
> ],
> "imm": ["0x00","0x00","0x00","0x00"
> ]
> }
> },{
> "disasm": "(61) r7 = *(u32 *)(r6 +16)",
> "opcodes": {
> "code": "0x61",
> "src_reg": "0x6",
> "dst_reg": "0x7",
> "off": ["0x10","0x00"
> ],
> "imm": ["0x00","0x00","0x00","0x00"
> ]
> }
> },{
> "disasm": "(95) exit",
> "opcodes": {
> "code": "0x95",
> "src_reg": "0x0",
> "dst_reg": "0x0",
> "off": ["0x00","0x00"
> ],
> "imm": ["0x00","0x00","0x00","0x00"
> ]
> }
> }
> ]
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH] net: sunrpc: svcauth_gss: use BUG_ON instead of if condition followed by BUG
From: J. Bruce Fields @ 2017-10-23 20:31 UTC (permalink / raw)
To: Gustavo A. R. Silva
Cc: Jeff Layton, Trond Myklebust, Anna Schumaker, David S. Miller,
linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20171023181635.GA25334-L1vi/lXTdts+Va1GwOuvDg@public.gmane.org>
In the past we've avoided BUG_ON(X) where X might have side effects, on
the theory that it should actually be OK just to compile out BUG_ON()s.
Has that changed?
In any case, I don't find that this improves readability; dropping.
--b.
On Mon, Oct 23, 2017 at 01:16:35PM -0500, Gustavo A. R. Silva wrote:
> Use BUG_ON instead of if condition followed by BUG.
>
> This issue was detected with the help of Coccinelle.
>
> Signed-off-by: Gustavo A. R. Silva <garsilva-L1vi/lXTdts+Va1GwOuvDg@public.gmane.org>
> ---
> net/sunrpc/auth_gss/svcauth_gss.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
> index 7b1ee5a..a10ce43 100644
> --- a/net/sunrpc/auth_gss/svcauth_gss.c
> +++ b/net/sunrpc/auth_gss/svcauth_gss.c
> @@ -855,11 +855,9 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g
> return stat;
> if (integ_len > buf->len)
> return stat;
> - if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len))
> - BUG();
> + BUG_ON(xdr_buf_subsegment(buf, &integ_buf, 0, integ_len));
> /* copy out mic... */
> - if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
> - BUG();
> + BUG_ON(read_u32_from_xdr_buf(buf, integ_len, &mic.len));
> if (mic.len > RPC_MAX_AUTH_SIZE)
> return stat;
> mic.data = kmalloc(mic.len, GFP_KERNEL);
> @@ -1611,8 +1609,7 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
> BUG_ON(integ_len % 4);
> *p++ = htonl(integ_len);
> *p++ = htonl(gc->gc_seq);
> - if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len))
> - BUG();
> + BUG_ON(xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len));
> if (resbuf->tail[0].iov_base == NULL) {
> if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE)
> goto out_err;
> --
> 2.7.4
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next 05/12] tools: bpftool: add JSON output for `bpftool prog dump jited *` command
From: Daniel Borkmann @ 2017-10-23 20:31 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-6-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Reuse the json_writer API introduced in an earlier commit to make
> bpftool able to generate JSON output on `bpftool prog show *` commands.
> A new printing function is created to be passed as an argument to the
> disassembler.
>
> Similarly to plain output, opcodes are printed on request.
>
> Outputs from sample programs have been successfully tested against a
> JSON validator.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 04/12] tools: bpftool: add JSON output for `bpftool prog show *` command
From: Daniel Borkmann @ 2017-10-23 20:30 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-5-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Reuse the json_writer API introduced in an earlier commit to make
> bpftool able to generate JSON output on `bpftool prog show *` commands.
>
> For readability, the code from show_prog() has been split into two
> functions, one for plain output, one for JSON.
>
> Outputs from sample programs have been successfully tested against a
> JSON validator.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 03/12] tools: bpftool: introduce --json and --pretty options
From: Daniel Borkmann @ 2017-10-23 20:30 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-4-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> These two options can be used to ask for a JSON output (--j or -json),
> and to make this JSON human-readable (-p or --pretty).
>
> A json_writer object is created when JSON is required, and will be used
> in follow-up commits to produce JSON output.
>
> Note that --pretty implies --json.
>
> Update for the manual pages and interactive help messages comes in a
> later patch of the series.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 02/12] tools: bpftool: add option parsing to bpftool, --help and --version
From: Daniel Borkmann @ 2017-10-23 20:30 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-3-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> Add an option parsing facility to bpftool, in prevision of future
> options for demanding JSON output. Currently, two options are added:
> --help and --version, that act the same as the respective commands
> `help` and `version`.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
* Re: [PATCH net-next 01/12] tools: bpftool: copy JSON writer from iproute2 repository
From: Daniel Borkmann @ 2017-10-23 20:29 UTC (permalink / raw)
To: Jakub Kicinski, netdev; +Cc: oss-drivers, alexei.starovoitov, Quentin Monnet
In-Reply-To: <20171023162416.32753-2-jakub.kicinski@netronome.com>
On 10/23/2017 06:24 PM, Jakub Kicinski wrote:
> From: Quentin Monnet <quentin.monnet@netronome.com>
>
> In prevision of following commits, supposed to add JSON output to the
> tool, two files are copied from the iproute2 repository (taken at commit
> 268a9eee985f): lib/json_writer.c and include/json_writer.h.
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox