From 8bf5df1d052a853579c0474dabc87af2d113fb53 Mon Sep 17 00:00:00 2001 From: Arne Kappen Date: Thu, 18 Aug 2016 11:35:29 +0200 Subject: [PATCH] device: add device handler list 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 Signed-off-by: Felix Fietkau [cleanup/fixes] --- bridge.c | 3 +++ config.c | 37 ++++++++++++++++--------------------- device.c | 43 +++++++++++++++++++++++++++++++++++++++++++ device.h | 6 ++++++ 4 files changed, 68 insertions(+), 21 deletions(-) diff --git a/bridge.c b/bridge.c index 0c538ba..bcece52 100644 --- a/bridge.c +++ b/bridge.c @@ -84,6 +84,9 @@ struct device_type bridge_device_type = { .name = "bridge", .config_params = &bridge_attr_list, + .bridge_capability = true, + .name_prefix = "br", + .create = bridge_create, .config_init = bridge_config_init, .reload = bridge_reload, diff --git a/config.c b/config.c index e7a0de7..0d965d3 100644 --- a/config.c +++ b/config.c @@ -53,18 +53,18 @@ config_section_idx(struct uci_section *s) } static int -config_parse_bridge_interface(struct uci_section *s) +config_parse_bridge_interface(struct uci_section *s, struct device_type *devtype) { 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); - 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); @@ -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; + struct device_type *devtype = NULL; 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 (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; @@ -169,18 +174,8 @@ config_init_devices(void) 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; diff --git a/device.c b/device.c index 07ec82f..8174ca0 100644 --- a/device.c +++ b/device.c @@ -24,10 +24,13 @@ #include #endif +#include + #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; @@ -63,6 +66,46 @@ const struct uci_blob_param_list device_attr_list = { 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++; diff --git a/device.h b/device.h index d28ec70..ef8d9a8 100644 --- a/device.h +++ b/device.h @@ -19,6 +19,7 @@ #include struct device; +struct device_type; struct device_user; struct device_hotplug_ops; struct interface; @@ -62,6 +63,9 @@ struct device_type { 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, @@ -227,6 +231,8 @@ extern struct device_type vlandev_device_type; 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); -- 2.30.2