device: add device handler list
authorArne Kappen <akappen@inet.tu-berlin.de>
Thu, 18 Aug 2016 09:35:29 +0000 (11:35 +0200)
committerFelix Fietkau <nbd@nbd.name>
Fri, 26 Aug 2016 08:38:50 +0000 (10:38 +0200)
Device handlers now also declare if they have bridge capabilities and include
a string to prefix device names for their types.

Signed-off-by: Arne Kappen <akappen@inet.tu-berlin.de>
Signed-off-by: Felix Fietkau <nbd@nbd.name> [cleanup/fixes]
bridge.c
config.c
device.c
device.h

index 0c538ba..bcece52 100644 (file)
--- a/bridge.c
+++ b/bridge.c
@@ -84,6 +84,9 @@ struct device_type bridge_device_type = {
        .name = "bridge",
        .config_params = &bridge_attr_list,
 
        .name = "bridge",
        .config_params = &bridge_attr_list,
 
+       .bridge_capability = true,
+       .name_prefix = "br",
+
        .create = bridge_create,
        .config_init = bridge_config_init,
        .reload = bridge_reload,
        .create = bridge_create,
        .config_init = bridge_config_init,
        .reload = bridge_reload,
index e7a0de7..0d965d3 100644 (file)
--- a/config.c
+++ b/config.c
@@ -53,18 +53,18 @@ config_section_idx(struct uci_section *s)
 }
 
 static int
 }
 
 static int
