if (operstate >= LINK_OPERSTATE_CARRIER) {
Link *slave;
- HASHMAP_FOREACH(slave, link->slaves, i) {
+ SET_FOREACH(slave, link->slaves, i) {
link_update_operstate(slave, false);
if (slave->operstate < LINK_OPERSTATE_CARRIER)
return 0;
}
-static void link_detach_from_manager(Link *link) {
- if (!link || !link->manager)
- return;
-
- hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
- set_remove(link->manager->links_requesting_uuid, link);
- link_clean(link);
-}
-
static Link *link_free(Link *link) {
- Link *carrier, *master;
+ Link *carrier;
Address *address;
Route *route;
Iterator i;
sd_ndisc_unref(link->ndisc);
sd_radv_unref(link->radv);
- link_detach_from_manager(link);
-
free(link->ifname);
-
free(link->kind);
(void) unlink(link->state_file);
hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex));
hashmap_free(link->bound_by_links);
- hashmap_free(link->slaves);
-
- if (link->network) {
- if (link->network->bond &&
- link_get(link->manager, link->network->bond->ifindex, &master) >= 0)
- (void) hashmap_remove(master->slaves, INT_TO_PTR(link->ifindex));
-
- if (link->network->bridge &&
- link_get(link->manager, link->network->bridge->ifindex, &master) >= 0)
- (void) hashmap_remove(master->slaves, INT_TO_PTR(link->ifindex));
- }
+ set_free_with_destructor(link->slaves, link_unref);
return mfree(link);
}
return r;
}
-static int link_append_to_master(Link *link, NetDev *netdev) {
- Link *master;
- int r;
-
- assert(link);
- assert(netdev);
-
- r = link_get(link->manager, netdev->ifindex, &master);
- if (r < 0)
- return r;
-
- r = hashmap_ensure_allocated(&master->slaves, NULL);
- if (r < 0)
- return r;
-
- r = hashmap_put(master->slaves, INT_TO_PTR(link->ifindex), link);
- if (r < 0)
- return r;
-
- return 0;
-}
-
static int link_lldp_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
return;
}
+static int link_append_to_master(Link *link, NetDev *netdev) {
+ Link *master;
+ int r;
+
+ assert(link);
+ assert(netdev);
+
+ r = link_get(link->manager, netdev->ifindex, &master);
+ if (r < 0)
+ return r;
+
+ r = set_ensure_allocated(&master->slaves, NULL);
+ if (r < 0)
+ return r;
+
+ r = set_put(master->slaves, link);
+ if (r < 0)
+ return r;
+
+ link_ref(link);
+ return 0;
+}
+
+static void link_drop_from_master(Link *link, NetDev *netdev) {
+ Link *master;
+
+ assert(link);
+
+ if (!link->manager || !netdev)
+ return;
+
+ if (link_get(link->manager, netdev->ifindex, &master) < 0)
+ return;
+
+ link_unref(set_remove(master->slaves, link));
+}
+
+static void link_detach_from_manager(Link *link) {
+ if (!link || !link->manager)
+ return;
+
+ link_unref(set_remove(link->manager->links_requesting_uuid, link));
+ link_clean(link);
+
+ /* The following must be called at last. */
+ assert_se(hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)) == link);
+ link_unref(link);
+}
+
void link_drop(Link *link) {
if (!link || link->state == LINK_STATE_LINGER)
return;
link_free_carrier_maps(link);
+ if (link->network) {
+ link_drop_from_master(link, link->network->bridge);
+ link_drop_from_master(link, link->network->bond);
+ }
+
log_link_debug(link, "Link removed");
(void) unlink(link->state_file);
-
link_detach_from_manager(link);
-
- link_unref(link);
-
- return;
}
static int link_joined(Link *link) {