7 #include <sys/socket.h>
8 #include <net/ethernet.h>
9 #include <netinet/ether.h>
15 static struct avl_tree devices;
17 static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
18 [DEV_ATTR_TYPE] = { "type", BLOBMSG_TYPE_STRING },
19 [DEV_ATTR_NAME] = { "name", BLOBMSG_TYPE_STRING },
20 [DEV_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_ARRAY },
21 [DEV_ATTR_MTU] = { "mtu", BLOBMSG_TYPE_INT32 },
22 [DEV_ATTR_MACADDR] = { "macaddr", BLOBMSG_TYPE_STRING },
23 [DEV_ATTR_TXQUEUELEN] = { "txqueuelen", BLOBMSG_TYPE_INT32 },
26 const struct config_param_list device_attr_list = {
27 .n_params = __DEV_ATTR_MAX,
31 static struct device *
32 simple_device_create(struct blob_attr *attr)
34 struct blob_attr *tb[__DEV_ATTR_MAX];
35 struct device *dev = NULL;
38 blobmsg_parse(dev_attrs, __DEV_ATTR_MAX, tb, blob_data(attr), blob_len(attr));
39 if (!tb[DEV_ATTR_NAME])
42 name = blobmsg_data(tb[DEV_ATTR_NAME]);
46 dev = device_get(name, true);
50 device_init_settings(dev, tb);
55 static void simple_device_free(struct device *dev)
61 const struct device_type simple_device_type = {
62 .name = "Network device",
63 .config_params = &device_attr_list,
65 .create = simple_device_create,
66 .check_state = system_if_check,
67 .free = simple_device_free,
71 device_init_settings(struct device *dev, struct blob_attr **tb)
73 struct blob_attr *cur;
74 struct ether_addr *ea;
78 if ((cur = tb[DEV_ATTR_MTU])) {
79 dev->mtu = blobmsg_get_u32(cur);
80 dev->flags |= DEV_OPT_MTU;
83 if ((cur = tb[DEV_ATTR_TXQUEUELEN])) {
84 dev->txqueuelen = blobmsg_get_u32(cur);
85 dev->flags |= DEV_OPT_TXQUEUELEN;
88 if ((cur = tb[DEV_ATTR_MACADDR])) {
89 ea = ether_aton(blob_data(cur));
91 memcpy(dev->macaddr, ea, sizeof(dev->macaddr));
92 dev->flags |= DEV_OPT_MACADDR;
97 static void __init dev_init(void)
99 avl_init(&devices, avl_strcmp, false, NULL);
102 static void device_broadcast_event(struct device *dev, enum device_event ev)
104 struct device_user *dep, *tmp;
106 list_for_each_entry_safe(dep, tmp, &dev->users, list) {
114 static int set_device_state(struct device *dev, bool state)
124 int device_claim(struct device_user *dep)
126 struct device *dev = dep->dev;
133 DPRINTF("claim device %s, new refcount: %d\n", dev->ifname, dev->active + 1);
134 if (++dev->active != 1)
137 device_broadcast_event(dev, DEV_EVENT_SETUP);
138 ret = dev->set_state(dev, true);
140 device_broadcast_event(dev, DEV_EVENT_UP);
147 void device_release(struct device_user *dep)
149 struct device *dev = dep->dev;
154 dep->claimed = false;
156 DPRINTF("release device %s, new refcount: %d\n", dev->ifname, dev->active);
157 assert(dev->active >= 0);
162 device_broadcast_event(dev, DEV_EVENT_TEARDOWN);
163 dev->set_state(dev, false);
164 device_broadcast_event(dev, DEV_EVENT_DOWN);
167 int check_device_state(struct device *dev)
169 if (!dev->type->check_state)
172 return dev->type->check_state(dev);
175 void device_init_virtual(struct device *dev, const struct device_type *type, const char *name)
181 strncpy(dev->ifname, name, IFNAMSIZ);
183 DPRINTF("Initialize device '%s'\n", dev->ifname);
184 INIT_LIST_HEAD(&dev->users);
188 int device_init(struct device *dev, const struct device_type *type, const char *ifname)
192 device_init_virtual(dev, type, ifname);
195 dev->set_state = set_device_state;
197 dev->avl.key = dev->ifname;
199 ret = avl_insert(&devices, &dev->avl);
203 check_device_state(dev);
208 struct device *device_get(const char *name, bool create)
212 if (strchr(name, '.'))
213 return get_vlan_device_chain(name, create);
215 dev = avl_find_element(&devices, name, dev, avl);
222 dev = calloc(1, sizeof(*dev));
223 device_init(dev, &simple_device_type, name);
228 void device_cleanup(struct device *dev)
230 struct device_user *dep, *tmp;
232 DPRINTF("Clean up device '%s'\n", dev->ifname);
233 list_for_each_entry_safe(dep, tmp, &dev->users, list) {
237 dep->cb(dep, DEV_EVENT_REMOVE);
241 avl_delete(&devices, &dev->avl);
244 void device_set_present(struct device *dev, bool state)
246 if (dev->present == state)
249 DPRINTF("Device '%s' %s present\n", dev->ifname, state ? "is now" : "is no longer" );
250 dev->present = state;
251 device_broadcast_event(dev, state ? DEV_EVENT_ADD : DEV_EVENT_REMOVE);
254 void device_add_user(struct device_user *dep, struct device *dev)
257 list_add_tail(&dep->list, &dev->users);
258 if (dep->cb && dev->present) {
259 dep->cb(dep, DEV_EVENT_ADD);
261 dep->cb(dep, DEV_EVENT_UP);
266 __device_free_unused(struct device *dev)
268 if (!list_empty(&dev->users))
274 void device_remove_user(struct device_user *dep)
276 struct device *dev = dep->dev;
281 list_del(&dep->list);
283 __device_free_unused(dev);
287 device_free_unused(struct device *dev)
292 return __device_free_unused(dev);
294 avl_for_each_element_safe(&devices, dev, avl, tmp)
295 __device_free_unused(dev);