hsr: remove hsr interface if all slaves are removed
authorTaehee Yoo <ap420073@gmail.com>
Thu, 30 Apr 2020 17:37:02 +0000 (17:37 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 30 Apr 2020 20:25:18 +0000 (13:25 -0700)
When all hsr slave interfaces are removed, hsr interface doesn't work.
At that moment, it's fine to remove an unused hsr interface automatically
for saving resources.
That's a common behavior of virtual interfaces.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/hsr/hsr_main.c

index 26d6c39..e2564de 100644 (file)
 #include "hsr_framereg.h"
 #include "hsr_slave.h"
 
+static bool hsr_slave_empty(struct hsr_priv *hsr)
+{
+       struct hsr_port *port;
+
+       hsr_for_each_port(hsr, port)
+               if (port->type != HSR_PT_MASTER)
+                       return false;
+       return true;
+}
+
 static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
                             void *ptr)
 {
-       struct net_device *dev;
        struct hsr_port *port, *master;
+       struct net_device *dev;
        struct hsr_priv *hsr;
+       LIST_HEAD(list_kill);
        int mtu_max;
        int res;
 
@@ -85,8 +96,15 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
                master->dev->mtu = mtu_max;
                break;
        case NETDEV_UNREGISTER:
-               if (!is_hsr_master(dev))
+               if (!is_hsr_master(dev)) {
+                       master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER);
                        hsr_del_port(port);
+                       if (hsr_slave_empty(master->hsr)) {
+                               unregister_netdevice_queue(master->dev,
+                                                          &list_kill);
+                               unregister_netdevice_many(&list_kill);
+                       }
+               }
                break;
        case NETDEV_PRE_TYPE_CHANGE:
                /* HSR works only on Ethernet devices. Refuse slave to change