* mirred, redirect action vs. dev refcount issue
@ 2010-07-21 23:24 Stephen Hemminger
2010-07-21 23:39 ` David Miller
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2010-07-21 23:24 UTC (permalink / raw)
To: jamal, David Miller; +Cc: netdev
Both the mirrored and redirect TC actions, hold a pointer to the
target device and increment the refcount. The problem is that administrator
may want to remove the target device (for example ifb0) and this will
cause the kernel to get in the "can't delete ifb0 with references" state.
Fixing this isn't trivial but I think that the best way would be to have
the action API have a device notifier and walk the actions and call a new
hook (device_event) similar to existing walk. The device_event in the
action ops can then redirect any mirror/redirect that are going to a dead
device off to bit bucket.
Alternatively, the mirror/redirect could just use ifindex which is
a soft reference, so if device is removed, they just drop.
Lazy me favors the later.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-21 23:24 mirred, redirect action vs. dev refcount issue Stephen Hemminger
@ 2010-07-21 23:39 ` David Miller
2010-07-21 23:52 ` Stephen Hemminger
0 siblings, 1 reply; 10+ messages in thread
From: David Miller @ 2010-07-21 23:39 UTC (permalink / raw)
To: shemminger; +Cc: hadi, netdev
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Wed, 21 Jul 2010 16:24:26 -0700
> Alternatively, the mirror/redirect could just use ifindex which is
> a soft reference, so if device is removed, they just drop.
>
> Lazy me favors the later.
If it is the action rule holding onto the device, it should have
an appropriate netdevice notifier handler.
If it's a transient reference on receive, it should be transient
and released eventually.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-21 23:39 ` David Miller
@ 2010-07-21 23:52 ` Stephen Hemminger
2010-07-21 23:58 ` David Miller
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2010-07-21 23:52 UTC (permalink / raw)
To: David Miller; +Cc: hadi, netdev
On Wed, 21 Jul 2010 16:39:55 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:
> From: Stephen Hemminger <shemminger@vyatta.com>
> Date: Wed, 21 Jul 2010 16:24:26 -0700
>
> > Alternatively, the mirror/redirect could just use ifindex which is
> > a soft reference, so if device is removed, they just drop.
> >
> > Lazy me favors the later.
>
> If it is the action rule holding onto the device, it should have
> an appropriate netdevice notifier handler.
There is no notifier there, and the module doesn't keep track of
list of filters. So that is why it has to be done at act api level.
> If it's a transient reference on receive, it should be transient
> and released eventually.
Kernel doesn't keep transient reference on receive any more.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-21 23:52 ` Stephen Hemminger
@ 2010-07-21 23:58 ` David Miller
2010-07-22 0:00 ` Stephen Hemminger
0 siblings, 1 reply; 10+ messages in thread
From: David Miller @ 2010-07-21 23:58 UTC (permalink / raw)
To: shemminger; +Cc: hadi, netdev
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Wed, 21 Jul 2010 16:52:47 -0700
> On Wed, 21 Jul 2010 16:39:55 -0700 (PDT)
> David Miller <davem@davemloft.net> wrote:
>
>> If it is the action rule holding onto the device, it should have
>> an appropriate netdevice notifier handler.
>
> There is no notifier there, and the module doesn't keep track of
> list of filters. So that is why it has to be done at act api level.
Any rule, or route, or whatever that makes references to devices must
transparently accomodate the requested removal or downing of a device.
There is no way around this.
So either the action code needs to keep track of it's table entries on
some global list that can be traversed at notifier time, or we go with
the ifindex thing.
Whether the ifindex or the global list + delete scheme is better is a
topic for discussion. Since from the user's perspective it is unclear
which semantic is less surprising, entries disappearing or suddenly
stop working (or start applying to a different device which has taken
a previous one's ifindex!).
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-21 23:58 ` David Miller
@ 2010-07-22 0:00 ` Stephen Hemminger
2010-07-22 10:11 ` jamal
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2010-07-22 0:00 UTC (permalink / raw)
To: David Miller; +Cc: hadi, netdev
On Wed, 21 Jul 2010 16:58:02 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:
> From: Stephen Hemminger <shemminger@vyatta.com>
> Date: Wed, 21 Jul 2010 16:52:47 -0700
>
> > On Wed, 21 Jul 2010 16:39:55 -0700 (PDT)
> > David Miller <davem@davemloft.net> wrote:
> >
> >> If it is the action rule holding onto the device, it should have
> >> an appropriate netdevice notifier handler.
> >
> > There is no notifier there, and the module doesn't keep track of
> > list of filters. So that is why it has to be done at act api level.
>
> Any rule, or route, or whatever that makes references to devices must
> transparently accomodate the requested removal or downing of a device.
>
> There is no way around this.
>
> So either the action code needs to keep track of it's table entries on
> some global list that can be traversed at notifier time, or we go with
> the ifindex thing.
>
> Whether the ifindex or the global list + delete scheme is better is a
> topic for discussion. Since from the user's perspective it is unclear
> which semantic is less surprising, entries disappearing or suddenly
> stop working (or start applying to a different device which has taken
> a previous one's ifindex!).
ifindex is unique (until integer wraps) so that soft reference
works.
--
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-22 0:00 ` Stephen Hemminger
@ 2010-07-22 10:11 ` jamal
2010-07-22 17:42 ` Stephen Hemminger
0 siblings, 1 reply; 10+ messages in thread
From: jamal @ 2010-07-22 10:11 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
On Wed, 2010-07-21 at 17:00 -0700, Stephen Hemminger wrote:
> On Wed, 21 Jul 2010 16:58:02 -0700 (PDT)
> David Miller <davem@davemloft.net> wrote:
>
> > Whether the ifindex or the global list + delete scheme is better is a
> > topic for discussion. Since from the user's perspective it is unclear
> > which semantic is less surprising, entries disappearing or suddenly
> > stop working (or start applying to a different device which has taken
> > a previous one's ifindex!).
>
> ifindex is unique (until integer wraps) so that soft reference
> works.
The proper way to do it is via a notifier since we point to the
netdev - and yes it is a little more complex thats why i just
let the admin suffer (IMO) the well deserved consequences[1].
I am in travel mode - but i will do some background thinking and
come up with a good way to resolve it when i get back. Unless you
have a patch you want me to look at.
cheers,
jamal
[1] least element of suprise principle:
Admin adds a rule which says
"you see a packet matching blah incoming on eth0,
do action1 then action2 ... then actionN"
Say action2 is "mirror to ifb0".
And then this same admin goes and rmmods ifb0 - it is easier to
just reject this rmmod operation as we do todau. Maybe we could be
kinder and be more informative and syslog something along the lines of
"rejected to unregister device you rat-bastard because you have a rule
which says we should mirror to ifb0".
Thoughts?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-22 10:11 ` jamal
@ 2010-07-22 17:42 ` Stephen Hemminger
2010-07-22 18:02 ` jamal
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2010-07-22 17:42 UTC (permalink / raw)
To: hadi; +Cc: David Miller, netdev
This is what I am testing now.
--- a/include/net/tc_act/tc_mirred.h 2010-07-22 09:17:41.631561924 -0700
+++ b/include/net/tc_act/tc_mirred.h 2010-07-22 09:49:53.355325645 -0700
@@ -9,6 +9,7 @@ struct tcf_mirred {
int tcfm_ifindex;
int tcfm_ok_push;
struct net_device *tcfm_dev;
+ struct list_head tcfm_list;
};
#define to_mirred(pc) \
container_of(pc, struct tcf_mirred, common)
--- a/net/sched/act_mirred.c 2010-07-21 16:10:48.922308036 -0700
+++ b/net/sched/act_mirred.c 2010-07-22 09:52:32.229910928 -0700
@@ -1,3 +1,4 @@
+
/*
* net/sched/mirred.c packet mirroring and redirect actions
*
@@ -21,6 +22,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gfp.h>
+#include <linux/notifier.h>
#include <net/net_namespace.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
@@ -33,6 +35,7 @@
static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
static u32 mirred_idx_gen;
static DEFINE_RWLOCK(mirred_lock);
+static LIST_HEAD(mirred_list);
static struct tcf_hashinfo mirred_hash_info = {
.htab = tcf_mirred_ht,
@@ -47,7 +50,10 @@ static inline int tcf_mirred_release(str
m->tcf_bindcnt--;
m->tcf_refcnt--;
if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
- dev_put(m->tcfm_dev);
+ ASSERT_RTNL();
+ list_del(&m->tcfm_list);
+ if (m->tcfm_dev)
+ dev_put(m->tcfm_dev);
tcf_hash_destroy(&m->common, &mirred_hash_info);
return 1;
}
@@ -134,8 +140,11 @@ static int tcf_mirred_init(struct nlattr
m->tcfm_ok_push = ok_push;
}
spin_unlock_bh(&m->tcf_lock);
- if (ret == ACT_P_CREATED)
+ if (ret == ACT_P_CREATED) {
+ ASSERT_RTNL();
+ list_add(&m->tcfm_list, &mirred_list);
tcf_hash_insert(pc, &mirred_hash_info);
+ }
return ret;
}
@@ -164,9 +173,14 @@ static int tcf_mirred(struct sk_buff *sk
m->tcf_bstats.packets++;
dev = m->tcfm_dev;
+ if (!dev) {
+ printk_once(KERN_NOTICE "tc mirred: target device is gone\n");
+ goto out;
+ }
+
if (!(dev->flags & IFF_UP)) {
if (net_ratelimit())
- pr_notice("tc mirred to Houston: device %s is gone!\n",
+ pr_notice("tc mirred to Houston: device %s is down\n",
dev->name);
goto out;
}
@@ -230,6 +244,28 @@ nla_put_failure:
return -1;
}
+static int mirred_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct tcf_mirred *m;
+
+ if (event == NETDEV_UNREGISTER)
+ list_for_each_entry(m, &mirred_list, tcfm_list) {
+ if (m->tcfm_dev == dev) {
+ dev_put(dev);
+ m->tcfm_dev = NULL;
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mirred_device_notifier = {
+ .notifier_call = mirred_device_event,
+};
+
+
static struct tc_action_ops act_mirred_ops = {
.kind = "mirred",
.hinfo = &mirred_hash_info,
@@ -250,12 +286,17 @@ MODULE_LICENSE("GPL");
static int __init mirred_init_module(void)
{
+ int err = register_netdevice_notifier(&mirred_device_notifier);
+ if (err)
+ return err;
+
pr_info("Mirror/redirect action on\n");
return tcf_register_action(&act_mirred_ops);
}
static void __exit mirred_cleanup_module(void)
{
+ unregister_netdevice_notifier(&mirred_device_notifier);
tcf_unregister_action(&act_mirred_ops);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: mirred, redirect action vs. dev refcount issue
2010-07-22 17:42 ` Stephen Hemminger
@ 2010-07-22 18:02 ` jamal
2010-07-23 4:45 ` [PATCH] net sched: fix race in mirred device removal Stephen Hemminger
0 siblings, 1 reply; 10+ messages in thread
From: jamal @ 2010-07-22 18:02 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
On Thu, 2010-07-22 at 10:42 -0700, Stephen Hemminger wrote:
> This is what I am testing now.
>
Looks very reasonable to me. Please add my signoff when you
submit.
cheers,
jamal
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH] net sched: fix race in mirred device removal
2010-07-22 18:02 ` jamal
@ 2010-07-23 4:45 ` Stephen Hemminger
2010-07-25 4:04 ` David Miller
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Hemminger @ 2010-07-23 4:45 UTC (permalink / raw)
To: hadi, David Miller; +Cc: netdev
This fixes hang when target device of mirred packet classifier
action is removed.
If a mirror or redirection action is configured to cause packets
to go to another device, the classifier holds a ref count, but was assuming
the adminstrator cleaned up all redirections before removing. The fix
is to add a notifier and cleanup during unregister.
The new list is implicitly protected by RTNL mutex because
it is held during filter add/delete as well as notifier.
Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
---
Patch is against 2.6.35-rc6 (not net-next)
--- a/include/net/tc_act/tc_mirred.h 2010-07-22 21:32:40.944000510 -0700
+++ b/include/net/tc_act/tc_mirred.h 2010-07-22 21:32:44.280173100 -0700
@@ -9,6 +9,7 @@ struct tcf_mirred {
int tcfm_ifindex;
int tcfm_ok_push;
struct net_device *tcfm_dev;
+ struct list_head tcfm_list;
};
#define to_mirred(pc) \
container_of(pc, struct tcf_mirred, common)
--- a/net/sched/act_mirred.c 2010-07-22 21:32:40.927999682 -0700
+++ b/net/sched/act_mirred.c 2010-07-22 21:42:22.356826443 -0700
@@ -33,6 +33,7 @@
static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
static u32 mirred_idx_gen;
static DEFINE_RWLOCK(mirred_lock);
+static LIST_HEAD(mirred_list);
static struct tcf_hashinfo mirred_hash_info = {
.htab = tcf_mirred_ht,
@@ -47,7 +48,9 @@ static inline int tcf_mirred_release(str
m->tcf_bindcnt--;
m->tcf_refcnt--;
if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
- dev_put(m->tcfm_dev);
+ list_del(&m->tcfm_list);
+ if (m->tcfm_dev)
+ dev_put(m->tcfm_dev);
tcf_hash_destroy(&m->common, &mirred_hash_info);
return 1;
}
@@ -134,8 +137,10 @@ static int tcf_mirred_init(struct nlattr
m->tcfm_ok_push = ok_push;
}
spin_unlock_bh(&m->tcf_lock);
- if (ret == ACT_P_CREATED)
+ if (ret == ACT_P_CREATED) {
+ list_add(&m->tcfm_list, &mirred_list);
tcf_hash_insert(pc, &mirred_hash_info);
+ }
return ret;
}
@@ -162,9 +167,14 @@ static int tcf_mirred(struct sk_buff *sk
m->tcf_tm.lastuse = jiffies;
dev = m->tcfm_dev;
+ if (!dev) {
+ printk_once(KERN_NOTICE "tc mirred: target device is gone\n");
+ goto out;
+ }
+
if (!(dev->flags & IFF_UP)) {
if (net_ratelimit())
- pr_notice("tc mirred to Houston: device %s is gone!\n",
+ pr_notice("tc mirred to Houston: device %s is down\n",
dev->name);
goto out;
}
@@ -232,6 +242,28 @@ nla_put_failure:
return -1;
}
+static int mirred_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = ptr;
+ struct tcf_mirred *m;
+
+ if (event == NETDEV_UNREGISTER)
+ list_for_each_entry(m, &mirred_list, tcfm_list) {
+ if (m->tcfm_dev == dev) {
+ dev_put(dev);
+ m->tcfm_dev = NULL;
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block mirred_device_notifier = {
+ .notifier_call = mirred_device_event,
+};
+
+
static struct tc_action_ops act_mirred_ops = {
.kind = "mirred",
.hinfo = &mirred_hash_info,
@@ -252,12 +284,17 @@ MODULE_LICENSE("GPL");
static int __init mirred_init_module(void)
{
+ int err = register_netdevice_notifier(&mirred_device_notifier);
+ if (err)
+ return err;
+
pr_info("Mirror/redirect action on\n");
return tcf_register_action(&act_mirred_ops);
}
static void __exit mirred_cleanup_module(void)
{
+ unregister_netdevice_notifier(&mirred_device_notifier);
tcf_unregister_action(&act_mirred_ops);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] net sched: fix race in mirred device removal
2010-07-23 4:45 ` [PATCH] net sched: fix race in mirred device removal Stephen Hemminger
@ 2010-07-25 4:04 ` David Miller
0 siblings, 0 replies; 10+ messages in thread
From: David Miller @ 2010-07-25 4:04 UTC (permalink / raw)
To: shemminger; +Cc: hadi, netdev
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Thu, 22 Jul 2010 21:45:04 -0700
> This fixes hang when target device of mirred packet classifier
> action is removed.
>
> If a mirror or redirection action is configured to cause packets
> to go to another device, the classifier holds a ref count, but was assuming
> the adminstrator cleaned up all redirections before removing. The fix
> is to add a notifier and cleanup during unregister.
>
> The new list is implicitly protected by RTNL mutex because
> it is held during filter add/delete as well as notifier.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
> Acked-by: Jamal Hadi Salim <hadi@cyberus.ca>
Applied to net-2.6, thanks.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2010-07-25 4:04 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-21 23:24 mirred, redirect action vs. dev refcount issue Stephen Hemminger
2010-07-21 23:39 ` David Miller
2010-07-21 23:52 ` Stephen Hemminger
2010-07-21 23:58 ` David Miller
2010-07-22 0:00 ` Stephen Hemminger
2010-07-22 10:11 ` jamal
2010-07-22 17:42 ` Stephen Hemminger
2010-07-22 18:02 ` jamal
2010-07-23 4:45 ` [PATCH] net sched: fix race in mirred device removal Stephen Hemminger
2010-07-25 4:04 ` David Miller
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).