7 #include <sys/socket.h>
8 #include <net/ethernet.h>
14 static struct avl_tree devices
;
16 static const struct blobmsg_policy dev_attrs
[__DEV_ATTR_MAX
] = {
17 [DEV_ATTR_TYPE
] = { "type", BLOBMSG_TYPE_STRING
},
18 [DEV_ATTR_NAME
] = { "name", BLOBMSG_TYPE_STRING
},
19 [DEV_ATTR_IFNAME
] = { "ifname", BLOBMSG_TYPE_ARRAY
},
20 [DEV_ATTR_MTU
] = { "mtu", BLOBMSG_TYPE_INT32
},
21 [DEV_ATTR_MACADDR
] = { "macaddr", BLOBMSG_TYPE_STRING
},
22 [DEV_ATTR_TXQUEUELEN
] = { "txqueuelen", BLOBMSG_TYPE_INT32
},
25 const struct config_param_list device_attr_list
= {
26 .n_params
= __DEV_ATTR_MAX
,
30 static struct device
*
31 simple_device_create(struct blob_attr
*attr
)
33 struct blob_attr
*tb
[__DEV_ATTR_MAX
];
34 struct device
*dev
= NULL
;
37 blobmsg_parse(dev_attrs
, __DEV_ATTR_MAX
, tb
, blob_data(attr
), blob_len(attr
));
38 if (!tb
[DEV_ATTR_NAME
])
41 name
= blobmsg_data(tb
[DEV_ATTR_NAME
]);
45 dev
= device_get(name
, true);
49 device_init_settings(dev
, tb
);
54 static void simple_device_free(struct device
*dev
)
60 const struct device_type simple_device_type
= {
61 .name
= "Network device",
62 .config_params
= &device_attr_list
,
64 .create
= simple_device_create
,
65 .check_state
= system_if_check
,
66 .free
= simple_device_free
,
70 device_init_settings(struct device
*dev
, struct blob_attr
**tb
)
72 struct blob_attr
*cur
;
73 struct ether_addr
*ea
;
77 if ((cur
= tb
[DEV_ATTR_MTU
])) {
78 dev
->mtu
= blobmsg_get_u32(cur
);
79 dev
->flags
|= DEV_OPT_MTU
;
82 if ((cur
= tb
[DEV_ATTR_TXQUEUELEN
])) {
83 dev
->txqueuelen
= blobmsg_get_u32(cur
);
84 dev
->flags
|= DEV_OPT_TXQUEUELEN
;
87 if ((cur
= tb
[DEV_ATTR_MACADDR
])) {
88 ea
= ether_aton(blob_data(cur
));
90 memcpy(dev
->macaddr
, ea
, sizeof(dev
->macaddr
));
91 dev
->flags
|= DEV_OPT_MACADDR
;
96 static void __init
dev_init(void)
98 avl_init(&devices
, avl_strcmp
, false, NULL
);
101 static void device_broadcast_event(struct device
*dev
, enum device_event ev
)
103 struct device_user
*dep
, *tmp
;
105 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
113 static int set_device_state(struct device
*dev
, bool state
)
123 int device_claim(struct device
*dev
)
127 DPRINTF("claim device %s, new refcount: %d\n", dev
->ifname
, dev
->active
+ 1);
128 if (++dev
->active
!= 1)
131 device_broadcast_event(dev
, DEV_EVENT_SETUP
);
132 ret
= dev
->set_state(dev
, true);
134 device_broadcast_event(dev
, DEV_EVENT_UP
);
141 void device_release(struct device
*dev
)
144 DPRINTF("release device %s, new refcount: %d\n", dev
->ifname
, dev
->active
);
145 assert(dev
->active
>= 0);
150 device_broadcast_event(dev
, DEV_EVENT_TEARDOWN
);
151 dev
->set_state(dev
, false);
152 device_broadcast_event(dev
, DEV_EVENT_DOWN
);
155 int check_device_state(struct device
*dev
)
157 if (!dev
->type
->check_state
)
160 return dev
->type
->check_state(dev
);
163 void device_init_virtual(struct device
*dev
, const struct device_type
*type
, const char *name
)
169 strncpy(dev
->ifname
, name
, IFNAMSIZ
);
171 fprintf(stderr
, "Initialize device '%s'\n", dev
->ifname
);
172 INIT_LIST_HEAD(&dev
->users
);
176 int device_init(struct device
*dev
, const struct device_type
*type
, const char *ifname
)
180 device_init_virtual(dev
, type
, ifname
);
183 dev
->set_state
= set_device_state
;
185 dev
->avl
.key
= dev
->ifname
;
187 ret
= avl_insert(&devices
, &dev
->avl
);
191 check_device_state(dev
);
196 struct device
*device_get(const char *name
, bool create
)
200 if (strchr(name
, '.'))
201 return get_vlan_device_chain(name
, create
);
203 dev
= avl_find_element(&devices
, name
, dev
, avl
);
210 dev
= calloc(1, sizeof(*dev
));
211 device_init(dev
, &simple_device_type
, name
);
216 void device_cleanup(struct device
*dev
)
218 struct device_user
*dep
, *tmp
;
220 fprintf(stderr
, "Clean up device '%s'\n", dev
->ifname
);
221 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
225 dep
->cb(dep
, DEV_EVENT_REMOVE
);
229 avl_delete(&devices
, &dev
->avl
);
232 void device_set_present(struct device
*dev
, bool state
)
234 if (dev
->present
== state
)
237 DPRINTF("Device '%s' %s present\n", dev
->ifname
, state
? "is now" : "is no longer" );
238 dev
->present
= state
;
239 device_broadcast_event(dev
, state
? DEV_EVENT_ADD
: DEV_EVENT_REMOVE
);
242 void device_add_user(struct device_user
*dep
, struct device
*dev
)
245 list_add_tail(&dep
->list
, &dev
->users
);
246 if (dep
->cb
&& dev
->present
) {
247 dep
->cb(dep
, DEV_EVENT_ADD
);
249 dep
->cb(dep
, DEV_EVENT_UP
);
253 void device_remove_user(struct device_user
*dep
)
255 struct device
*dev
= dep
->dev
;
257 list_del(&dep
->list
);
259 if (list_empty(&dev
->users
)) {
260 /* all references have gone away, remove this device */
268 device_free_all(void)
270 struct device
*dev
, *tmp
;
272 avl_for_each_element_safe(&devices
, dev
, avl
, tmp
) {
273 if (!list_empty(&dev
->users
))