|
@@ -1138,6 +1138,33 @@ static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = {
|
|
|
.priority = 100,
|
|
|
};
|
|
|
|
|
|
+static bool is_vti6_tunnel(const struct net_device *dev)
|
|
|
+{
|
|
|
+ return dev->netdev_ops == &vti6_netdev_ops;
|
|
|
+}
|
|
|
+
|
|
|
+static int vti6_device_event(struct notifier_block *unused,
|
|
|
+ unsigned long event, void *ptr)
|
|
|
+{
|
|
|
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
|
|
+ struct ip6_tnl *t = netdev_priv(dev);
|
|
|
+
|
|
|
+ if (!is_vti6_tunnel(dev))
|
|
|
+ return NOTIFY_DONE;
|
|
|
+
|
|
|
+ switch (event) {
|
|
|
+ case NETDEV_DOWN:
|
|
|
+ if (!net_eq(t->net, dev_net(dev)))
|
|
|
+ xfrm_garbage_collect(t->net);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return NOTIFY_DONE;
|
|
|
+}
|
|
|
+
|
|
|
+static struct notifier_block vti6_notifier_block __read_mostly = {
|
|
|
+ .notifier_call = vti6_device_event,
|
|
|
+};
|
|
|
+
|
|
|
/**
|
|
|
* vti6_tunnel_init - register protocol and reserve needed resources
|
|
|
*
|
|
@@ -1148,6 +1175,8 @@ static int __init vti6_tunnel_init(void)
|
|
|
const char *msg;
|
|
|
int err;
|
|
|
|
|
|
+ register_netdevice_notifier(&vti6_notifier_block);
|
|
|
+
|
|
|
msg = "tunnel device";
|
|
|
err = register_pernet_device(&vti6_net_ops);
|
|
|
if (err < 0)
|
|
@@ -1180,6 +1209,7 @@ xfrm_proto_ah_failed:
|
|
|
xfrm_proto_esp_failed:
|
|
|
unregister_pernet_device(&vti6_net_ops);
|
|
|
pernet_dev_failed:
|
|
|
+ unregister_netdevice_notifier(&vti6_notifier_block);
|
|
|
pr_err("vti6 init: failed to register %s\n", msg);
|
|
|
return err;
|
|
|
}
|
|
@@ -1194,6 +1224,7 @@ static void __exit vti6_tunnel_cleanup(void)
|
|
|
xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
|
|
|
xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
|
|
|
unregister_pernet_device(&vti6_net_ops);
|
|
|
+ unregister_netdevice_notifier(&vti6_notifier_block);
|
|
|
}
|
|
|
|
|
|
module_init(vti6_tunnel_init);
|