[PATCH v1 net-next 4/6] ip6_gre: Unlink ip6gre_tunnel_unlink() from ->dellink().
From: Kuniyuki Iwashima <kuniyu@google.com>
Date: 2026-09-16 23:04:03
Subsystem:
networking [general], networking [ipv4/ipv6], the rest · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds
With the previous patch, itn->fb_tunnel_dev can be removed via ->dellink(). However, ioctl(SIOCDELTUNNEL) still uses unregister_netdevice(), which requires ip6gre_tunnel_unlink() in ip6gre_tunnel_uninit(). Let's use __ip6gre_dellink() everywhere to remove ip6gre (and variant) devices and remove ip6gre_tunnel_unlink() and ip6gre_tunnel_unlink_md() in ip6gre_tunnel_uninit(). ip6erspan_tunnel_uninit() is also changed accordingly. Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> --- net/ipv6/ip6_gre.c | 50 +++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 16 deletions(-)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index d5d98474aeb5..a9059f3841ac 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c@@ -79,6 +79,7 @@ static void ip6gre_tunnel_setup(struct net_device *dev); static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); static void ip6erspan_tnl_link_config(struct ip6_tnl *t, int set_mtu); +static void __ip6gre_dellink(struct net_device *dev, struct list_head *head); /* Tunnel hash table */
@@ -359,10 +360,7 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, static void ip6erspan_tunnel_uninit(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); - ip6erspan_tunnel_unlink_md(ign, t); - ip6gre_tunnel_unlink(ign, t); dst_cache_reset(&t->dst_cache); netdev_put(dev, &t->dev_tracker); }
@@ -370,10 +368,7 @@ static void ip6erspan_tunnel_uninit(struct net_device *dev) static void ip6gre_tunnel_uninit(struct net_device *dev) { struct ip6_tnl *t = netdev_priv(dev); - struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id); - ip6gre_tunnel_unlink_md(ign, t); - ip6gre_tunnel_unlink(ign, t); dst_cache_reset(&t->dst_cache); netdev_put(dev, &t->dev_tracker); }
@@ -1251,14 +1246,15 @@ static int ip6gre_tunnel_siocdevprivate(struct net_device *dev, struct ifreq *ifr, void __user *data, int cmd) { - int err = 0; - struct ip6_tnl_parm2 p; - struct __ip6_tnl_parm p1; struct ip6_tnl *t = netdev_priv(dev); + struct __ip6_tnl_parm p1 = {}; + LIST_HEAD(dev_kill_list); struct net *net = t->net; - struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct ip6_tnl_parm2 p; + struct ip6gre_net *ign; + int err = 0; - memset(&p1, 0, sizeof(p1)); + ign = net_generic(net, ip6gre_net_id); switch (cmd) { case SIOCGETTUNNEL:
@@ -1347,7 +1343,8 @@ static int ip6gre_tunnel_siocdevprivate(struct net_device *dev, goto done; dev = t->dev; } - unregister_netdevice(dev); + + __ip6gre_dellink(dev, &dev_kill_list); err = 0; break;
@@ -1356,6 +1353,7 @@ static int ip6gre_tunnel_siocdevprivate(struct net_device *dev, } done: + unregister_netdevice_many(&dev_kill_list); return err; }
@@ -1563,7 +1561,7 @@ static void __net_exit ip6gre_exit_rtnl_net(struct net *net, struct ip6_tnl *t; hlist_for_each_entry_safe(t, tmp, head, hash_node) - unregister_netdevice_queue(t->dev, dev_kill_list); + __ip6gre_dellink(t->dev, dev_kill_list); } } }
@@ -2056,13 +2054,31 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], return 0; } +static void __ip6gre_dellink(struct net_device *dev, struct list_head *head) +{ + struct ip6_tnl *t = netdev_priv(dev); + struct ip6gre_net *ign; + + ign = net_generic(t->net, ip6gre_net_id); + + if (dev->rtnl_link_ops == &ip6erspan_tap_ops) + ip6erspan_tunnel_unlink_md(ign, t); + else + ip6gre_tunnel_unlink_md(ign, t); + + ip6gre_tunnel_unlink(ign, t); + unregister_netdevice_queue(dev, head); +} + static void ip6gre_dellink(struct net_device *dev, struct list_head *head) { - struct net *net = dev_net(dev); - struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct ip6_tnl *t = netdev_priv(dev); + struct ip6gre_net *ign; + + ign = net_generic(t->net, ip6gre_net_id); if (dev != ign->fb_tunnel_dev) - unregister_netdevice_queue(dev, head); + __ip6gre_dellink(dev, head); } static size_t ip6gre_get_size(const struct net_device *dev)
@@ -2304,6 +2320,7 @@ static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = { .validate = ip6gre_tap_validate, .newlink = ip6gre_newlink, .changelink = ip6gre_changelink, + .dellink = ip6gre_dellink, .get_size = ip6gre_get_size, .fill_info = ip6gre_fill_info, .get_link_net = ip6_tnl_get_link_net,
@@ -2318,6 +2335,7 @@ static struct rtnl_link_ops ip6erspan_tap_ops __read_mostly = { .validate = ip6erspan_tap_validate, .newlink = ip6erspan_newlink, .changelink = ip6erspan_changelink, + .dellink = ip6gre_dellink, .get_size = ip6gre_get_size, .fill_info = ip6gre_fill_info, .get_link_net = ip6_tnl_get_link_net,
--
2.55.0.1082.g2b9226bbc0-goog