6 #include <libubox/uapi.h>
11 static struct avl_tree devices
;
13 static int avl_strcmp(const void *k1
, const void *k2
, void *ptr
)
15 return strcmp(k1
, k2
);
18 static void API_CTOR
dev_init(void)
20 avl_init(&devices
, avl_strcmp
, false, NULL
);
23 static void free_device(struct device
*dev
)
29 static void broadcast_device_event(struct device
*dev
, enum device_event ev
)
31 struct device_user
*dep
, *tmp
;
33 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
41 static int set_device_state(struct device
*dev
, bool state
)
44 broadcast_device_event(dev
, DEV_EVENT_SETUP
);
46 broadcast_device_event(dev
, DEV_EVENT_UP
);
48 broadcast_device_event(dev
, DEV_EVENT_TEARDOWN
);
50 broadcast_device_event(dev
, DEV_EVENT_DOWN
);
55 int claim_device(struct device
*dev
)
59 DPRINTF("claim device %s, new refcount: %d\n", dev
->ifname
, dev
->active
+ 1);
60 if (++dev
->active
!= 1)
63 ret
= dev
->set_state(dev
, true);
70 void release_device(struct device
*dev
)
73 DPRINTF("release device %s, new refcount: %d\n", dev
->ifname
, dev
->active
);
74 assert(dev
->active
>= 0);
77 dev
->set_state(dev
, false);
80 int check_device_state(struct device
*dev
)
82 if (!dev
->type
->check_state
)
85 return dev
->type
->check_state(dev
);
88 int init_device(struct device
*dev
, const struct device_type
*type
, const char *ifname
)
96 strncpy(dev
->ifname
, ifname
, IFNAMSIZ
);
99 dev
->set_state
= set_device_state
;
101 fprintf(stderr
, "Initialize interface '%s'\n", dev
->ifname
);
102 INIT_LIST_HEAD(&dev
->users
);
103 dev
->avl
.key
= dev
->ifname
;
106 ret
= avl_insert(&devices
, &dev
->avl
);
110 check_device_state(dev
);
114 struct device
*get_device(const char *name
, bool create
)
116 static const struct device_type simple_type
= {
118 .check_state
= system_if_check
,
124 if (strchr(name
, '.'))
125 return get_vlan_device_chain(name
, create
);
127 dev
= avl_find_element(&devices
, name
, dev
, avl
);
134 dev
= calloc(1, sizeof(*dev
));
135 init_device(dev
, &simple_type
, name
);
140 void cleanup_device(struct device
*dev
)
142 struct device_user
*dep
, *tmp
;
144 fprintf(stderr
, "Clean up interface '%s'\n", dev
->ifname
);
145 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
149 dep
->cb(dep
, DEV_EVENT_REMOVE
);
152 avl_delete(&devices
, &dev
->avl
);
155 void set_device_present(struct device
*dev
, bool state
)
157 if (dev
->present
== state
)
160 DPRINTF("Device '%s' %s present\n", dev
->ifname
, state
? "is now" : "is no longer" );
161 dev
->present
= state
;
162 broadcast_device_event(dev
, state
? DEV_EVENT_ADD
: DEV_EVENT_REMOVE
);
165 void add_device_user(struct device_user
*dep
, struct device
*dev
)
168 list_add(&dep
->list
, &dev
->users
);
169 if (dep
->cb
&& dev
->present
) {
170 dep
->cb(dep
, DEV_EVENT_ADD
);
172 dep
->cb(dep
, DEV_EVENT_UP
);
176 void remove_device_user(struct device_user
*dep
)
178 struct device
*dev
= dep
->dev
;
180 list_del(&dep
->list
);
182 if (list_empty(&dev
->users
)) {
183 /* all references have gone away, remove this interface */
184 dev
->type
->free(dev
);