bool active;
bool force_active;
- struct list_head members;
+ struct vlist_tree members;
int n_present;
};
struct bridge_member {
- struct list_head list;
+ struct vlist_node node;
struct bridge_state *bst;
struct device_user dev;
bool present;
+ char name[];
};
-static void bridge_free_member(struct bridge_member *bm);
-
static int
bridge_disable_member(struct bridge_member *bm)
{
goto error;
ret = system_bridge_addif(&bst->dev, bm->dev.dev);
- if (ret < 0)
+ if (ret < 0) {
+ D(DEVICE, "Bridge device %s could not be added\n", bm->dev.dev->ifname);
goto error;
+ }
return 0;
break;
case DEV_EVENT_REMOVE:
- if (!bm->present)
+ if (dev->hotplug) {
+ vlist_delete(&bst->members, &bm->node);
return;
+ }
- if (dev->hotplug)
- bridge_free_member(bm);
- else
+ if (bm->present)
bridge_remove_member(bm);
break;
bst->set_state(&bst->dev, false);
- list_for_each_entry(bm, &bst->members, list)
+ vlist_for_each_element(&bst->members, bm, node)
bridge_disable_member(bm);
system_bridge_delbr(&bst->dev);
if (ret < 0)
goto out;
- list_for_each_entry(bm, &bst->members, list)
+ vlist_for_each_element(&bst->members, bm, node)
bridge_enable_member(bm);
if (!bst->force_active && !bst->n_present) {
{
struct bridge_member *bm;
- bm = calloc(1, sizeof(*bm));
+ bm = calloc(1, sizeof(*bm) + strlen(dev->ifname) + 1);
bm->bst = bst;
bm->dev.cb = bridge_member_cb;
bm->dev.hotplug = hotplug;
- list_add_tail(&bm->list, &bst->members);
-
- device_add_user(&bm->dev, dev);
+ strcpy(bm->name, dev->ifname);
+ bm->dev.dev = dev;
+ vlist_add(&bst->members, &bm->node, bm->name);
return bm;
}
static void
-bridge_free_member(struct bridge_member *bm)
+bridge_member_update(struct vlist_tree *tree, struct vlist_node *node_new,
+ struct vlist_node *node_old)
{
- bridge_remove_member(bm);
- device_remove_user(&bm->dev);
- list_del(&bm->list);
- free(bm);
+ struct bridge_member *bm;
+ struct device *dev;
+
+ if (node_new) {
+ bm = container_of(node_new, struct bridge_member, node);
+
+ if (node_old) {
+ free(bm);
+ return;
+ }
+
+ dev = bm->dev.dev;
+ bm->dev.dev = NULL;
+ device_add_user(&bm->dev, dev);
+ }
+
+
+ if (node_old) {
+ bm = container_of(node_old, struct bridge_member, node);
+ bridge_remove_member(bm);
+ device_remove_user(&bm->dev);
+ free(bm);
+ }
}
+
static void
bridge_add_member(struct bridge_state *bst, const char *name)
{
struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
struct bridge_member *bm;
- list_for_each_entry(bm, &bst->members, list) {
- if (bm->dev.dev != member)
- continue;
-
- bridge_free_member(bm);
- return 0;
- }
+ bm = vlist_find(&bst->members, member->ifname, bm, node);
+ if (!bm)
+ return UBUS_STATUS_NOT_FOUND;
- return UBUS_STATUS_NOT_FOUND;
+ vlist_delete(&bst->members, &bm->node);
+ return 0;
}
static int
bridge_free(struct device *dev)
{
struct bridge_state *bst;
- struct bridge_member *bm;
device_cleanup(dev);
bst = container_of(dev, struct bridge_state, dev);
- while (!list_empty(&bst->members)) {
- bm = list_first_entry(&bst->members, struct bridge_member, list);
- bridge_free_member(bm);
- }
+ vlist_flush_all(&bst->members);
free(bst);
}
bst = container_of(dev, struct bridge_state, dev);
+ system_if_dump_info(dev, b);
list = blobmsg_open_array(b, "bridge-members");
- list_for_each_entry(bm, &bst->members, list) {
+
+ vlist_for_each_element(&bst->members, bm, node)
blobmsg_add_string(b, NULL, bm->dev.dev->ifname);
- }
+
blobmsg_close_array(b, list);
}
dev->hotplug_ops = &bridge_ops;
- INIT_LIST_HEAD(&bst->members);
+ vlist_init(&bst->members, avl_strcmp, bridge_member_update);
+ bst->members.keep_old = true;
return dev;
}