X-Git-Url: http://git.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=bridge.c;h=c46d44e2c362ead282778187abab9d9e5df27e05;hp=f8478ad698a9f0609c4a08ff7be14063113594d9;hb=b4f89847883de95126ef332aa8df886c64b16b3d;hpb=8db8cbbb449ff1f2fd010846061cd2799aef3b43 diff --git a/bridge.c b/bridge.c index f8478ad..c46d44e 100644 --- a/bridge.c +++ b/bridge.c @@ -32,6 +32,12 @@ enum { BRIDGE_ATTR_HELLO_TIME, BRIDGE_ATTR_MAX_AGE, BRIDGE_ATTR_BRIDGE_EMPTY, + BRIDGE_ATTR_MULTICAST_QUERIER, + BRIDGE_ATTR_HASH_MAX, + BRIDGE_ATTR_ROBUSTNESS, + BRIDGE_ATTR_QUERY_INTERVAL, + BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL, + BRIDGE_ATTR_LAST_MEMBER_INTERVAL, __BRIDGE_ATTR_MAX }; @@ -45,6 +51,12 @@ static const struct blobmsg_policy bridge_attrs[__BRIDGE_ATTR_MAX] = { [BRIDGE_ATTR_MAX_AGE] = { "max_age", BLOBMSG_TYPE_INT32 }, [BRIDGE_ATTR_IGMP_SNOOP] = { "igmp_snooping", BLOBMSG_TYPE_BOOL }, [BRIDGE_ATTR_BRIDGE_EMPTY] = { "bridge_empty", BLOBMSG_TYPE_BOOL }, + [BRIDGE_ATTR_MULTICAST_QUERIER] = { "multicast_querier", BLOBMSG_TYPE_BOOL }, + [BRIDGE_ATTR_HASH_MAX] = { "hash_max", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_ROBUSTNESS] = { "robustness", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_QUERY_INTERVAL] = { "query_interval", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL] = { "query_response_interval", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_LAST_MEMBER_INTERVAL] = { "last_member_interval", BLOBMSG_TYPE_INT32 }, }; static const struct uci_blob_param_info bridge_attr_info[__BRIDGE_ATTR_MAX] = { @@ -60,17 +72,21 @@ static const struct uci_blob_param_list bridge_attr_list = { .next = { &device_attr_list }, }; -static struct device *bridge_create(const char *name, struct blob_attr *attr); +static struct device *bridge_create(const char *name, struct device_type *devtype, + struct blob_attr *attr); static void bridge_config_init(struct device *dev); static void bridge_free(struct device *dev); static void bridge_dump_info(struct device *dev, struct blob_buf *b); enum dev_change_type bridge_reload(struct device *dev, struct blob_attr *attr); -const struct device_type bridge_device_type = { - .name = "Bridge", +static 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, @@ -295,7 +311,7 @@ bridge_member_cb(struct device_user *dev, enum device_event ev) * bridge mtu is set */ system_if_apply_settings(&bst->dev, &bst->dev.settings, - DEV_OPT_MTU); + DEV_OPT_MTU | DEV_OPT_MTU6); } break; @@ -378,24 +394,25 @@ bridge_set_state(struct device *dev, bool up) } static struct bridge_member * -bridge_create_member(struct bridge_state *bst, struct device *dev, bool hotplug) +bridge_create_member(struct bridge_state *bst, const char *name, + struct device *dev, bool hotplug) { struct bridge_member *bm; - bm = calloc(1, sizeof(*bm) + strlen(dev->ifname) + 1); + bm = calloc(1, sizeof(*bm) + strlen(name) + 1); if (!bm) return NULL; bm->bst = bst; bm->dev.cb = bridge_member_cb; bm->dev.hotplug = hotplug; - strcpy(bm->name, dev->ifname); + strcpy(bm->name, name); bm->dev.dev = dev; vlist_add(&bst->members, &bm->node, bm->name); // Need to look up the bridge member again as the above // created pointer will be freed in case the bridge member // already existed - bm = vlist_find(&bst->members, dev->ifname, bm, node); + bm = vlist_find(&bst->members, name, bm, node); if (hotplug && bm) bm->node.version = -1; @@ -439,7 +456,7 @@ bridge_add_member(struct bridge_state *bst, const char *name) if (!dev) return; - bridge_create_member(bst, dev, false); + bridge_create_member(bst, name, dev, false); } static int @@ -447,7 +464,7 @@ bridge_hotplug_add(struct device *dev, struct device *member) { struct bridge_state *bst = container_of(dev, struct bridge_state, dev); - bridge_create_member(bst, member, true); + bridge_create_member(bst, member->ifname, member, true); return 0; } @@ -491,6 +508,7 @@ bridge_free(struct device *dev) bst = container_of(dev, struct bridge_state, dev); vlist_flush_all(&bst->members); + free(bst->config_data); free(bst); } @@ -506,8 +524,12 @@ bridge_dump_info(struct device *dev, struct blob_buf *b) system_if_dump_info(dev, b); list = blobmsg_open_array(b, "bridge-members"); - vlist_for_each_element(&bst->members, bm, node) + vlist_for_each_element(&bst->members, bm, node) { + if (bm->dev.dev->hidden) + continue; + blobmsg_add_string(b, NULL, bm->dev.dev->ifname); + } blobmsg_close_array(b, list); } @@ -546,7 +568,11 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb) /* defaults */ cfg->stp = false; cfg->forward_delay = 2; - cfg->igmp_snoop = true; + cfg->robustness = 2; + cfg->query_interval = 12500; + cfg->query_response_interval = 1000; + cfg->last_member_interval = 100; + cfg->hash_max = 512; cfg->bridge_empty = false; cfg->priority = 0x7FFF; @@ -560,7 +586,33 @@ bridge_apply_settings(struct bridge_state *bst, struct blob_attr **tb) cfg->priority = blobmsg_get_u32(cur); if ((cur = tb[BRIDGE_ATTR_IGMP_SNOOP])) - cfg->igmp_snoop = blobmsg_get_bool(cur); + cfg->multicast_querier = cfg->igmp_snoop = blobmsg_get_bool(cur); + + if ((cur = tb[BRIDGE_ATTR_MULTICAST_QUERIER])) + cfg->multicast_querier = blobmsg_get_bool(cur); + + if ((cur = tb[BRIDGE_ATTR_HASH_MAX])) + cfg->hash_max = blobmsg_get_u32(cur); + + if ((cur = tb[BRIDGE_ATTR_ROBUSTNESS])) { + cfg->robustness = blobmsg_get_u32(cur); + cfg->flags |= BRIDGE_OPT_ROBUSTNESS; + } + + if ((cur = tb[BRIDGE_ATTR_QUERY_INTERVAL])) { + cfg->query_interval = blobmsg_get_u32(cur); + cfg->flags |= BRIDGE_OPT_QUERY_INTERVAL; + } + + if ((cur = tb[BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL])) { + cfg->query_response_interval = blobmsg_get_u32(cur); + cfg->flags |= BRIDGE_OPT_QUERY_RESPONSE_INTERVAL; + } + + if ((cur = tb[BRIDGE_ATTR_LAST_MEMBER_INTERVAL])) { + cfg->last_member_interval = blobmsg_get_u32(cur); + cfg->flags |= BRIDGE_OPT_LAST_MEMBER_INTERVAL; + } if ((cur = tb[BRIDGE_ATTR_AGEING_TIME])) { cfg->ageing_time = blobmsg_get_u32(cur); @@ -594,12 +646,16 @@ bridge_reload(struct device *dev, struct blob_attr *attr) BUILD_BUG_ON(sizeof(diff) < __DEV_ATTR_MAX / 8); bst = container_of(dev, struct bridge_state, dev); + attr = blob_memdup(attr); blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev, blob_data(attr), blob_len(attr)); blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, tb_br, blob_data(attr), blob_len(attr)); + if (tb_dev[DEV_ATTR_MACADDR]) + bst->primary_port = NULL; + bst->ifnames = tb_br[BRIDGE_ATTR_IFNAME]; device_init_settings(dev, tb_dev); bridge_apply_settings(bst, tb_br); @@ -613,7 +669,7 @@ bridge_reload(struct device *dev, struct blob_attr *attr) diff = 0; uci_blob_diff(tb_dev, otb_dev, &device_attr_list, &diff); - if (diff & ~(1 << DEV_ATTR_IFNAME)) + if (diff) ret = DEV_CONFIG_RESTART; blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, otb_br, @@ -627,6 +683,7 @@ bridge_reload(struct device *dev, struct blob_attr *attr) bridge_config_init(dev); } + free(bst->config_data); bst->config_data = attr; return ret; } @@ -652,7 +709,8 @@ bridge_retry_members(struct uloop_timeout *timeout) } static struct device * -bridge_create(const char *name, struct blob_attr *attr) +bridge_create(const char *name, struct device_type *devtype, + struct blob_attr *attr) { struct bridge_state *bst; struct device *dev = NULL; @@ -662,7 +720,7 @@ bridge_create(const char *name, struct blob_attr *attr) return NULL; dev = &bst->dev; - device_init(dev, &bridge_device_type, name); + device_init(dev, devtype, name); dev->config_pending = true; bst->retry.cb = bridge_retry_members; @@ -677,3 +735,8 @@ bridge_create(const char *name, struct blob_attr *attr) return dev; } + +static void __init bridge_device_type_init(void) +{ + device_type_add(&bridge_device_type); +}