summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2014-07-24 11:12:48 +0200
committerFelix Fietkau <nbd@openwrt.org>2014-07-24 11:12:50 +0200
commit5844d3caa26f5f8810476836a8b711107e4ba8d7 (patch)
tree2debeb439e416f30b04bb59773e181e811ecd398
parent81b14db5ca47ae44efc5ccb982f16597873ab4ba (diff)
downloadnetifd-5844d3caa26f5f8810476836a8b711107e4ba8d7.tar.gz
interface: fix restart after reload with external devices
When an interface goes down, the main_dev is reset to NULL. Track an externally added device separately to be able to bring it back up. Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-rw-r--r--interface.c16
-rw-r--r--interface.h1
2 files changed, 17 insertions, 0 deletions
diff --git a/interface.c b/interface.c
index 4c92f10..e66b58a 100644
--- a/interface.c
+++ b/interface.c
@@ -308,6 +308,13 @@ interface_set_link_state(struct interface *iface, bool new_state)
}
static void
+interface_ext_cb(struct device_user *dep, enum device_event ev)
+{
+ if (ev == DEV_EVENT_REMOVE)
+ device_remove_user(dep);
+}
+
+static void
interface_cb(struct device_user *dep, enum device_event ev)
{
struct interface *iface;
@@ -491,6 +498,8 @@ interface_claim_device(struct interface *iface)
} else if (iface->ifname &&
!(iface->proto_handler->flags & PROTO_FLAG_NODEV)) {
dev = device_get(iface->ifname, true);
+ } else {
+ dev = iface->ext_dev.dev;
}
if (dev)
@@ -518,6 +527,8 @@ interface_cleanup(struct interface *iface)
{
struct interface_user *dep, *tmp;
+ device_remove_user(&iface->ext_dev);
+
if (iface->parent_iface.iface)
interface_remove_user(&iface->parent_iface);
@@ -653,6 +664,7 @@ interface_alloc(const char *name, struct blob_attr *config)
iface->config_ip.enabled = false;
iface->main_dev.cb = interface_cb;
+ iface->ext_dev.cb = interface_ext_cb;
blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb,
blob_data(config), blob_len(config));
@@ -807,6 +819,9 @@ interface_remove_link(struct interface *iface, struct device *dev)
if (mdev && mdev->hotplug_ops)
return mdev->hotplug_ops->del(mdev, dev);
+ if (dev == iface->ext_dev.dev)
+ device_remove_user(&iface->ext_dev);
+
if (!iface->main_dev.hotplug)
return UBUS_STATUS_INVALID_ARGUMENT;
@@ -835,6 +850,7 @@ interface_add_link(struct interface *iface, struct device *dev)
return UBUS_STATUS_NOT_SUPPORTED;
}
+ device_add_user(&iface->ext_dev, dev);
interface_set_main_dev(iface, dev);
iface->main_dev.hotplug = true;
return 0;
diff --git a/interface.h b/interface.h
index 6cfe264..1cd7e96 100644
--- a/interface.h
+++ b/interface.h
@@ -119,6 +119,7 @@ struct interface {
/* main interface that the interface is bound to */
struct device_user main_dev;
+ struct device_user ext_dev;
/* interface that layer 3 communication will go through */
struct device_user l3_dev;