From: Cong Wang <hidden> Date: 2016-09-02 05:57:46
Currently there are only two tc actions lockless:
gact and mirred. But they are questionable because
we don't have anything to prevent a parallel update
on an existing tc action in hash table while reading
it on fast path, this could be a problem when a tc
action becomes complex.
This patchset introduces a few new tc action API's
based on RCU so that the fast path could now really
be protected by RCU and we can update existing tc
actions safely and race-freely.
Obviously this is still _not_ complete yet, I only
modified mirred action to show the use case of
the new API's, all the rest actions could switch to
the new API's too. The new API's are a bit ugly too,
any suggestion to improve them is welcome.
I tested mirred action with a few test cases, so far
so good, at least no obvious bugs. ;)
Cong Wang (6):
net_sched: use RCU for action hash table
net_sched: introduce tcf_hash_replace()
net_sched: return NULL in tcf_hash_check()
net_sched: introduce tcf_hash_copy()
net_sched: use rcu in fast path
net_sched: switch to RCU API for act_mirred
include/net/act_api.h | 3 +++
net/sched/act_api.c | 59 +++++++++++++++++++++++++++++++++++++++++++-------
net/sched/act_mirred.c | 41 ++++++++++++++++-------------------
3 files changed, 73 insertions(+), 30 deletions(-)
--
2.1.0
From: Cong Wang <hidden> Date: 2016-09-02 05:57:46
We already free tc actions in a RCU callback, so here
we just need to convert the hash table operations to
RCU API's.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <redacted>
---
net/sched/act_api.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
From: Cong Wang <hidden> Date: 2016-09-02 05:57:48
When we don't find an action with a specific index,
we only return false but not touch *a. It is nicer
if we could set *a to NULL here, this would make
callers easier to use these API's.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <redacted>
---
net/sched/act_api.c | 1 +
1 file changed, 1 insertion(+)
From: Cong Wang <hidden> Date: 2016-09-02 05:57:48
This API is used to replace the old action in hash table
with the new one. It is used by the following patch.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <redacted>
---
include/net/act_api.h | 2 ++
net/sched/act_api.c | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+)
@@ -296,6 +296,24 @@ int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,}EXPORT_SYMBOL(tcf_hash_create);+booltcf_hash_copy(structtc_action*dst,conststructtc_action*src)+{+if(src){+memcpy(dst,src,sizeof(*src));+spin_lock_init(&dst->tcfa_lock);+INIT_HLIST_NODE(&dst->tcfa_head);+INIT_LIST_HEAD(&dst->list);++/* tcf_hash_check() is called before this */+dst->tcfa_refcnt=src->tcfa_refcnt-1;+if(src->tcfa_bindcnt)+dst->tcfa_bindcnt=src->tcfa_bindcnt-1;+returntrue;+}+returnfalse;+}+EXPORT_SYMBOL(tcf_hash_copy);+voidtcf_hash_insert(structtc_action_net*tn,structtc_action*a){structtcf_hashinfo*hinfo=tn->hinfo;
@@ -470,10 +470,14 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,gotoexec_done;}for(i=0;i<nr_actions;i++){-conststructtc_action*a=actions[i];+conststructtc_action*a;+rcu_read_lock();+a=rcu_dereference(actions[i]);repeat:ret=a->ops->act(skb,a,res);+rcu_read_unlock();+if(ret==TC_ACT_REPEAT)gotorepeat;/* we need a ttl - JHS */if(ret!=TC_ACT_PIPE)
Fri, Sep 02, 2016 at 07:57:14AM CEST, xiyou.wangcong@gmail.com wrote:
Currently there are only two tc actions lockless:
gact and mirred. But they are questionable because
we don't have anything to prevent a parallel update
on an existing tc action in hash table while reading
it on fast path, this could be a problem when a tc
action becomes complex.
This patchset introduces a few new tc action API's
based on RCU so that the fast path could now really
be protected by RCU and we can update existing tc
actions safely and race-freely.
Obviously this is still _not_ complete yet, I only
modified mirred action to show the use case of
the new API's, all the rest actions could switch to
the new API's too. The new API's are a bit ugly too,
any suggestion to improve them is welcome.
I tested mirred action with a few test cases, so far
so good, at least no obvious bugs. ;)
I wonder, do you happen to have a very tiny narrow screen?
From: Jamal Hadi Salim <jhs@mojatatu.com> Date: 2016-09-06 12:47:56
On 16-09-02 01:57 AM, Cong Wang wrote:
We already free tc actions in a RCU callback, so here
we just need to convert the hash table operations to
RCU API's.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <redacted>
This one stands on its own merit, no?
So:
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
cheers,
jamal
+void tcf_hash_replace(struct tc_action_net *tn, struct tc_action **old,+ struct tc_action *new, int bind)+{+ struct tcf_hashinfo *hinfo = tn->hinfo;+ unsigned int h = tcf_hash(new->tcfa_index, hinfo->hmask);+
WWhy do you need to recreate the index?
Old index was fine since this is just a replacement..
The rest of the patches seem fine - will let Eric comment on the
mirred.
Note: I am going to still push forward with skbmod action and I think
so should the new tunnel action code i.e we make them independent.
I'd like to switch to this when we think it is stable.
cheers,
jamal
From: Eric Dumazet <hidden> Date: 2016-09-06 14:52:10
On Thu, 2016-09-01 at 22:57 -0700, Cong Wang wrote:
Missing changelog ?
Here I have no idea what you want to fix, since John already took care
all this infra.
Adding extra rcu_dereference() and rcu_read_lock() while the critical
RCU dereferences already happen in callers is not needed.
+void tcf_hash_replace(struct tc_action_net *tn, struct tc_action **old,+ struct tc_action *new, int bind)+{+ struct tcf_hashinfo *hinfo = tn->hinfo;+ unsigned int h = tcf_hash(new->tcfa_index, hinfo->hmask);+
WWhy do you need to recreate the index?
Old index was fine since this is just a replacement..
A new index is possible created by tcf_hash_create(), but later
overwritten by tcf_hash_copy(). I know this is a bit ugly, so
feel free to suggest any better API here.
The rest of the patches seem fine - will let Eric comment on the
mirred.
Note: I am going to still push forward with skbmod action and I think
so should the new tunnel action code i.e we make them independent.
I'd like to switch to this when we think it is stable.
You don't have to rebase or change, I will take care of it because they
will probably be merged before this patchset. At least I can hold on
this for a while to let that happen. ;)
Thanks.
From: Cong Wang <hidden> Date: 2016-09-06 22:38:10
On Tue, Sep 6, 2016 at 5:47 AM, Jamal Hadi Salim [off-list ref] wrote:
On 16-09-02 01:57 AM, Cong Wang wrote:
quoted
We already free tc actions in a RCU callback, so here
we just need to convert the hash table operations to
RCU API's.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <redacted>
This one stands on its own merit, no?
Yes, I think so. I think it is fine to carry it in this patchset too.
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-07 16:23:28
On 16-09-01 10:57 PM, Cong Wang wrote:
Currently there are only two tc actions lockless:
gact and mirred. But they are questionable because
we don't have anything to prevent a parallel update
on an existing tc action in hash table while reading
it on fast path, this could be a problem when a tc
action becomes complex.
hmm I'm trying to see where the questionable part is in the current
code? What is it exactly.
The calls to
tcf_lastuse_update(&m->tcf_tm);
for example are possibly wrong as that is a u64 may be set from
multiple cores. So fixing that seems like a good idea.
Actions themselves don't have a path to be "updated" while live do they?
iirc and I think a quick scan this morning of the code shows actions
have a refcnt and a "bind"/"release" action that increments/decrements
this counter. Both bind and release are protected via rtnl lock in the
control path.
I need to follow all the code paths but is there a way to remove an
action that still has a refcnt > 0? In other words does it need to be
removed from all filters before it can be deleted. If yes then by the
time it is removed (after rcu grace period) it should not be in use.
If no then I think there is a problem.
I'm looking at this code path here,
int __tcf_hash_release(struct tc_action *p, bool bind, bool strict)
{
int ret = 0;
if (p) {
if (bind)
p->tcfa_bindcnt--;
else if (strict && p->tcfa_bindcnt > 0)
return -EPERM;
p->tcfa_refcnt--;
if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
if (p->ops->cleanup)
p->ops->cleanup(p, bind);
tcf_hash_destroy(p->hinfo, p);
ret = ACT_P_DELETED;
}
}
return ret;
}
It looks to me that every call site that jumps here where its possible
an action is being used by a filter is "strict". And further filters
only release actions after an rcu grace period when being destroyed and
the filter is no longer using the action.
Although the refcnt should be atomic now that its being called from
outside the rtnl lock in rcu call back? At least it looks racy to me
at a glance this morning.
If the refcnt'ing is atomic then do we care/need the hash rcu bits? I'm
not seeing how it helps because in the fast path we don't even touch the
hash table we have a pointer to a refcnt'd action object.
What did I miss?
This patchset introduces a few new tc action API's
based on RCU so that the fast path could now really
be protected by RCU and we can update existing tc
actions safely and race-freely.
Obviously this is still _not_ complete yet, I only
modified mirred action to show the use case of
the new API's, all the rest actions could switch to
the new API's too. The new API's are a bit ugly too,
any suggestion to improve them is welcome.
I tested mirred action with a few test cases, so far
so good, at least no obvious bugs. ;)
Take a quick survey of the actions I didn't see any with global state.
But I didn't look at them all.
Cong Wang (6):
net_sched: use RCU for action hash table
net_sched: introduce tcf_hash_replace()
net_sched: return NULL in tcf_hash_check()
net_sched: introduce tcf_hash_copy()
net_sched: use rcu in fast path
net_sched: switch to RCU API for act_mirred
include/net/act_api.h | 3 +++
net/sched/act_api.c | 59 +++++++++++++++++++++++++++++++++++++++++++-------
net/sched/act_mirred.c | 41 ++++++++++++++++-------------------
3 files changed, 73 insertions(+), 30 deletions(-)
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-08 06:16:37
On 16-09-06 07:52 AM, Eric Dumazet wrote:
On Thu, 2016-09-01 at 22:57 -0700, Cong Wang wrote:
Missing changelog ?
Yeah this stuff is a bit tricky more notes to walk us through
this would be helpful. (btw you can disregard my comment from
earlier this morning I've tracked most of this down now)
Here I have no idea what you want to fix, since John already took care
all this infra.
Adding extra rcu_dereference() and rcu_read_lock() while the critical
RCU dereferences already happen in callers is not needed.
Agreed drop all the extra rcu_read_lock/unlock here.
But the caller already has rcu_read_lock() or rcu_read_lock_bh()
This was done in commit 25d8c0d55f241ce2 ("net: rcu-ify tcf_proto")
quoted
+ a = rcu_dereference(actions[i]);
Add in your .config :
CONFIG_SPARSE_RCU_POINTER=y
make C=2 M=net/sched
quoted
repeat: ret = a->ops->act(skb, a, res);+ rcu_read_unlock();+ if (ret == TC_ACT_REPEAT) goto repeat; /* we need a ttl - JHS */ if (ret != TC_ACT_PIPE)
I do not believe this patch is necessary.
Please add John as reviewer next time.
Thanks.
So the actual issue as I see it is with the late binding actions the
ones created with the ill documented 'tc action' syntax.
If you add a rule here and then bind it to a filter (stealing Jamals
example),
tc actions add action skbedit mark 10 index 1
tc filter add dev $DEV parent ffff: protocol ip prio 1 u32\
match ip dst 17.0.0.1/32 flowid 1:10 action skbedit index 1
then you can modify this action later with the following
tc actions replace action ....
So for an action such as act_mirred we may end up running with a
partially updated state from this,
tcf_mirred_init(...)
[...]
m->tcf_action = parm->action;
m->tcfm_eaction = parm->eaction;
[...]
and then in the execution of the action,
tcf_mirred(...)
[...]
retval = READ_ONCE(m->tcf_action);
[...]
if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
[...]
So its at least possible I think these could be interleaved on multiple
cpus.
Notice that some of the actions are fine though and don't have this
issue act_bpf for example is fine.
I think we can either fix it in the hash table create part of the
list as this series does or just let each action handle it on its own.
.John
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-08 07:02:21
On 16-09-07 09:23 AM, John Fastabend wrote:
On 16-09-01 10:57 PM, Cong Wang wrote:
quoted
Currently there are only two tc actions lockless:
gact and mirred. But they are questionable because
we don't have anything to prevent a parallel update
on an existing tc action in hash table while reading
it on fast path, this could be a problem when a tc
action becomes complex.
hmm I'm trying to see where the questionable part is in the current
code? What is it exactly.
From: Eric Dumazet <hidden> Date: 2016-09-08 13:28:07
On Wed, 2016-09-07 at 23:04 -0700, John Fastabend wrote:
So the actual issue as I see it is with the late binding actions the
ones created with the ill documented 'tc action' syntax.
If you add a rule here and then bind it to a filter (stealing Jamals
example),
tc actions add action skbedit mark 10 index 1
tc filter add dev $DEV parent ffff: protocol ip prio 1 u32\
match ip dst 17.0.0.1/32 flowid 1:10 action skbedit index 1
then you can modify this action later with the following
tc actions replace action ....
So for an action such as act_mirred we may end up running with a
partially updated state from this,
tcf_mirred_init(...)
[...]
m->tcf_action = parm->action;
m->tcfm_eaction = parm->eaction;
[...]
and then in the execution of the action,
tcf_mirred(...)
[...]
retval = READ_ONCE(m->tcf_action);
[...]
if (m->tcfm_eaction != TCA_EGRESS_MIRROR)
[...]
So its at least possible I think these could be interleaved on multiple
cpus.
Sure, this was very clear when I wrote this code. Otherwise I would have
used an intermediate object and one rcu_dereference() instead of the
READ_ONCE().
Notice that some of the actions are fine though and don't have this
issue act_bpf for example is fine.
I think we can either fix it in the hash table create part of the
list as this series does or just let each action handle it on its own.
If we want a fix for stable kernels we want a tc_mirred fix on its own,
and I was planning to do so.
Given that a "tc qdisc replace ..." drops all packets sitting in the old
qdisc, I never thought someone would actually depend on atomically
switching tc_mirred parameters. I for sure did not care.
Thanks.
From: Eric Dumazet <hidden> Date: 2016-09-08 15:35:46
From: Eric Dumazet <redacted>
As reported by Cong Wang, I was lazy when I did initial RCU conversion
of tc_mirred, as I thought I could avoid allocation/freeing of a
parameter block.
Use an intermediate object so that fast path can get a consistent
snapshot of multiple variables (dev, action, eaction, ok_push)
Fixes: 2ee22a90c7af ("net_sched: act_mirred: remove spinlock in fast path")
Signed-off-by: Eric Dumazet <redacted>
Reported-by: Cong Wang <redacted>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Hadar Hen Zion <redacted>
Cc: Amir Vadai <redacted>
---
include/net/tc_act/tc_mirred.h | 12 +++++-
net/sched/act_mirred.c | 54 +++++++++++++++++++++----------
2 files changed, 47 insertions(+), 19 deletions(-)
@@ -36,15 +36,16 @@ static DEFINE_SPINLOCK(mirred_list_lock);staticvoidtcf_mirred_release(structtc_action*a,intbind){structtcf_mirred*m=to_mirred(a);-structnet_device*dev;+structtcf_mirred_params*params;/* We could be called either in a RCU callback or with RTNL lock held. */spin_lock_bh(&mirred_list_lock);list_del(&m->tcfm_list);-dev=rcu_dereference_protected(m->tcfm_dev,1);-if(dev)-dev_put(dev);+params=rcu_dereference_protected(m->params,1);+if(params->dev)+dev_put(params->dev);spin_unlock_bh(&mirred_list_lock);+kfree_rcu(params,rcu);}staticconststructnla_policymirred_policy[TCA_MIRRED_MAX+1]={
@@ -60,6 +61,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,{structtc_action_net*tn=net_generic(net,mirred_net_id);structnlattr*tb[TCA_MIRRED_MAX+1];+structtcf_mirred_params*params_new;+structtcf_mirred_params*params_old;structtc_mirred*parm;structtcf_mirred*m;structnet_device*dev;
@@ -124,21 +127,33 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,tcf_hash_release(*a,bind);if(!ovr)return-EEXIST;+ret=0;}m=to_mirred(*a);ASSERT_RTNL();-m->tcf_action=parm->action;-m->tcfm_eaction=parm->eaction;+params_new=kzalloc(sizeof(*params_new),GFP_KERNEL);+if(unlikely(!params_new)){+if(ret==ACT_P_CREATED)+tcf_hash_release(*a,bind);+return-ENOMEM;+}+params_old=rtnl_dereference(m->params);+params_new->action=m->tcf_action=parm->action;+params_new->eaction=m->tcfm_eaction=parm->eaction;if(dev!=NULL){m->tcfm_ifindex=parm->ifindex;-if(ret!=ACT_P_CREATED)-dev_put(rcu_dereference_protected(m->tcfm_dev,1));dev_hold(dev);-rcu_assign_pointer(m->tcfm_dev,dev);-m->tcfm_ok_push=ok_push;+params_new->dev=dev;+params_new->ok_push=ok_push;}+rcu_assign_pointer(m->params,params_new);+if(params_old){+if(params_old->dev)+dev_put(params_old->dev);+kfree_rcu(params_old,rcu);+}if(ret==ACT_P_CREATED){spin_lock_bh(&mirred_list_lock);list_add(&m->tcfm_list,&mirred_list);
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-08 15:47:52
On 16-09-08 08:35 AM, Eric Dumazet wrote:
From: Eric Dumazet <redacted>
As reported by Cong Wang, I was lazy when I did initial RCU conversion
of tc_mirred, as I thought I could avoid allocation/freeing of a
parameter block.
Use an intermediate object so that fast path can get a consistent
snapshot of multiple variables (dev, action, eaction, ok_push)
Fixes: 2ee22a90c7af ("net_sched: act_mirred: remove spinlock in fast path")
Signed-off-by: Eric Dumazet <redacted>
Reported-by: Cong Wang <redacted>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Cc: Hadar Hen Zion <redacted>
Cc: Amir Vadai <redacted>
---
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-08 15:49:50
[...]
quoted
So its at least possible I think these could be interleaved on multiple
cpus.
Sure, this was very clear when I wrote this code. Otherwise I would have
used an intermediate object and one rcu_dereference() instead of the
READ_ONCE().
quoted
Notice that some of the actions are fine though and don't have this
issue act_bpf for example is fine.
I think we can either fix it in the hash table create part of the
list as this series does or just let each action handle it on its own.
If we want a fix for stable kernels we want a tc_mirred fix on its own,
and I was planning to do so.
Given that a "tc qdisc replace ..." drops all packets sitting in the old
qdisc, I never thought someone would actually depend on atomically
switching tc_mirred parameters. I for sure did not care.
Thanks.
Agreed not sure why you would ever want to do a late binding and
replace on a tc_mirred actions. But it is supported...
From: Eric Dumazet <hidden> Date: 2016-09-08 15:51:42
On Thu, 2016-09-08 at 08:47 -0700, John Fastabend wrote:
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
Yes, it seems this hash table is used in control path, with RTNL held
anyway.
Thanks for reviewing John.
From: Cong Wang <hidden> Date: 2016-09-09 05:24:53
On Thu, Sep 8, 2016 at 8:35 AM, Eric Dumazet [off-list ref] wrote:
From: Eric Dumazet <redacted>
As reported by Cong Wang, I was lazy when I did initial RCU conversion
of tc_mirred, as I thought I could avoid allocation/freeing of a
parameter block.
Quote from Eric Dumazet:
https://www.mail-archive.com/netdev@vger.kernel.org/msg115482.html
<Quote>
Well, I added a READ_ONCE() to read tcf_action once.
Adding rcu here would mean adding a pointer and extra cache line, to
deref the values.
IMHO the race here has no effect . You either read the old or new value.
</Quote>
Me with facepalm... ;-)
From: Cong Wang <hidden> Date: 2016-09-09 05:27:07
On Thu, Sep 8, 2016 at 8:51 AM, Eric Dumazet [off-list ref] wrote:
On Thu, 2016-09-08 at 08:47 -0700, John Fastabend wrote:
quoted
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
Yes, it seems this hash table is used in control path, with RTNL held
anyway.
Seriously? You never read hashtable in fast path?? I think you need
to wake up.
On Thu, Sep 08, 2016 at 10:24:32PM -0700, Cong Wang wrote:
On Thu, Sep 8, 2016 at 8:35 AM, Eric Dumazet [off-list ref] wrote:
quoted
From: Eric Dumazet <redacted>
As reported by Cong Wang, I was lazy when I did initial RCU conversion
of tc_mirred, as I thought I could avoid allocation/freeing of a
parameter block.
Quote from Eric Dumazet:
https://www.mail-archive.com/netdev@vger.kernel.org/msg115482.html
<Quote>
Well, I added a READ_ONCE() to read tcf_action once.
Adding rcu here would mean adding a pointer and extra cache line, to
deref the values.
IMHO the race here has no effect . You either read the old or new value.
</Quote>
Me with facepalm... ;-)
imo the deliberate small race in Eric's initial lock removal in mirred
was a good design choice. I think he did this patch only to
silence the complains with the code instead of arguing with words.
imo the initial code is good as-is. This patch is also a nice improvement,
but certainly not mandatory. 'face palm' is unnecessary.
From: Cong Wang <hidden> Date: 2016-09-09 05:50:03
On Tue, Sep 6, 2016 at 7:52 AM, Eric Dumazet [off-list ref] wrote:
On Thu, 2016-09-01 at 22:57 -0700, Cong Wang wrote:
Missing changelog ?
I was too lazy to write a changelog for this RFC patch, surely
it will be added when removing RFC.
Here I have no idea what you want to fix, since John already took care
all this infra.
Adding extra rcu_dereference() and rcu_read_lock() while the critical
RCU dereferences already happen in callers is not needed.
Of course it is, TX and RX both have rcu read lock held.
But the caller already has rcu_read_lock() or rcu_read_lock_bh()
This was done in commit 25d8c0d55f241ce2 ("net: rcu-ify tcf_proto")
More precisely, it is __dev_queue_xmit() or netif_receive_skb_internal().
Not directly related to John.
The reason why I made it is to make it explicit that I take rcu_read_lock()
for tc action fast path, since it can be called recursively.
quoted
+ a = rcu_dereference(actions[i]);
Add in your .config :
CONFIG_SPARSE_RCU_POINTER=y
make C=2 M=net/sched
Yeah, kbuild-robot already reported this to me, no worries,
fixing it is already in my TODO list.
quoted
repeat: ret = a->ops->act(skb, a, res);+ rcu_read_unlock();+ if (ret == TC_ACT_REPEAT) goto repeat; /* we need a ttl - JHS */ if (ret != TC_ACT_PIPE)
I do not believe this patch is necessary.
Please add John as reviewer next time.
From: Cong Wang <hidden> Date: 2016-09-09 05:59:50
On Thu, Sep 8, 2016 at 10:48 PM, Alexei Starovoitov
[off-list ref] wrote:
imo the deliberate small race in Eric's initial lock removal in mirred
was a good design choice. I think he did this patch only to
silence the complains with the code instead of arguing with words.
imo the initial code is good as-is. This patch is also a nice improvement,
but certainly not mandatory. 'face palm' is unnecessary.
LOL, to summarize your words:
1) not changing the current code is good
2) changing the current code is good too
From: Eric Dumazet <hidden> Date: 2016-09-09 12:23:47
On Thu, 2016-09-08 at 22:26 -0700, Cong Wang wrote:
On Thu, Sep 8, 2016 at 8:51 AM, Eric Dumazet [off-list ref] wrote:
quoted
On Thu, 2016-09-08 at 08:47 -0700, John Fastabend wrote:
quoted
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
Yes, it seems this hash table is used in control path, with RTNL held
anyway.
Seriously? You never read hashtable in fast path?? I think you need
to wake up.
I seriously consider to ignore your mails.
Since you write patches with no changelog, expecting us to read your
mind, you definitely don't need us.
From: Eric Dumazet <hidden> Date: 2016-09-09 12:23:59
On Thu, 2016-09-08 at 22:24 -0700, Cong Wang wrote:
On Thu, Sep 8, 2016 at 8:35 AM, Eric Dumazet [off-list ref] wrote:
quoted
From: Eric Dumazet <redacted>
As reported by Cong Wang, I was lazy when I did initial RCU conversion
of tc_mirred, as I thought I could avoid allocation/freeing of a
parameter block.
Quote from Eric Dumazet:
https://www.mail-archive.com/netdev@vger.kernel.org/msg115482.html
<Quote>
Well, I added a READ_ONCE() to read tcf_action once.
Adding rcu here would mean adding a pointer and extra cache line, to
deref the values.
IMHO the race here has no effect . You either read the old or new value.
</Quote>
Me with facepalm... ;-)
Point is still valid. Show me a real case where it was a serious
problem, instead of simply theoretical.
tc_mirred + ifb patches allowed us to reach a milestone, removing the
last contended spinlocks, and you are catching up with this one year
later.
I wont backport this fix in Google prod kernels, because there is
absolutely no way we need it, and the extra memory cache line might hurt
latencies.
Since you did not write a fix on your side since June 17th, I presume
you do not care that much.
From: Eric Dumazet <hidden> Date: 2016-09-09 12:25:36
On Thu, 2016-09-08 at 22:59 -0700, Cong Wang wrote:
On Thu, Sep 8, 2016 at 10:48 PM, Alexei Starovoitov
[off-list ref] wrote:
quoted
imo the deliberate small race in Eric's initial lock removal in mirred
was a good design choice. I think he did this patch only to
silence the complains with the code instead of arguing with words.
imo the initial code is good as-is. This patch is also a nice improvement,
but certainly not mandatory. 'face palm' is unnecessary.
LOL, to summarize your words:
1) not changing the current code is good
2) changing the current code is good too
Only because I was tired of your rants.
I wont backport this patch to Google prod kernels, I already spent too
much time.
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-09 15:25:49
On 16-09-08 10:54 PM, Cong Wang wrote:
On Thu, Sep 8, 2016 at 8:49 AM, John Fastabend [off-list ref] wrote:
quoted
Agreed not sure why you would ever want to do a late binding and
replace on a tc_mirred actions. But it is supported...
I will let Jamal teach you on this, /me is really tired of explaining
things to you John.
This was a meta-comment on the use case for doing this with mirred
action. Not necessarily about the patch itself.
I was actually curious where this happens in practice. The only thing
I can think of is your external logging box moved so you need to send
out another port. Is there any open source software that manages 'tc'
like this. If so I would like to read it.
So do you know of any?
.John
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-09 15:53:01
On 16-09-08 10:26 PM, Cong Wang wrote:
On Thu, Sep 8, 2016 at 8:51 AM, Eric Dumazet [off-list ref] wrote:
quoted
On Thu, 2016-09-08 at 08:47 -0700, John Fastabend wrote:
quoted
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
Yes, it seems this hash table is used in control path, with RTNL held
anyway.
Seriously? You never read hashtable in fast path?? I think you need
to wake up.
But the actions use refcnt'ing and should never be decremented to zero
as long as they can still be referenced by an active filter. If each
action handles its parameters like mirred/gact then I don't see why its
necessary.
I believe though that the refcnt needs to be fixed a bit though most
likely by making it atomic. I original assumed it was protected by
RTNL lock but because its getting decremented from rcu callback this is
not true.
.John
From: Cong Wang <hidden> Date: 2016-09-12 05:46:24
On Fri, Sep 9, 2016 at 5:23 AM, Eric Dumazet [off-list ref] wrote:
On Thu, 2016-09-08 at 22:24 -0700, Cong Wang wrote:
quoted
On Thu, Sep 8, 2016 at 8:35 AM, Eric Dumazet [off-list ref] wrote:
quoted
From: Eric Dumazet <redacted>
As reported by Cong Wang, I was lazy when I did initial RCU conversion
of tc_mirred, as I thought I could avoid allocation/freeing of a
parameter block.
Quote from Eric Dumazet:
https://www.mail-archive.com/netdev@vger.kernel.org/msg115482.html
<Quote>
Well, I added a READ_ONCE() to read tcf_action once.
Adding rcu here would mean adding a pointer and extra cache line, to
deref the values.
IMHO the race here has no effect . You either read the old or new value.
</Quote>
Me with facepalm... ;-)
Point is still valid. Show me a real case where it was a serious
problem, instead of simply theoretical.
tc_mirred + ifb patches allowed us to reach a milestone, removing the
last contended spinlocks, and you are catching up with this one year
later.
I wont backport this fix in Google prod kernels, because there is
absolutely no way we need it, and the extra memory cache line might hurt
latencies.
Since you did not write a fix on your side since June 17th, I presume
you do not care that much.
Sounds like I were the author of this patch.... Why are you questioning
your own patch? Did I ask you to care about it? ;-)
Please drop this patch.
Thanks.
From: Cong Wang <hidden> Date: 2016-09-12 06:12:44
On Fri, Sep 9, 2016 at 8:52 AM, John Fastabend [off-list ref] wrote:
On 16-09-08 10:26 PM, Cong Wang wrote:
quoted
On Thu, Sep 8, 2016 at 8:51 AM, Eric Dumazet [off-list ref] wrote:
quoted
On Thu, 2016-09-08 at 08:47 -0700, John Fastabend wrote:
quoted
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
Yes, it seems this hash table is used in control path, with RTNL held
anyway.
Seriously? You never read hashtable in fast path?? I think you need
to wake up.
But the actions use refcnt'ing and should never be decremented to zero
as long as they can still be referenced by an active filter. If each
action handles its parameters like mirred/gact then I don't see why its
necessary.
This is correct, by "read" I meant "dereference", the tc actions
are now permanently stored in hashtable directly, so "reading"
a tc action is reading from hashtable.
Sorry if this wasn't clear.
From: John Fastabend <john.fastabend@gmail.com> Date: 2016-09-12 15:35:02
On 16-09-11 11:12 PM, Cong Wang wrote:
On Fri, Sep 9, 2016 at 8:52 AM, John Fastabend [off-list ref] wrote:
quoted
On 16-09-08 10:26 PM, Cong Wang wrote:
quoted
On Thu, Sep 8, 2016 at 8:51 AM, Eric Dumazet [off-list ref] wrote:
quoted
On Thu, 2016-09-08 at 08:47 -0700, John Fastabend wrote:
quoted
Works for me. FWIW I find this plenty straightforward and don't really
see the need to make the hash table itself rcu friendly.
Acked-by: John Fastabend <redacted>
Yes, it seems this hash table is used in control path, with RTNL held
anyway.
Seriously? You never read hashtable in fast path?? I think you need
to wake up.
But the actions use refcnt'ing and should never be decremented to zero
as long as they can still be referenced by an active filter. If each
action handles its parameters like mirred/gact then I don't see why its
necessary.
This is correct, by "read" I meant "dereference", the tc actions
are now permanently stored in hashtable directly, so "reading"
a tc action is reading from hashtable.
Sorry if this wasn't clear.
OK, but with the current code there is no need to protect the hash table
with an RCU semantics. The ref counting ensures the hash table entries
are always available and any 'replace' commands on actions are handled
internally in the action itself with rcu_assign_pointer replacing old
params with new params. The fast path readers will always read a
consistent set of parameters in this scheme.
So no need for an rcu hash table. The reference count though should
likely be atomic because not all increments/decrements are protected by
RTNL lock.
.John