X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=device.c;h=dd2823d2f9cc9ecd7f7a0aef3067f52f43cba2df;hp=b29d73b122704206b95325228b84900b12bda562;hb=3653d721dad44c5a63790a3fd67e819dfb1dc428;hpb=b965453c9df60f1c2681c3bfb7e8cff671c4b223 diff --git a/device.c b/device.c index b29d73b..dd2823d 100644 --- a/device.c +++ b/device.c @@ -29,16 +29,23 @@ #include "config.h" static struct avl_tree devices; +static bool default_ps = true; static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING }, - [DEV_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_ARRAY }, [DEV_ATTR_MTU] = { .name = "mtu", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING }, [DEV_ATTR_TXQUEUELEN] = { .name = "txqueuelen", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_IPV6] = { .name = "ipv6", .type = BLOBMSG_TYPE_BOOL }, [DEV_ATTR_PROMISC] = { .name = "promisc", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_RPFILTER] = { .name = "rpfilter", .type = BLOBMSG_TYPE_STRING }, + [DEV_ATTR_ACCEPTLOCAL] = { .name = "acceptlocal", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_IGMPVERSION] = { .name = "igmpversion", .type = BLOBMSG_TYPE_INT32 }, + [DEV_ATTR_MLDVERSION] = { .name = "mldversion", .type = BLOBMSG_TYPE_INT32 }, + [DEV_ATTR_NEIGHREACHABLETIME] = { .name = "neighreachabletime", .type = BLOBMSG_TYPE_INT32 }, + [DEV_ATTR_RPS] = { .name = "rps", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_XPS] = { .name = "xps", .type = BLOBMSG_TYPE_BOOL }, }; const struct uci_blob_param_list device_attr_list = { @@ -62,6 +69,14 @@ void device_unlock(void) static int set_device_state(struct device *dev, bool state) { + if (state) { + /* Set ifindex for all devices being enabled so a valid */ + /* ifindex is in place avoiding possible race conditions */ + device_set_ifindex(dev, system_if_resolve(dev)); + if (!dev->ifindex) + return -1; + } + if (dev->external) return 0; @@ -146,6 +161,14 @@ device_merge_settings(struct device *dev, struct device_settings *n) sizeof(n->macaddr)); n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6; n->promisc = s->flags & DEV_OPT_PROMISC ? s->promisc : os->promisc; + n->rpfilter = s->flags & DEV_OPT_RPFILTER ? s->rpfilter : os->rpfilter; + n->acceptlocal = s->flags & DEV_OPT_ACCEPTLOCAL ? s->acceptlocal : os->acceptlocal; + n->igmpversion = s->flags & DEV_OPT_IGMPVERSION ? s->igmpversion : os->igmpversion; + n->mldversion = s->flags & DEV_OPT_MLDVERSION ? s->mldversion : os->mldversion; + n->neigh4reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ? + s->neigh4reachabletime : os->neigh4reachabletime; + n->neigh6reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ? + s->neigh6reachabletime : os->neigh6reachabletime; n->flags = s->flags | os->flags; } @@ -189,6 +212,53 @@ device_init_settings(struct device *dev, struct blob_attr **tb) s->flags |= DEV_OPT_PROMISC; } + if ((cur = tb[DEV_ATTR_RPFILTER])) { + if (system_resolve_rpfilter(blobmsg_data(cur), &s->rpfilter)) + s->flags |= DEV_OPT_RPFILTER; + else + DPRINTF("Failed to resolve rpfilter: %s\n", (char *) blobmsg_data(cur)); + } + + if ((cur = tb[DEV_ATTR_ACCEPTLOCAL])) { + s->acceptlocal = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_ACCEPTLOCAL; + } + + if ((cur = tb[DEV_ATTR_IGMPVERSION])) { + s->igmpversion = blobmsg_get_u32(cur); + if (s->igmpversion >= 1 && s->igmpversion <= 3) + s->flags |= DEV_OPT_IGMPVERSION; + else + DPRINTF("Failed to resolve igmpversion: %d\n", blobmsg_get_u32(cur)); + } + + if ((cur = tb[DEV_ATTR_MLDVERSION])) { + s->mldversion = blobmsg_get_u32(cur); + if (s->mldversion >= 1 && s->mldversion <= 2) + s->flags |= DEV_OPT_MLDVERSION; + else + DPRINTF("Failed to resolve mldversion: %d\n", blobmsg_get_u32(cur)); + } + + if ((cur = tb[DEV_ATTR_NEIGHREACHABLETIME])) { + s->neigh6reachabletime = s->neigh4reachabletime = blobmsg_get_u32(cur); + s->flags |= DEV_OPT_NEIGHREACHABLETIME; + } + + if ((cur = tb[DEV_ATTR_RPS])) { + s->rps = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_RPS; + } + else + s->rps = default_ps; + + if ((cur = tb[DEV_ATTR_XPS])) { + s->xps = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_XPS; + } + else + s->xps = default_ps; + device_set_disabled(dev, disabled); } @@ -305,6 +375,8 @@ int device_init(struct device *dev, const struct device_type *type, const char * system_if_clear_state(dev); device_check_state(dev); + dev->settings.rps = default_ps; + dev->settings.xps = default_ps; return 0; } @@ -543,10 +615,17 @@ device_init_pending(void) } static enum dev_change_type -device_reload_config(struct device *dev, struct blob_attr *attr) +device_set_config(struct device *dev, const struct device_type *type, + struct blob_attr *attr) { struct blob_attr *tb[__DEV_ATTR_MAX]; - const struct uci_blob_param_list *cfg = dev->type->config_params; + const struct uci_blob_param_list *cfg = type->config_params; + + if (type != dev->type) + return DEV_CONFIG_RECREATE; + + if (dev->type->reload) + return dev->type->reload(dev, attr); if (uci_blob_check_equal(dev->config, attr, cfg)) return DEV_CONFIG_NO_CHANGE; @@ -565,16 +644,41 @@ device_reload_config(struct device *dev, struct blob_attr *attr) } enum dev_change_type -device_set_config(struct device *dev, const struct device_type *type, - struct blob_attr *attr) +device_apply_config(struct device *dev, const struct device_type *type, + struct blob_attr *config) { - if (type != dev->type) - return DEV_CONFIG_RECREATE; + enum dev_change_type change; - if (dev->type->reload) - return dev->type->reload(dev, attr); + change = device_set_config(dev, type, config); + if (dev->external) { + system_if_apply_settings(dev, &dev->settings, dev->settings.flags); + change = DEV_CONFIG_APPLIED; + } - return device_reload_config(dev, attr); + switch (change) { + case DEV_CONFIG_RESTART: + case DEV_CONFIG_APPLIED: + D(DEVICE, "Device '%s': config applied\n", dev->ifname); + config = blob_memdup(config); + free(dev->config); + dev->config = config; + if (change == DEV_CONFIG_RESTART && dev->present) { + device_set_present(dev, false); + if (dev->active && !dev->external) { + dev->set_state(dev, false); + dev->set_state(dev, true); + } + device_set_present(dev, true); + } + break; + case DEV_CONFIG_NO_CHANGE: + D(DEVICE, "Device '%s': no configuration change\n", dev->ifname); + break; + case DEV_CONFIG_RECREATE: + break; + } + + return change; } static void @@ -624,6 +728,41 @@ device_reset_old(void) } } +void +device_set_default_ps(bool state) +{ + struct device *dev; + + if (state == default_ps) + return; + + default_ps = state; + + avl_for_each_element(&devices, dev, avl) { + struct device_settings *s = &dev->settings; + unsigned int apply_mask = 0; + + if (!(s->flags & DEV_OPT_RPS)) { + s->rps = default_ps; + apply_mask |= DEV_OPT_RPS; + } + + if (!(s->flags & DEV_OPT_XPS)) { + s->xps = default_ps; + apply_mask |= DEV_OPT_XPS; + } + + if (!apply_mask) + continue; + + if (!(dev->external || (dev->present && dev->active)) || + dev->config_pending) + continue; + + system_if_apply_settings(dev, s, apply_mask); + } +} + struct device * device_create(const char *name, const struct device_type *type, struct blob_attr *config) @@ -631,41 +770,25 @@ device_create(const char *name, const struct device_type *type, struct device *odev = NULL, *dev; enum dev_change_type change; - config = blob_memdup(config); - if (!config) - return NULL; - odev = device_get(name, false); if (odev) { odev->current_config = true; - change = device_set_config(odev, type, config); - if (odev->external) { - system_if_apply_settings(odev, &odev->settings, odev->settings.flags); - change = DEV_CONFIG_APPLIED; - } + change = device_apply_config(odev, type, config); switch (change) { - case DEV_CONFIG_RESTART: - case DEV_CONFIG_APPLIED: - D(DEVICE, "Device '%s': config applied\n", odev->ifname); - free(odev->config); - odev->config = config; - if (change == DEV_CONFIG_RESTART && odev->present) { - device_set_present(odev, false); - device_set_present(odev, true); - } - return odev; - case DEV_CONFIG_NO_CHANGE: - D(DEVICE, "Device '%s': no configuration change\n", odev->ifname); - free(config); - return odev; case DEV_CONFIG_RECREATE: D(DEVICE, "Device '%s': recreate device\n", odev->ifname); device_delete(odev); break; + default: + return odev; } } else D(DEVICE, "Create new device '%s' (%s)\n", name, type->name); + config = blob_memdup(config); + if (!config) + return NULL; + dev = type->create(name, config); if (!dev) return NULL; @@ -675,8 +798,10 @@ device_create(const char *name, const struct device_type *type, if (odev) device_replace(dev, odev); - if (!config_init && dev->config_pending) + if (!config_init && dev->config_pending) { type->config_init(dev); + dev->config_pending = false; + } return dev; } @@ -726,6 +851,18 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_u8(b, "ipv6", st.ipv6); if (st.flags & DEV_OPT_PROMISC) blobmsg_add_u8(b, "promisc", st.promisc); + if (st.flags & DEV_OPT_RPFILTER) + blobmsg_add_u32(b, "rpfilter", st.rpfilter); + if (st.flags & DEV_OPT_ACCEPTLOCAL) + blobmsg_add_u8(b, "acceptlocal", st.acceptlocal); + if (st.flags & DEV_OPT_IGMPVERSION) + blobmsg_add_u32(b, "igmpversion", st.igmpversion); + if (st.flags & DEV_OPT_MLDVERSION) + blobmsg_add_u32(b, "mldversion", st.mldversion); + if (st.flags & DEV_OPT_NEIGHREACHABLETIME) { + blobmsg_add_u32(b, "neigh4reachabletime", st.neigh4reachabletime); + blobmsg_add_u32(b, "neigh6reachabletime", st.neigh6reachabletime); + } } s = blobmsg_open_table(b, "statistics");