9 static struct avl_tree devices
;
11 static void __init
dev_init(void)
13 avl_init(&devices
, avl_strcmp
, false, NULL
);
16 static void free_simple_device(struct device
*dev
)
22 static void broadcast_device_event(struct device
*dev
, enum device_event ev
)
24 struct device_user
*dep
, *tmp
;
26 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
34 static int set_device_state(struct device
*dev
, bool state
)
44 int claim_device(struct device
*dev
)
48 DPRINTF("claim device %s, new refcount: %d\n", dev
->ifname
, dev
->active
+ 1);
49 if (++dev
->active
!= 1)
52 broadcast_device_event(dev
, DEV_EVENT_SETUP
);
53 ret
= dev
->set_state(dev
, true);
55 broadcast_device_event(dev
, DEV_EVENT_UP
);
62 void release_device(struct device
*dev
)
65 DPRINTF("release device %s, new refcount: %d\n", dev
->ifname
, dev
->active
);
66 assert(dev
->active
>= 0);
71 broadcast_device_event(dev
, DEV_EVENT_TEARDOWN
);
72 dev
->set_state(dev
, false);
73 broadcast_device_event(dev
, DEV_EVENT_DOWN
);
76 int check_device_state(struct device
*dev
)
78 if (!dev
->type
->check_state
)
81 return dev
->type
->check_state(dev
);
84 void init_virtual_device(struct device
*dev
, const struct device_type
*type
, const char *name
)
90 strncpy(dev
->ifname
, name
, IFNAMSIZ
);
92 fprintf(stderr
, "Initialize device '%s'\n", dev
->ifname
);
93 INIT_LIST_HEAD(&dev
->users
);
97 int init_device(struct device
*dev
, const struct device_type
*type
, const char *ifname
)
101 init_virtual_device(dev
, type
, ifname
);
104 dev
->set_state
= set_device_state
;
106 dev
->avl
.key
= dev
->ifname
;
108 ret
= avl_insert(&devices
, &dev
->avl
);
112 check_device_state(dev
);
117 struct device
*get_device(const char *name
, bool create
)
119 static const struct device_type simple_type
= {
121 .check_state
= system_if_check
,
122 .free
= free_simple_device
,
127 if (strchr(name
, '.'))
128 return get_vlan_device_chain(name
, create
);
130 dev
= avl_find_element(&devices
, name
, dev
, avl
);
137 dev
= calloc(1, sizeof(*dev
));
138 init_device(dev
, &simple_type
, name
);
143 void cleanup_device(struct device
*dev
)
145 struct device_user
*dep
, *tmp
;
147 fprintf(stderr
, "Clean up device '%s'\n", dev
->ifname
);
148 list_for_each_entry_safe(dep
, tmp
, &dev
->users
, list
) {
152 dep
->cb(dep
, DEV_EVENT_REMOVE
);
156 avl_delete(&devices
, &dev
->avl
);
159 void set_device_present(struct device
*dev
, bool state
)
161 if (dev
->present
== state
)
164 DPRINTF("Device '%s' %s present\n", dev
->ifname
, state
? "is now" : "is no longer" );
165 dev
->present
= state
;
166 broadcast_device_event(dev
, state
? DEV_EVENT_ADD
: DEV_EVENT_REMOVE
);
169 void add_device_user(struct device_user
*dep
, struct device
*dev
)
172 list_add(&dep
->list
, &dev
->users
);
173 if (dep
->cb
&& dev
->present
) {
174 dep
->cb(dep
, DEV_EVENT_ADD
);
176 dep
->cb(dep
, DEV_EVENT_UP
);
180 void remove_device_user(struct device_user
*dep
)
182 struct device
*dev
= dep
->dev
;
184 list_del(&dep
->list
);
186 if (list_empty(&dev
->users
)) {
187 /* all references have gone away, remove this device */
195 cleanup_devices(void)
197 struct device
*dev
, *tmp
;
199 avl_for_each_element_safe(&devices
, dev
, avl
, tmp
) {
200 if (!list_empty(&dev
->users
))