|
@@ -244,18 +244,6 @@ static int veth_open(struct net_device *dev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int veth_close(struct net_device *dev)
|
|
|
-{
|
|
|
- struct veth_priv *priv;
|
|
|
-
|
|
|
- if (netif_carrier_ok(dev)) {
|
|
|
- priv = netdev_priv(dev);
|
|
|
- netif_carrier_off(dev);
|
|
|
- netif_carrier_off(priv->peer);
|
|
|
- }
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
static int veth_dev_init(struct net_device *dev)
|
|
|
{
|
|
|
struct veth_net_stats *stats;
|
|
@@ -286,13 +274,50 @@ static void veth_setup(struct net_device *dev)
|
|
|
dev->hard_start_xmit = veth_xmit;
|
|
|
dev->get_stats = veth_get_stats;
|
|
|
dev->open = veth_open;
|
|
|
- dev->stop = veth_close;
|
|
|
dev->ethtool_ops = &veth_ethtool_ops;
|
|
|
dev->features |= NETIF_F_LLTX;
|
|
|
dev->init = veth_dev_init;
|
|
|
dev->destructor = veth_dev_free;
|
|
|
}
|
|
|
|
|
|
+static void veth_change_state(struct net_device *dev)
|
|
|
+{
|
|
|
+ struct net_device *peer;
|
|
|
+ struct veth_priv *priv;
|
|
|
+
|
|
|
+ priv = netdev_priv(dev);
|
|
|
+ peer = priv->peer;
|
|
|
+
|
|
|
+ if (netif_carrier_ok(peer)) {
|
|
|
+ if (!netif_carrier_ok(dev))
|
|
|
+ netif_carrier_on(dev);
|
|
|
+ } else {
|
|
|
+ if (netif_carrier_ok(dev))
|
|
|
+ netif_carrier_off(dev);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int veth_device_event(struct notifier_block *unused,
|
|
|
+ unsigned long event, void *ptr)
|
|
|
+{
|
|
|
+ struct net_device *dev = ptr;
|
|
|
+
|
|
|
+ if (dev->open != veth_open)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ switch (event) {
|
|
|
+ case NETDEV_CHANGE:
|
|
|
+ veth_change_state(dev);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+out:
|
|
|
+ return NOTIFY_DONE;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block veth_notifier_block __read_mostly = {
|
|
|
+ .notifier_call = veth_device_event,
|
|
|
+};
|
|
|
+
|
|
|
/*
|
|
|
* netlink interface
|
|
|
*/
|
|
@@ -454,12 +479,14 @@ static struct rtnl_link_ops veth_link_ops = {
|
|
|
|
|
|
static __init int veth_init(void)
|
|
|
{
|
|
|
+ register_netdevice_notifier(&veth_notifier_block);
|
|
|
return rtnl_link_register(&veth_link_ops);
|
|
|
}
|
|
|
|
|
|
static __exit void veth_exit(void)
|
|
|
{
|
|
|
rtnl_link_unregister(&veth_link_ops);
|
|
|
+ unregister_netdevice_notifier(&veth_notifier_block);
|
|
|
}
|
|
|
|
|
|
module_init(veth_init);
|