-config_parse_bridge_interface(struct uci_section *s)
+config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype)
 {
        char *name;
 
 {
        char *name;
 
-       name = alloca(strlen(s->e.name) + 4);
-       sprintf(name, "br-%s", s->e.name);
+       name = alloca(strlen(s->e.name) + strlen(devtype->name_prefix) + 2);
+       sprintf(name, "%s-%s", devtype->name_prefix, s->e.name);
        blobmsg_add_string(&b, "name", name);
 
        blobmsg_add_string(&b, "name", name);
 
-       uci_to_blob(&b, s, bridge_device_type.config_params);
-       if (!device_create(name, &bridge_device_type, b.head)) {
-               D(INTERFACE, "Failed to create bridge for interface '%s'\n", s->e.name);
-               return -EINVAL;
+       uci_to_blob(&b, s, devtype->config_params);
+       if (!device_create(name, devtype, b.head)) {
+               D(INTERFACE, "Failed to create '%s' device for interface '%s'\n",
+                       devtype->name, s->e.name);
        }
 
        blob_buf_init(&b, 0);
        }
 
        blob_buf_init(&b, 0);
@@ -79,6 +79,7 @@ config_parse_interface(struct uci_section *s, bool alias)
        const char *type = NULL, *disabled;
        struct blob_attr *config;
        bool bridge = false;
        const char *type = NULL, *disabled;
        struct blob_attr *config;
        bool bridge = false;
+       struct device_type *devtype = NULL;
 
        disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
        if (disabled && !strcmp(disabled, "1"))
 
        disabled = uci_lookup_option_string(uci_ctx, s, "disabled");
        if (disabled && !strcmp(disabled, "1"))
@@ -88,8 +89,12 @@ config_parse_interface(struct uci_section *s, bool alias)
 
        if (!alias)
                type = uci_lookup_option_string(uci_ctx, s, "type");
 
        if (!alias)
                type = uci_lookup_option_string(uci_ctx, s, "type");
-       if (type && !strcmp(type, "bridge")) {
-               if (config_parse_bridge_interface(s))
+
+       if (type)
+               devtype = device_type_get(type);
+
+       if (devtype && devtype->bridge_capability) {
+               if (config_parse_bridge_interface(s, devtype))
                        return;
 
                bridge = true;
                        return;
 
                bridge = true;
@@ -169,18 +174,8 @@ config_init_devices(void)
                        continue;
 
                type = uci_lookup_option_string(uci_ctx, s, "type");
                        continue;
 
                type = uci_lookup_option_string(uci_ctx, s, "type");
-               if (type) {
-                       if (!strcmp(type, "8021ad"))
-                               devtype = &vlandev_device_type;
-                       else if (!strcmp(type, "8021q"))
-                               devtype = &vlandev_device_type;
-                       else if (!strcmp(type, "bridge"))
-                               devtype = &bridge_device_type;
-                       else if (!strcmp(type, "macvlan"))
-                               devtype = &macvlan_device_type;
-                       else if (!strcmp(type, "tunnel"))
-                               devtype = &tunnel_device_type;
-               }
+               if (type)
+                       devtype = device_type_get(type);
 
                if (devtype)
                        params = devtype->config_params;
 
                if (devtype)
                        params = devtype->config_params;
index 07ec82f..8174ca0 100644 (file)
--- a/device.c
+++ b/device.c
 #include <netinet/ether.h>
 #endif
 
 #include <netinet/ether.h>
 #endif
 
+#include <libubox/list.h>
+
 #include "netifd.h"
 #include "system.h"
 #include "config.h"
 
 #include "netifd.h"
 #include "system.h"
 #include "config.h"
 
+static struct list_head devtypes = LIST_HEAD_INIT(devtypes);
 static struct avl_tree devices;
 static bool default_ps = true;
 
 static struct avl_tree devices;
 static bool default_ps = true;
 
@@ -63,6 +66,46 @@ const struct uci_blob_param_list device_attr_list = {
 
 static int __devlock = 0;
 
 
 static int __devlock = 0;
 
+int device_type_add(struct device_type *devtype)
+{
+       if (device_type_get(devtype->name)) {
+               netifd_log_message(L_WARNING, "Device handler '%s' already exists\n",
+                                  devtype->name);
+               return 1;
+       }
+
+       netifd_log_message(L_NOTICE, "Added device handler type: %s\n",
+               devtype->name);
+
+       list_add(&devtype->list, &devtypes);
+       return 0;
+}
+
+/* initialize device type list and add known types */
+static void __init devtypes_init(void)
+{
+       device_type_add(&simple_device_type);
+       device_type_add(&bridge_device_type);
+       device_type_add(&tunnel_device_type);
+       device_type_add(&macvlan_device_type);
+       device_type_add(&vlandev_device_type);
+}
+
+/* Retrieve the device type for the given name. If 'bridge' is true, the type
+ * must have bridge capabilities
+ */
+struct device_type *
+device_type_get(const char *tname)
+{
+       struct device_type *cur;
+
+       list_for_each_entry(cur, &devtypes, list)
+               if (!strcmp(cur->name, tname))
+                       return cur;
+
+       return NULL;
+}
+
 void device_lock(void)
 {
        __devlock++;
 void device_lock(void)
 {
        __devlock++;
index d28ec70..ef8d9a8 100644 (file)
--- a/device.h
+++ b/device.h
@@ -19,6 +19,7 @@
 #include <netinet/in.h>
 
 struct device;
 #include <netinet/in.h>
 
 struct device;
+struct device_type;
 struct device_user;
 struct device_hotplug_ops;
 struct interface;
 struct device_user;
 struct device_hotplug_ops;
 struct interface;
@@ -62,6 +63,9 @@ struct device_type {
        struct list_head list;
        const char *name;
 
        struct list_head list;
        const char *name;
 
+       bool bridge_capability;
+       const char *name_prefix;
+
        const struct uci_blob_param_list *config_params;
 
        struct device *(*create)(const char *name, struct device_type *devtype,
        const struct uci_blob_param_list *config_params;
 
        struct device *(*create)(const char *name, struct device_type *devtype,
@@ -227,6 +231,8 @@ extern struct device_type vlandev_device_type;
 void device_lock(void);
 void device_unlock(void);
 
 void device_lock(void);
 void device_unlock(void);
 
+int device_type_add(struct device_type *devtype);
+struct device_type *device_type_get(const char *tname);
 struct device *device_create(const char *name, struct device_type *type,
                             struct blob_attr *config);
 void device_init_settings(struct device *dev, struct blob_attr **tb);
 struct device *device_create(const char *name, struct device_type *type,
                             struct blob_attr *config);
 void device_init_settings(struct device *dev, struct blob_attr **tb);