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_config_init(struct device
*dev
);
38 static void bridge_free(struct device
*dev
);
39 static void bridge_dump_status(struct device
*dev
, struct blob_buf
*b
);
41 const struct device_type bridge_device_type
= {
43 .config_params
= &bridge_attr_list
,
45 .create
= bridge_create
,
46 .config_init
= bridge_config_init
,
48 .dump_status
= bridge_dump_status
,
53 device_state_cb set_state
;
55 struct blob_attr
*ifnames
;
58 struct list_head members
;
62 struct bridge_member
{
63 struct list_head list
;
64 struct bridge_state
*bst
;
65 struct device_user dev
;
70 bridge_disable_member(struct bridge_member
*bm
)
72 struct bridge_state
*bst
= bm
->bst
;
77 system_bridge_delif(&bst
->dev
, bm
->dev
.dev
);
78 device_release(&bm
->dev
);
84 bridge_enable_member(struct bridge_member
*bm
)
86 struct bridge_state
*bst
= bm
->bst
;
92 ret
= device_claim(&bm
->dev
);
96 ret
= system_bridge_addif(&bst
->dev
, bm
->dev
.dev
);
109 bridge_member_cb(struct device_user
*dev
, enum device_event ev
)
111 struct bridge_member
*bm
= container_of(dev
, struct bridge_member
, dev
);
112 struct bridge_state
*bst
= bm
->bst
;
116 assert(!bm
->present
);
122 bridge_enable_member(bm
);
123 else if (bst
->n_present
== 1)
124 device_set_present(&bst
->dev
, true);
127 case DEV_EVENT_REMOVE
:
132 bridge_disable_member(bm
);
135 bm
->bst
->n_present
--;
136 if (bst
->n_present
== 0)
137 device_set_present(&bst
->dev
, false);
146 bridge_set_down(struct bridge_state
*bst
)
148 struct bridge_member
*bm
;
150 bst
->set_state(&bst
->dev
, false);
152 list_for_each_entry(bm
, &bst
->members
, list
)
153 bridge_disable_member(bm
);
155 system_bridge_delbr(&bst
->dev
);
161 bridge_set_up(struct bridge_state
*bst
)
163 struct bridge_member
*bm
;
169 ret
= system_bridge_addbr(&bst
->dev
);
173 list_for_each_entry(bm
, &bst
->members
, list
)
174 bridge_enable_member(bm
);
176 if (!bst
->n_present
) {
177 /* initialization of all member interfaces failed */
178 system_bridge_delbr(&bst
->dev
);
179 device_set_present(&bst
->dev
, false);
183 ret
= bst
->set_state(&bst
->dev
, true);
185 bridge_set_down(bst
);
192 bridge_set_state(struct device
*dev
, bool up
)
194 struct bridge_state
*bst
;
196 bst
= container_of(dev
, struct bridge_state
, dev
);
199 return bridge_set_up(bst
);
201 return bridge_set_down(bst
);
204 static struct bridge_member
*
205 bridge_create_member(struct bridge_state
*bst
, struct device
*dev
)
207 struct bridge_member
*bm
;
209 bm
= calloc(1, sizeof(*bm
));
211 bm
->dev
.cb
= bridge_member_cb
;
212 device_add_user(&bm
->dev
, dev
);
214 list_add_tail(&bm
->list
, &bst
->members
);
217 bridge_enable_member(bm
);
223 bridge_free_member(struct bridge_member
*bm
)
226 bridge_member_cb(&bm
->dev
, DEV_EVENT_REMOVE
);
227 bm
->bst
->n_present
--;
228 if (bm
->bst
->dev
.active
)
229 bridge_disable_member(bm
);
233 device_remove_user(&bm
->dev
);
238 bridge_add_member(struct bridge_state
*bst
, const char *name
)
242 dev
= device_get(name
, true);
246 bridge_create_member(bst
, dev
);
250 bridge_hotplug_add(struct device
*dev
, struct device
*member
)
252 struct bridge_state
*bst
= container_of(dev
, struct bridge_state
, dev
);
254 bridge_create_member(bst
, member
);
260 bridge_hotplug_del(struct device
*dev
, struct device
*member
)
262 struct bridge_state
*bst
= container_of(dev
, struct bridge_state
, dev
);
263 struct bridge_member
*bm
;
265 list_for_each_entry(bm
, &bst
->members
, list
) {
266 if (bm
->dev
.dev
!= member
)
269 bridge_free_member(bm
);
276 static const struct device_hotplug_ops bridge_ops
= {
277 .add
= bridge_hotplug_add
,
278 .del
= bridge_hotplug_del
282 bridge_free(struct device
*dev
)
284 struct bridge_state
*bst
;
285 struct bridge_member
*bm
;
288 bst
= container_of(dev
, struct bridge_state
, dev
);
289 while (!list_empty(&bst
->members
)) {
290 bm
= list_first_entry(&bst
->members
, struct bridge_member
, list
);
291 bridge_free_member(bm
);
297 bridge_dump_status(struct device
*dev
, struct blob_buf
*b
)
299 struct bridge_state
*bst
;
300 struct bridge_member
*bm
;
303 bst
= container_of(dev
, struct bridge_state
, dev
);
305 list
= blobmsg_open_array(b
, "bridge-members");
306 list_for_each_entry(bm
, &bst
->members
, list
) {
307 blobmsg_add_string(b
, NULL
, bm
->dev
.dev
->ifname
);
309 blobmsg_close_array(b
, list
);
313 bridge_config_init(struct device
*dev
)
315 struct bridge_state
*bst
;
316 struct blob_attr
*cur
;
319 bst
= container_of(dev
, struct bridge_state
, dev
);
320 blobmsg_for_each_attr(cur
, bst
->ifnames
, rem
) {
321 bridge_add_member(bst
, blobmsg_data(cur
));
325 static struct device
*
326 bridge_create(struct blob_attr
*attr
)
328 struct blob_attr
*tb_dev
[__DEV_ATTR_MAX
];
329 struct blob_attr
*tb_br
[__BRIDGE_ATTR_MAX
];
330 struct bridge_state
*bst
;
331 struct device
*dev
= NULL
;
334 blobmsg_parse(device_attr_list
.params
, __DEV_ATTR_MAX
, tb_dev
,
335 blob_data(attr
), blob_len(attr
));
336 blobmsg_parse(bridge_attrs
, __BRIDGE_ATTR_MAX
, tb_br
,
337 blob_data(attr
), blob_len(attr
));
339 if (!tb_dev
[DEV_ATTR_NAME
])
342 if (!tb_br
[BRIDGE_ATTR_IFNAME
])
345 name
= blobmsg_data(tb_dev
[DEV_ATTR_NAME
]);
347 bst
= calloc(1, sizeof(*bst
));
352 device_init(dev
, &bridge_device_type
, name
);
353 device_init_settings(dev
, tb_dev
);
354 dev
->config_pending
= true;
355 bst
->ifnames
= tb_br
[BRIDGE_ATTR_IFNAME
];
357 bst
->set_state
= dev
->set_state
;
358 dev
->set_state
= bridge_set_state
;
360 dev
->hotplug_ops
= &bridge_ops
;
362 INIT_LIST_HEAD(&bst
->members
);