|
@@ -1635,6 +1635,15 @@ static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
|
|
|
return ip6_tnl_update(t, &p);
|
|
|
}
|
|
|
|
|
|
+static void ip6_tnl_dellink(struct net_device *dev, struct list_head *head)
|
|
|
+{
|
|
|
+ struct net *net = dev_net(dev);
|
|
|
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
|
|
|
+
|
|
|
+ if (dev != ip6n->fb_tnl_dev)
|
|
|
+ unregister_netdevice_queue(dev, head);
|
|
|
+}
|
|
|
+
|
|
|
static size_t ip6_tnl_get_size(const struct net_device *dev)
|
|
|
{
|
|
|
return
|
|
@@ -1699,6 +1708,7 @@ static struct rtnl_link_ops ip6_link_ops __read_mostly = {
|
|
|
.validate = ip6_tnl_validate,
|
|
|
.newlink = ip6_tnl_newlink,
|
|
|
.changelink = ip6_tnl_changelink,
|
|
|
+ .dellink = ip6_tnl_dellink,
|
|
|
.get_size = ip6_tnl_get_size,
|
|
|
.fill_info = ip6_tnl_fill_info,
|
|
|
};
|
|
@@ -1715,9 +1725,9 @@ static struct xfrm6_tunnel ip6ip6_handler __read_mostly = {
|
|
|
.priority = 1,
|
|
|
};
|
|
|
|
|
|
-static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
|
|
|
+static void __net_exit ip6_tnl_destroy_tunnels(struct net *net)
|
|
|
{
|
|
|
- struct net *net = dev_net(ip6n->fb_tnl_dev);
|
|
|
+ struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
|
|
|
struct net_device *dev, *aux;
|
|
|
int h;
|
|
|
struct ip6_tnl *t;
|
|
@@ -1785,10 +1795,8 @@ err_alloc_dev:
|
|
|
|
|
|
static void __net_exit ip6_tnl_exit_net(struct net *net)
|
|
|
{
|
|
|
- struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
|
|
|
-
|
|
|
rtnl_lock();
|
|
|
- ip6_tnl_destroy_tunnels(ip6n);
|
|
|
+ ip6_tnl_destroy_tunnels(net);
|
|
|
rtnl_unlock();
|
|
|
}
|
|
|
|