From 370e9930c3260cc58984ec70e44b1e2ab7676496 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Thu, 8 May 2014 20:50:05 +0200 Subject: [PATCH] networkd: link - introduce LINGER state and link_drop() We need the LINGER state in case we still have references to the link after it has been dropped. --- src/network/networkd-link.c | 61 ++++++++++++++++++++++++++--------- src/network/networkd-netdev.c | 2 ++ src/network/networkd.h | 2 ++ 3 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index e3fb09494..0a228b29a 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, "dropped"); + + 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; } @@ -1784,6 +1807,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 +1865,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); diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index c7bec74aa..36decf459 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -114,6 +114,8 @@ void netdev_drop(NetDev *netdev) { netdev->state = NETDEV_STATE_LINGER; + log_debug_netdev(netdev, "dropped"); + netdev_cancel_callbacks(netdev); netdev_unref(netdev); diff --git a/src/network/networkd.h b/src/network/networkd.h index bdf980872..692b3df9a 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -195,6 +195,7 @@ typedef enum LinkState { LINK_STATE_CONFIGURED, LINK_STATE_UNMANAGED, LINK_STATE_FAILED, + LINK_STATE_LINGER, _LINK_STATE_MAX, _LINK_STATE_INVALID = -1 } LinkState; @@ -370,6 +371,7 @@ Link *link_unref(Link *link); Link *link_ref(Link *link); int link_get(Manager *m, int ifindex, Link **ret); int link_add(Manager *manager, sd_rtnl_message *message, Link **ret); +void link_drop(Link *link); int link_update(Link *link, sd_rtnl_message *message); -- 2.30.2