X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fnetwork%2Fnetworkd-link.c;h=d23be9ccbf23e7c0f37af020dbfb8d44424933af;hp=e3fb09494372baf0a311594299886e6634f1269d;hb=7619683b46bddcf753786fd20581322da9825f99;hpb=b226d99b044222739dccfa9cf9f7a9d79576c407 diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e3fb09494..d23be9ccb 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -154,6 +154,19 @@ int link_get(Manager *m, int ifindex, Link **ret) { return 0; } +void link_drop(Link *link) { + if (!link || link->state == LINK_STATE_LINGER) + return; + + link->state = LINK_STATE_LINGER; + + log_debug_link(link, "link removed"); + + link_unref(link); + + return; +} + static int link_enter_configured(Link *link) { assert(link); assert(link->state == LINK_STATE_SETTING_ROUTES); @@ -213,7 +226,7 @@ static int link_stop_clients(Link *link) { static void link_enter_failed(Link *link) { assert(link); - if (link->state == LINK_STATE_FAILED) + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; log_warning_link(link, "failed"); @@ -230,13 +243,13 @@ static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { int r; assert(link->route_messages > 0); - assert(link->state == LINK_STATE_SETTING_ADDRESSES || - link->state == LINK_STATE_SETTING_ROUTES || - link->state == LINK_STATE_FAILED); + assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, + LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED, + LINK_STATE_LINGER)); link->route_messages --; - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -272,7 +285,7 @@ static int link_enter_set_routes(Link *link) { link->state = LINK_STATE_SETTING_ROUTES; if (!link->network->static_routes && !link->dhcp_lease && - (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false)) + (!link->ipv4ll || ipv4ll_is_bound(link->ipv4ll) == false)) return link_enter_configured(link); log_debug_link(link, "setting routes"); @@ -401,7 +414,7 @@ static int route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) assert(link); assert(link->ifname); - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -427,11 +440,12 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { assert(link); assert(link->ifname); assert(link->addr_messages > 0); - assert(link->state == LINK_STATE_SETTING_ADDRESSES || link->state == LINK_STATE_FAILED); + assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, + LINK_STATE_FAILED, LINK_STATE_LINGER)); link->addr_messages --; - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -577,7 +591,7 @@ static int address_update_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userd assert(link); assert(link->ifname); - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -603,7 +617,7 @@ static int address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdat assert(link); assert(link->ifname); - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -627,6 +641,11 @@ static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, assert(link); + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { + link_unref(link); + return 1; + } + r = sd_bus_message_get_errno(m); if (r < 0) log_warning("Could not set hostname: %s", strerror(-r)); @@ -682,7 +701,7 @@ static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { assert(link); assert(link->ifname); - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -933,7 +952,7 @@ static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) { assert(link->network); assert(link->manager); - if (link->state == LINK_STATE_FAILED) + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; switch (event) { @@ -1128,6 +1147,9 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){ assert(link->network); assert(link->manager); + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return; + switch(event) { case IPV4LL_EVENT_STOP: case IPV4LL_EVENT_CONFLICT: @@ -1335,7 +1357,7 @@ static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { assert(link); - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -1417,12 +1439,13 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { int r; assert(link); - assert(link->state == LINK_STATE_ENSLAVING || link->state == LINK_STATE_FAILED); + assert(IN_SET(link->state, LINK_STATE_ENSLAVING, LINK_STATE_FAILED, + LINK_STATE_LINGER)); assert(link->network); link->enslaving --; - if (link->state == LINK_STATE_FAILED) { + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { link_unref(link); return 1; } @@ -1467,19 +1490,19 @@ static int link_enter_enslave(Link *link) { hashmap_isempty(link->network->macvlans)) return link_enslaved(link); - if (link->network->bridge) { + if (link->network->bond) { log_struct_link(LOG_DEBUG, link, "MESSAGE=%s: enslaving by '%s'", - link->ifname, link->network->bridge->name, - NETDEV(link->network->bridge), + link->ifname, link->network->bond->name, + NETDEV(link->network->bond), NULL); - r = netdev_enslave(link->network->bridge, link, &enslave_handler); + r = netdev_enslave(link->network->bond, link, &enslave_handler); if (r < 0) { log_struct_link(LOG_WARNING, link, "MESSAGE=%s: could not enslave by '%s': %s", - link->ifname, link->network->bridge->name, strerror(-r), - NETDEV(link->network->bridge), + link->ifname, link->network->bond->name, strerror(-r), + NETDEV(link->network->bond), NULL); link_enter_failed(link); return r; @@ -1489,19 +1512,19 @@ static int link_enter_enslave(Link *link) { link->enslaving ++; } - if (link->network->bond) { + if (link->network->bridge) { log_struct_link(LOG_DEBUG, link, "MESSAGE=%s: enslaving by '%s'", - link->ifname, link->network->bond->name, - NETDEV(link->network->bond), + link->ifname, link->network->bridge->name, + NETDEV(link->network->bridge), NULL); - r = netdev_enslave(link->network->bond, link, &enslave_handler); + r = netdev_enslave(link->network->bridge, link, &enslave_handler); if (r < 0) { log_struct_link(LOG_WARNING, link, "MESSAGE=%s: could not enslave by '%s': %s", - link->ifname, link->network->bond->name, strerror(-r), - NETDEV(link->network->bond), + link->ifname, link->network->bridge->name, strerror(-r), + NETDEV(link->network->bridge), NULL); link_enter_failed(link); return r; @@ -1710,6 +1733,12 @@ int link_update(Link *link, sd_rtnl_message *m) { assert(link->ifname); assert(m); + if (link->state == LINK_STATE_LINGER) { + link_ref(link); + log_info_link(link, "link readded"); + link->state = LINK_STATE_ENSLAVING; + } + r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname); if (r >= 0 && !streq(ifname, link->ifname)) { log_info_link(link, "renamed to %s", ifname); @@ -1784,6 +1813,11 @@ int link_save(Link *link) { if (r < 0) return r; + if (link->state == LINK_STATE_LINGER) { + unlink(link->state_file); + return 0; + } + admin_state = link_state_to_string(link->state); assert(admin_state); @@ -1837,6 +1871,7 @@ static const char* const link_state_table[_LINK_STATE_MAX] = { [LINK_STATE_CONFIGURED] = "configured", [LINK_STATE_UNMANAGED] = "unmanaged", [LINK_STATE_FAILED] = "failed", + [LINK_STATE_LINGER] = "linger", }; DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState);