+ __interface_set_down(iface, true);
+}
+
+void
+interface_add_user(struct interface_user *dep, struct interface *iface)
+{
+ if (!iface) {
+ list_add(&dep->list, &iface_all_users);
+ return;
+ }
+
+ dep->iface = iface;
+ list_add(&dep->list, &iface->users);
+ if (iface->state == IFS_UP)
+ dep->cb(dep, iface, IFEV_UP);
+}
+
+void
+interface_remove_user(struct interface_user *dep)
+{
+ list_del_init(&dep->list);
+ dep->iface = NULL;
+}
+
+static void
+interface_claim_device(struct interface *iface)
+{
+ struct device *dev;
+
+ if (iface->ifname &&
+ !(iface->proto_handler->flags & PROTO_FLAG_NODEV)) {
+ dev = device_get(iface->ifname, true);
+ if (dev)
+ interface_set_main_dev(iface, dev);
+ }
+ if (iface->proto_handler->flags & PROTO_FLAG_INIT_AVAILABLE)
+ interface_set_available(iface, true);
+}
+
+
+static void
+interface_cleanup(struct interface *iface, bool reload)
+{
+ struct interface_user *dep, *tmp;
+
+ list_for_each_entry_safe(dep, tmp, &iface->users, list)
+ interface_remove_user(dep);
+
+ interface_dequeue_event(iface);
+ interface_ip_flush(&iface->config_ip);
+ interface_flush_state(iface);
+ interface_clear_errors(iface);
+ if (iface->main_dev.dev &&
+ (!reload || !iface->main_dev.hotplug))
+ interface_set_main_dev(iface, NULL);
+ interface_set_proto_state(iface, NULL);
+}
+
+static void
+interface_do_free(struct interface *iface)
+{
+ interface_event(iface, IFEV_FREE);
+ interface_cleanup(iface, false);
+ free(iface->config);
+ netifd_ubus_remove_interface(iface);
+ avl_delete(&interfaces.avl, &iface->node.avl);
+ free(iface);
+}
+
+static void
+interface_do_reload(struct interface *iface)
+{
+ interface_event(iface, IFEV_RELOAD);
+ interface_cleanup(iface, true);
+ proto_init_interface(iface, iface->config);
+ interface_claim_device(iface);
+}
+
+static void
+interface_handle_config_change(struct interface *iface)
+{
+ switch(iface->config_state) {
+ case IFC_NORMAL:
+ break;
+ case IFC_RELOAD:
+ interface_do_reload(iface);
+ break;
+ case IFC_REMOVE:
+ interface_do_free(iface);
+ return;
+ }
+ if (iface->autostart && iface->available)
+ interface_set_up(iface);