netifd: Interface last error support
[project/netifd.git] / interface.c
index 72599e6..8239eac 100644 (file)
@@ -80,7 +80,7 @@ const struct uci_blob_param_list interface_attr_list = {
 };
 
 static void
-interface_clear_errors(struct interface *iface)
+interface_error_flush(struct interface *iface)
 {
        struct interface_error *error, *tmp;
 
@@ -90,6 +90,17 @@ interface_clear_errors(struct interface *iface)
        }
 }
 
+static void
+interface_clear_errors(struct interface *iface)
+{
+        /* don't flush the errors in case the configured protocol handler matches the
+           running protocol handler and is having the last error capability */
+       if (!(iface->proto &&
+              (iface->proto->handler->flags & PROTO_FLAG_LASTERROR) &&
+              (iface->proto->handler->name == iface->proto_handler->name)))
+               interface_error_flush(iface);
+}
+
 void interface_add_error(struct interface *iface, const char *subsystem,
                         const char *code, const char **data, int n_data)
 {
@@ -98,6 +109,14 @@ void interface_add_error(struct interface *iface, const char *subsystem,
        int *datalen = NULL;
        char *dest, *d_subsys, *d_code;
 
+        /* if the configured protocol handler has the last error support capability,
+           errors should only be added if the running protocol handler matches the
+           configured one */
+       if (iface->proto &&
+            (iface->proto->handler->flags & PROTO_FLAG_LASTERROR) &&
+            (iface->proto->handler->name != iface->proto_handler->name))
+               return;
+
        if (n_data) {
                len = n_data * sizeof(char *);
                datalen = alloca(len);
@@ -113,6 +132,11 @@ void interface_add_error(struct interface *iface, const char *subsystem,
        if (!error)
                return;
 
+       /* Only keep the last flagged error, prevent this list grows unlimitted in case the
+          protocol can't be established (e.g auth failure) */
+       if (iface->proto_handler->flags & PROTO_FLAG_LASTERROR)
+               interface_error_flush(iface);
+
        list_add_tail(&error->list, &iface->errors);
 
        dest = (char *) &error->data[n_data + 1];
@@ -188,6 +212,7 @@ interface_event(struct interface *iface, enum interface_event ev)
 
        switch (ev) {
        case IFEV_UP:
+               interface_error_flush(iface);
                adev = iface->l3_dev.dev;
                /* fall through */
        case IFEV_DOWN:
@@ -918,11 +943,11 @@ interface_handle_link(struct interface *iface, const char *name, bool add, bool
        }
 
        if (add) {
-               device_set_present(dev, true);
                if (iface->device_config && dev->default_config)
-                       device_set_config(dev, dev->type, iface->config);
+                       device_apply_config(dev, dev->type, iface->config);
+
+               device_set_present(dev, true);
 
-               system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
                ret = interface_add_link(iface, dev, link_ext);
        } else {
                ret = interface_remove_link(iface, dev);