X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=device.c;h=8f0e823373e75e27eeb53f656a122f393fa0d34a;hp=b2db29168dfd439166748e1de271e54547b6a827;hb=f5f78c1eca1fe2df04dae56a4d9f024533066b29;hpb=10741b4974b85c825036eb0717ddc7112f96f5fb diff --git a/device.c b/device.c index b2db291..8f0e823 100644 --- a/device.c +++ b/device.c @@ -34,6 +34,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_MTU] = { "mtu", BLOBMSG_TYPE_INT32 }, [DEV_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING }, [DEV_ATTR_TXQUEUELEN] = { "txqueuelen", BLOBMSG_TYPE_INT32 }, + [DEV_ATTR_ENABLED] = { "enabled", BLOBMSG_TYPE_BOOL }, }; const struct config_param_list device_attr_list = { @@ -68,12 +69,17 @@ static int set_device_state(struct device *dev, bool state) static int simple_device_set_state(struct device *dev, bool state) { + struct device *pdev; int ret = 0; - if (state && !dev->parent.dev) - dev->parent.dev = system_if_get_parent(dev); + pdev = dev->parent.dev; + if (state && !pdev) { + pdev = system_if_get_parent(dev); + if (pdev) + device_add_user(&dev->parent, pdev); + } - if (dev->parent.dev) { + if (pdev) { if (state) ret = device_claim(&dev->parent); else @@ -169,31 +175,53 @@ static const struct device_type alias_device_type = { .free = alias_device_free, }; +static void +device_merge_settings(struct device *dev, struct device_settings *n) +{ + struct device_settings *os = &dev->orig_settings; + struct device_settings *s = &dev->settings; + + memset(n, 0, sizeof(*n)); + n->mtu = s->flags & DEV_OPT_MTU ? s->mtu : os->mtu; + n->txqueuelen = s->flags & DEV_OPT_TXQUEUELEN ? + s->txqueuelen : os->txqueuelen; + memcpy(n->macaddr, + (s->flags & DEV_OPT_MACADDR ? s->macaddr : os->macaddr), + sizeof(n->macaddr)); + n->flags = s->flags | os->flags; +} + void device_init_settings(struct device *dev, struct blob_attr **tb) { + struct device_settings *s = &dev->settings; struct blob_attr *cur; struct ether_addr *ea; + bool disabled = false; - dev->flags = 0; + s->flags = 0; + if ((cur = tb[DEV_ATTR_ENABLED])) + disabled = !blobmsg_get_bool(cur); if ((cur = tb[DEV_ATTR_MTU])) { - dev->mtu = blobmsg_get_u32(cur); - dev->flags |= DEV_OPT_MTU; + s->mtu = blobmsg_get_u32(cur); + s->flags |= DEV_OPT_MTU; } if ((cur = tb[DEV_ATTR_TXQUEUELEN])) { - dev->txqueuelen = blobmsg_get_u32(cur); - dev->flags |= DEV_OPT_TXQUEUELEN; + s->txqueuelen = blobmsg_get_u32(cur); + s->flags |= DEV_OPT_TXQUEUELEN; } if ((cur = tb[DEV_ATTR_MACADDR])) { - ea = ether_aton(blob_data(cur)); + ea = ether_aton(blobmsg_data(cur)); if (ea) { - memcpy(dev->macaddr, ea, sizeof(dev->macaddr)); - dev->flags |= DEV_OPT_MACADDR; + memcpy(s->macaddr, ea, 6); + s->flags |= DEV_OPT_MACADDR; } } + + device_set_disabled(dev, disabled); } static void __init dev_init(void) @@ -404,18 +432,42 @@ void device_cleanup(struct device *dev) device_delete(dev); } -void device_set_present(struct device *dev, bool state) +static void __device_set_present(struct device *dev, bool state) { if (dev->present == state) return; - D(DEVICE, "%s '%s' %s present\n", dev->type->name, dev->ifname, state ? "is now" : "is no longer" ); dev->present = state; device_broadcast_event(dev, state ? DEV_EVENT_ADD : DEV_EVENT_REMOVE); } +void device_set_present(struct device *dev, bool state) +{ + if (dev->sys_present == state) + return; + + dev->sys_present = state; + D(DEVICE, "%s '%s' %s present\n", dev->type->name, dev->ifname, state ? "is now" : "is no longer" ); + + if (state && dev->disabled) + return; + + __device_set_present(dev, state); +} + +void +device_set_disabled(struct device *dev, bool value) +{ + dev->disabled = value; + if (dev->sys_present) + __device_set_present(dev, !value); +} + void device_add_user(struct device_user *dep, struct device *dev) { + if (dep->dev) + device_remove_user(dep); + dep->dev = dev; list_add_tail(&dep->list, &dev->users); if (dep->cb && dev->present) { @@ -425,6 +477,14 @@ void device_add_user(struct device_user *dep, struct device *dev) } } +void +device_free(struct device *dev) +{ + __devlock++; + dev->type->free(dev); + __devlock--; +} + static void __device_free_unused(struct device *dev) { @@ -612,6 +672,7 @@ device_create(const char *name, const struct device_type *type, void device_dump_status(struct blob_buf *b, struct device *dev) { + struct device_settings st; void *c, *s; if (!dev) { @@ -633,6 +694,18 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u8(b, "up", !!dev->active); if (dev->type->dump_info) dev->type->dump_info(dev, b); + else + system_if_dump_info(dev, b); + + if (dev->active) { + device_merge_settings(dev, &st); + if (st.flags & DEV_OPT_MTU) + blobmsg_add_u32(b, "mtu", st.mtu); + if (st.flags & DEV_OPT_MACADDR) + blobmsg_add_string(b, "macaddr", ether_ntoa((struct ether_addr *) st.macaddr)); + if (st.flags & DEV_OPT_TXQUEUELEN) + blobmsg_add_u32(b, "txqueuelen", st.txqueuelen); + } s = blobmsg_open_table(b, "statistics"); if (dev->type->dump_stats)