s/init_virtual_device/device_init_virtual/
[project/netifd.git] / device.c
index 34b49d4..6fa697b 100644 (file)
--- a/device.c
+++ b/device.c
 #include <stdio.h>
 #include <assert.h>
 
-#include <libubox/uapi.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
 
 #include "netifd.h"
 #include "system.h"
+#include "config.h"
 
 static struct avl_tree devices;
 
-static int avl_strcmp(const void *k1, const void *k2, void *ptr)
+enum {
+       DEV_ATTR_NAME,
+       DEV_ATTR_TYPE,
+       DEV_ATTR_MTU,
+       DEV_ATTR_MACADDR,
+       DEV_ATTR_TXQUEUELEN,
+       __DEV_ATTR_MAX,
+};
+
+static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
+       [DEV_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
+       [DEV_ATTR_TYPE] = { "type", BLOBMSG_TYPE_STRING },
+       [DEV_ATTR_MTU] = { "mtu", BLOBMSG_TYPE_INT32 },
+       [DEV_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING },
+       [DEV_ATTR_TXQUEUELEN] = { "txqueuelen", BLOBMSG_TYPE_INT32 },
+};
+
+const struct config_param_list device_attr_list = {
+       .n_params = __DEV_ATTR_MAX,
+       .params = dev_attrs,
+};
+
+static void
+device_init_settings(struct device *dev, struct blob_attr **tb)
 {
-       return strcmp(k1, k2);
+       struct blob_attr *cur;
+       struct ether_addr *ea;
+
+       dev->flags = 0;
+
+       if ((cur = tb[DEV_ATTR_MTU])) {
+               dev->mtu = blobmsg_get_u32(cur);
+               dev->flags |= DEV_OPT_MTU;
+       }
+
+       if ((cur = tb[DEV_ATTR_TXQUEUELEN])) {
+               dev->txqueuelen = blobmsg_get_u32(cur);
+               dev->flags |= DEV_OPT_TXQUEUELEN;
+       }
+
+       if ((cur = tb[DEV_ATTR_MACADDR])) {
+               ea = ether_aton(blob_data(cur));
+               if (ea) {
+                       memcpy(dev->macaddr, ea, sizeof(dev->macaddr));
+                       dev->flags |= DEV_OPT_MACADDR;
+               }
+       }
+}
+
+struct device *
+device_create(struct blob_attr *attr, struct uci_section *s)
+{
+       struct blob_attr *tb[__DEV_ATTR_MAX];
+       struct blob_attr *cur;
+       struct device *dev = NULL;
+       const char *name;
+
+       blobmsg_parse(dev_attrs, __DEV_ATTR_MAX, tb, blob_data(attr), blob_len(attr));
+       if (!tb[DEV_ATTR_NAME])
+               return NULL;
+
+       name = blobmsg_data(tb[DEV_ATTR_NAME]);
+       if ((cur = tb[DEV_ATTR_TYPE])) {
+               if (!strcmp(blobmsg_data(cur), "bridge"))
+                       dev = bridge_create(name, s);
+       } else {
+               dev = device_get(name, true);
+       }
+
+       if (!dev)
+               return NULL;
+
+       device_init_settings(dev, tb);
+
+       return dev;
 }
 
-static void API_CTOR dev_init(void)
+
+static void __init dev_init(void)
 {
        avl_init(&devices, avl_strcmp, false, NULL);
 }
 
 static void free_simple_device(struct device *dev)
 {
-       cleanup_device(dev);
+       device_cleanup(dev);
        free(dev);
 }
 
@@ -88,7 +164,7 @@ int check_device_state(struct device *dev)
        return dev->type->check_state(dev);
 }
 
-void init_virtual_device(struct device *dev, const struct device_type *type, const char *name)
+void device_init_virtual(struct device *dev, const struct device_type *type, const char *name)
 {
        assert(dev);
        assert(type);
@@ -101,11 +177,11 @@ void init_virtual_device(struct device *dev, const struct device_type *type, con
        dev->type = type;
 }
 
-int init_device(struct device *dev, const struct device_type *type, const char *ifname)
+int device_init(struct device *dev, const struct device_type *type, const char *ifname)
 {
        int ret;
 
-       init_virtual_device(dev, type, ifname);
+       device_init_virtual(dev, type, ifname);
 
        if (!dev->set_state)
                dev->set_state = set_device_state;
@@ -121,7 +197,7 @@ int init_device(struct device *dev, const struct device_type *type, const char *
        return 0;
 }
 
-struct device *get_device(const char *name, bool create)
+struct device *device_get(const char *name, bool create)
 {
        static const struct device_type simple_type = {
                .name = "Device",
@@ -142,12 +218,12 @@ struct device *get_device(const char *name, bool create)
                return NULL;
 
        dev = calloc(1, sizeof(*dev));
-       init_device(dev, &simple_type, name);
+       device_init(dev, &simple_type, name);
 
        return dev;
 }
 
-void cleanup_device(struct device *dev)
+void device_cleanup(struct device *dev)
 {
        struct device_user *dep, *tmp;
 
@@ -163,7 +239,7 @@ void cleanup_device(struct device *dev)
                avl_delete(&devices, &dev->avl);
 }
 
-void set_device_present(struct device *dev, bool state)
+void device_set_present(struct device *dev, bool state)
 {
        if (dev->present == state)
                return;
@@ -173,7 +249,7 @@ void set_device_present(struct device *dev, bool state)
        broadcast_device_event(dev, state ? DEV_EVENT_ADD : DEV_EVENT_REMOVE);
 }
 
-void add_device_user(struct device_user *dep, struct device *dev)
+void device_add_user(struct device_user *dep, struct device *dev)
 {
        dep->dev = dev;
        list_add(&dep->list, &dev->users);
@@ -184,7 +260,7 @@ void add_device_user(struct device_user *dep, struct device *dev)
        }
 }
 
-void remove_device_user(struct device_user *dep)
+void device_remove_user(struct device_user *dep)
 {
        struct device *dev = dep->dev;
 
@@ -192,14 +268,14 @@ void remove_device_user(struct device_user *dep)
 
        if (list_empty(&dev->users)) {
                /* all references have gone away, remove this device */
-               free_device(dev);
+               device_free(dev);
        }
 
        dep->dev = NULL;
 }
 
 void
-cleanup_devices(void)
+device_free_all(void)
 {
        struct device *dev, *tmp;
 
@@ -207,6 +283,6 @@ cleanup_devices(void)
                if (!list_empty(&dev->users))
                        continue;
 
-               free_device(dev);
+               device_free(dev);
        }
 }