From: Stephen Hemminger <shemminger@vyatta.com>
To: hadi@cyberus.ca
Cc: David Miller <davem@davemloft.net>, netdev@vger.kernel.org
Subject: Re: mirred, redirect action vs. dev refcount issue
Date: Thu, 22 Jul 2010 10:42:56 -0700 [thread overview]
Message-ID: <20100722104256.5a7e7cb6@nehalam> (raw)
In-Reply-To: <1279793481.2747.39.camel@bigi>
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);
}
next prev parent reply other threads:[~2010-07-22 17:42 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100722104256.5a7e7cb6@nehalam \
--to=shemminger@vyatta.com \
--cc=davem@davemloft.net \
--cc=hadi@cyberus.ca \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.