X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=device.c;h=6fa697b45220f60652cbc5503ec3fe588f637a26;hp=34b49d4ed013dfc4557a9d682320b3e93c8f38f2;hb=c4c609517db5f7a33e4d26809dd67620ba77e795;hpb=d3a4844047c7b3c62511a9836a81703b5ee70fc0 diff --git a/device.c b/device.c index 34b49d4..6fa697b 100644 --- a/device.c +++ b/device.c @@ -3,26 +3,102 @@ #include #include -#include +#include +#include +#include #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); } }