Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: David Miller
Date: Thursday, March 5, 2009 - 12:19 am

From: Patrick McHardy <kaber@trash.net>
Date: Thu, 05 Mar 2009 08:12:50 +0100


Here is the updated version just for the record:

vlan: Fix vlan-in-vlan crashes.

As analyzed by Patrick McHardy, vlan needs to reset it's
netdev_ops pointer in it's ->init() function but this
leaves the compat method pointers stale.

Add a netdev_resync_ops() and call it from the vlan code.

Any other driver which changes ->netdev_ops after register_netdevice()
will need to call this new function after doing so too.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/linux/netdevice.h |    1 +
 net/8021q/vlan_dev.c      |    1 +
 net/core/dev.c            |   56 +++++++++++++++++++++++++++-----------------
 3 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ec54785..6593667 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1079,6 +1079,7 @@ extern void		synchronize_net(void);
 extern int 		register_netdevice_notifier(struct notifier_block *nb);
 extern int		unregister_netdevice_notifier(struct notifier_block *nb);
 extern int		init_dummy_netdev(struct net_device *dev);
+extern void		netdev_resync_ops(struct net_device *dev);
 
 extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 extern struct net_device	*dev_get_by_index(struct net *net, int ifindex);
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 4a19acd..b6e1f9e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -639,6 +639,7 @@ static int vlan_dev_init(struct net_device *dev)
 		dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
 		dev->netdev_ops         = &vlan_netdev_ops;
 	}
+	netdev_resync_ops(dev);
 
 	if (is_vlan_dev(real_dev))
 		subclass = 1;
diff --git a/net/core/dev.c b/net/core/dev.c
index 2dd484e..f112970 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4282,6 +4282,39 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
+/* Some devices need to (re-)set their netdev_ops inside
+ * ->init() or similar.  If that happens, we have to setup
+ * the compat pointers again.
+ */
+void netdev_resync_ops(struct net_device *dev)
+{
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
+	const struct net_device_ops *ops = dev->netdev_ops;
+
+	dev->init = ops->ndo_init;
+	dev->uninit = ops->ndo_uninit;
+	dev->open = ops->ndo_open;
+	dev->change_rx_flags = ops->ndo_change_rx_flags;
+	dev->set_rx_mode = ops->ndo_set_rx_mode;
+	dev->set_multicast_list = ops->ndo_set_multicast_list;
+	dev->set_mac_address = ops->ndo_set_mac_address;
+	dev->validate_addr = ops->ndo_validate_addr;
+	dev->do_ioctl = ops->ndo_do_ioctl;
+	dev->set_config = ops->ndo_set_config;
+	dev->change_mtu = ops->ndo_change_mtu;
+	dev->neigh_setup = ops->ndo_neigh_setup;
+	dev->tx_timeout = ops->ndo_tx_timeout;
+	dev->get_stats = ops->ndo_get_stats;
+	dev->vlan_rx_register = ops->ndo_vlan_rx_register;
+	dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
+	dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = ops->ndo_poll_controller;
+#endif
+#endif
+}
+EXPORT_SYMBOL(netdev_resync_ops);
+
 /**
  *	register_netdevice	- register a network device
  *	@dev: device to register
@@ -4326,28 +4359,7 @@ int register_netdevice(struct net_device *dev)
 	 * This is temporary until all network devices are converted.
 	 */
 	if (dev->netdev_ops) {
-		const struct net_device_ops *ops = dev->netdev_ops;
-
-		dev->init = ops->ndo_init;
-		dev->uninit = ops->ndo_uninit;
-		dev->open = ops->ndo_open;
-		dev->change_rx_flags = ops->ndo_change_rx_flags;
-		dev->set_rx_mode = ops->ndo_set_rx_mode;
-		dev->set_multicast_list = ops->ndo_set_multicast_list;
-		dev->set_mac_address = ops->ndo_set_mac_address;
-		dev->validate_addr = ops->ndo_validate_addr;
-		dev->do_ioctl = ops->ndo_do_ioctl;
-		dev->set_config = ops->ndo_set_config;
-		dev->change_mtu = ops->ndo_change_mtu;
-		dev->neigh_setup = ops->ndo_neigh_setup;
-		dev->tx_timeout = ops->ndo_tx_timeout;
-		dev->get_stats = ops->ndo_get_stats;
-		dev->vlan_rx_register = ops->ndo_vlan_rx_register;
-		dev->vlan_rx_add_vid = ops->ndo_vlan_rx_add_vid;
-		dev->vlan_rx_kill_vid = ops->ndo_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-		dev->poll_controller = ops->ndo_poll_controller;
-#endif
+		netdev_resync_ops(dev);
 	} else {
 		char drivername[64];
 		pr_info("%s (%s): not using net_device_ops yet\n",
-- 
1.6.2

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[BUG] 2.6.29-rc* QinQ vlan trunking regression, Bart Trojanowski, (Sat Feb 28, 11:05 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Wed Mar 4, 12:43 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Wed Mar 4, 2:57 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Wed Mar 4, 3:59 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Wed Mar 4, 4:45 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Wed Mar 4, 8:53 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Bart Trojanowski, (Wed Mar 4, 9:54 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Bart Trojanowski, (Wed Mar 4, 9:59 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Wed Mar 4, 10:21 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Wed Mar 4, 10:51 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Wed Mar 4, 10:51 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Wed Mar 4, 11:57 pm)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 12:00 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 12:05 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 12:11 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 12:12 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 12:19 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 12:26 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 12:31 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 12:45 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Frank Blaschka, (Thu Mar 5, 1:05 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 1:27 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 1:56 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 1:59 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 2:08 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Patrick McHardy, (Thu Mar 5, 2:09 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 2:58 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, Maxime Bizon, (Thu Mar 5, 5:30 am)
Re: [BUG] 2.6.29-rc* QinQ vlan trunking regression, David Miller, (Thu Mar 5, 5:55 am)