1f84a83ee66cd20ba824442d3c5df42494a839e3
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
)
51 int claim_device(struct device
*dev
)
55 DPRINTF("claim device %s, new refcount: %d\n", dev
->ifname
, dev
->active
+ 1);
56 if (++dev
->active
!= 1)
59 broadcast_device_event(dev
, DEV_EVENT_SETUP
);
60 ret
= dev
->set_state(dev
, true);
62 broadcast_device_event(dev
, DEV_EVENT_UP
);
69 void release_device(struct device
*dev
)
72 DPRINTF("release device %s, new refcount: %d\n", dev
->ifname
, dev
->active
);
73 assert(dev
->active
>= 0);
78 broadcast_device_event(dev
, DEV_EVENT_TEARDOWN
);
79 dev
->set_state(dev
, false);
80 broadcast_device_event(dev
, DEV_EVENT_DOWN
);
83 int check_device_state(struct device
*dev
)
85 if (!dev
->type
->check_state
)
88 return dev
->type
->check_state(dev
);
91 void init_virtual_device(struct device
*dev
, const struct device_type
*type
, const char *name
)
96 fprintf(stderr
, "Initialize interface '%s'\n", dev
->ifname
);
97 INIT_LIST_HEAD(&dev
->users
);
101 strncpy(dev
->ifname
, name
, IFNAMSIZ
);
104 int init_device(struct device
*dev
, const struct device_type
*type
, const char *ifname
)
108 init_virtual_device(dev
, type
, ifname
);
111 dev
->set_state
= set_device_state
;
113 dev
->avl
.key
= dev
->ifname
;
115 ret
= avl_insert(&devices
, &dev
->avl
);
119 check_device_state(dev
);
124 struct device
*get_device(const char *name
, bool create
)
126 static const struct device_type simple_type
= {
128 .check_state
= system_if_check
,
134 if (strchr(name
, '.'))
135 return get_vlan_device_chain(name
, create
);
137 dev
= avl_find_element(&devices
, name
, dev
, avl
);
144 dev
= calloc(1, sizeof(*dev
));
145 init_device(dev
, &simple_type
, name
);
150 void cleanup_device(struct device
*dev
)
152 struct device_user
*dep
, *tmp
;
154 fprintf(stderr
, "Clean up interface '%s'\n", dev
->ifname
);
155 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
159 dep
->cb(dep
, DEV_EVENT_REMOVE
);
163 avl_delete(&devices
, &dev
->avl
);
166 void set_device_present(struct device
*dev
, bool state
)
168 if (dev
->present
== state
)
171 DPRINTF("Device '%s' %s present\n", dev
->ifname
, state
? "is now" : "is no longer" );
172 dev
->present
= state
;
173 broadcast_device_event(dev
, state
? DEV_EVENT_ADD
: DEV_EVENT_REMOVE
);
176 void add_device_user(struct device_user
*dep
, struct device
*dev
)
179 list_add(&dep
->list
, &dev
->users
);
180 if (dep
->cb
&& dev
->present
) {
181 dep
->cb(dep
, DEV_EVENT_ADD
);
183 dep
->cb(dep
, DEV_EVENT_UP
);
187 void remove_device_user(struct device_user
*dep
)
189 struct device
*dev
= dep
->dev
;
191 list_del(&dep
->list
);
193 if (list_empty(&dev
->users
)) {
194 /* all references have gone away, remove this interface */
195 dev
->type
->free(dev
);