18 static const struct blobmsg_policy bridge_attrs[__BRIDGE_ATTR_MAX] = {
19 [BRIDGE_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_ARRAY },
20 [BRIDGE_ATTR_STP] = { "stp", BLOBMSG_TYPE_BOOL },
23 static const union config_param_info bridge_attr_info[__BRIDGE_ATTR_MAX] = {
24 [BRIDGE_ATTR_IFNAME] = { .type = BLOBMSG_TYPE_STRING },
27 static const struct config_param_list bridge_attr_list = {
28 .n_params = __BRIDGE_ATTR_MAX,
29 .params = bridge_attrs,
30 .info = bridge_attr_info,
33 .next = { &device_attr_list },
36 static struct device *bridge_create(struct blob_attr *attr);
37 static void bridge_free(struct device *dev);
38 static void bridge_dump_status(struct device *dev, struct blob_buf *b);
40 const struct device_type bridge_device_type = {
42 .config_params = &bridge_attr_list,
44 .create = bridge_create,
46 .dump_status = bridge_dump_status,
51 device_state_cb set_state;
55 struct list_head members;
59 struct bridge_member {
60 struct list_head list;
61 struct bridge_state *bst;
62 struct device_user dev;
67 bridge_disable_member(struct bridge_member *bm)
69 struct bridge_state *bst = bm->bst;
74 system_bridge_delif(&bst->dev, bm->dev.dev);
75 device_release(&bm->dev);
81 bridge_enable_member(struct bridge_member *bm)
83 struct bridge_state *bst = bm->bst;
89 ret = device_claim(&bm->dev);
93 ret = system_bridge_addif(&bst->dev, bm->dev.dev);
106 bridge_member_cb(struct device_user *dev, enum device_event ev)
108 struct bridge_member *bm = container_of(dev, struct bridge_member, dev);
109 struct bridge_state *bst = bm->bst;
113 assert(!bm->present);
119 bridge_enable_member(bm);
120 else if (bst->n_present == 1)
121 device_set_present(&bst->dev, true);
124 case DEV_EVENT_REMOVE:
129 bridge_disable_member(bm);
132 bm->bst->n_present--;
133 if (bst->n_present == 0)
134 device_set_present(&bst->dev, false);
143 bridge_set_down(struct bridge_state *bst)
145 struct bridge_member *bm;
147 bst->set_state(&bst->dev, false);
149 list_for_each_entry(bm, &bst->members, list)
150 bridge_disable_member(bm);
152 system_bridge_delbr(&bst->dev);
158 bridge_set_up(struct bridge_state *bst)
160 struct bridge_member *bm;
166 ret = system_bridge_addbr(&bst->dev);
170 list_for_each_entry(bm, &bst->members, list)
171 bridge_enable_member(bm);
173 if (!bst->n_present) {
174 /* initialization of all member interfaces failed */
175 system_bridge_delbr(&bst->dev);
176 device_set_present(&bst->dev, false);
180 ret = bst->set_state(&bst->dev, true);
182 bridge_set_down(bst);
189 bridge_set_state(struct device *dev, bool up)
191 struct bridge_state *bst;
193 bst = container_of(dev, struct bridge_state, dev);
196 return bridge_set_up(bst);
198 return bridge_set_down(bst);
201 static struct bridge_member *
202 bridge_create_member(struct bridge_state *bst, struct device *dev)
204 struct bridge_member *bm;
206 bm = calloc(1, sizeof(*bm));
208 bm->dev.cb = bridge_member_cb;
209 device_add_user(&bm->dev, dev);
211 list_add_tail(&bm->list, &bst->members);
214 bridge_enable_member(bm);
220 bridge_free_member(struct bridge_member *bm)
223 bridge_member_cb(&bm->dev, DEV_EVENT_REMOVE);
224 bm->bst->n_present--;
225 if (bm->bst->dev.active)
226 bridge_disable_member(bm);
230 device_remove_user(&bm->dev);
235 bridge_add_member(struct bridge_state *bst, const char *name)
239 dev = device_get(name, true);
243 bridge_create_member(bst, dev);
247 bridge_hotplug_add(struct device *dev, struct device *member)
249 struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
251 bridge_create_member(bst, member);
257 bridge_hotplug_del(struct device *dev, struct device *member)
259 struct bridge_state *bst = container_of(dev, struct bridge_state, dev);
260 struct bridge_member *bm;
262 list_for_each_entry(bm, &bst->members, list) {
263 if (bm->dev.dev != member)
266 bridge_free_member(bm);
273 static const struct device_hotplug_ops bridge_ops = {
274 .add = bridge_hotplug_add,
275 .del = bridge_hotplug_del
279 bridge_free(struct device *dev)
281 struct bridge_state *bst;
282 struct bridge_member *bm;
284 bst = container_of(dev, struct bridge_state, dev);
285 while (!list_empty(&bst->members)) {
286 bm = list_first_entry(&bst->members, struct bridge_member, list);
287 bridge_free_member(bm);
293 bridge_dump_status(struct device *dev, struct blob_buf *b)
295 struct bridge_state *bst;
296 struct bridge_member *bm;
299 bst = container_of(dev, struct bridge_state, dev);
301 list = blobmsg_open_array(b, "bridge-members");
302 list_for_each_entry(bm, &bst->members, list) {
303 blobmsg_add_string(b, NULL, bm->dev.dev->ifname);
305 blobmsg_close_array(b, list);
308 static struct device *
309 bridge_create(struct blob_attr *attr)
311 struct blob_attr *tb_dev[__DEV_ATTR_MAX];
312 struct blob_attr *tb_br[__BRIDGE_ATTR_MAX];
313 struct blob_attr *cur;
314 struct bridge_state *bst;
315 struct device *dev = NULL;
319 blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev,
320 blob_data(attr), blob_len(attr));
321 blobmsg_parse(bridge_attrs, __BRIDGE_ATTR_MAX, tb_br,
322 blob_data(attr), blob_len(attr));
324 if (!tb_dev[DEV_ATTR_NAME])
327 if (!tb_br[BRIDGE_ATTR_IFNAME])
330 name = blobmsg_data(tb_dev[DEV_ATTR_NAME]);
332 bst = calloc(1, sizeof(*bst));
337 device_init(dev, &bridge_device_type, name);
338 device_init_settings(dev, tb_dev);
340 bst->set_state = dev->set_state;
341 dev->set_state = bridge_set_state;
343 dev->hotplug_ops = &bridge_ops;
345 INIT_LIST_HEAD(&bst->members);
347 blobmsg_for_each_attr(cur, tb_br[BRIDGE_ATTR_IFNAME], rem) {
348 bridge_add_member(bst, blobmsg_data(cur));