From 4ddbf08cfd2904eb4317e222716c65deacf22513 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 13 Mar 2019 14:26:38 +0900 Subject: [PATCH 01/10] test-network: wait more and fix wrong operational state Closes #11977. --- test/test-network/systemd-networkd-tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 856960ad65..eaf57cb540 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1219,7 +1219,7 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities): self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0) self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0) - time.sleep(2) + time.sleep(5) output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8') print(output) @@ -1231,7 +1231,7 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities): output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8') print(output) - self.assertRegex(output, 'State: degraded \(configured\)') + self.assertRegex(output, 'State: no-carrier \(configured\)') class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities): links = [ From 2cd6b9326c3555c4af6645beaa05ab482aff2e21 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 5 Mar 2019 14:39:57 +0900 Subject: [PATCH 02/10] network: move LinkOperationalState and relevant functions to network-util.[ch] --- src/libsystemd/sd-network/network-util.c | 13 +++++++++++++ src/libsystemd/sd-network/network-util.h | 17 +++++++++++++++++ src/network/networkd-link.c | 12 ------------ src/network/networkd-link.h | 16 +--------------- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c index df5ce86842..86e9b1a751 100644 --- a/src/libsystemd/sd-network/network-util.c +++ b/src/libsystemd/sd-network/network-util.c @@ -3,6 +3,7 @@ #include "alloc-util.h" #include "fd-util.h" #include "network-util.h" +#include "string-table.h" #include "strv.h" bool network_is_online(void) { @@ -18,3 +19,15 @@ bool network_is_online(void) { return false; } + +static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { + [LINK_OPERSTATE_OFF] = "off", + [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", + [LINK_OPERSTATE_DORMANT] = "dormant", + [LINK_OPERSTATE_CARRIER] = "carrier", + [LINK_OPERSTATE_DEGRADED] = "degraded", + [LINK_OPERSTATE_ENSLAVED] = "enslaved", + [LINK_OPERSTATE_ROUTABLE] = "routable", +}; + +DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState); diff --git a/src/libsystemd/sd-network/network-util.h b/src/libsystemd/sd-network/network-util.h index e868bc2e27..82a16b092e 100644 --- a/src/libsystemd/sd-network/network-util.h +++ b/src/libsystemd/sd-network/network-util.h @@ -3,4 +3,21 @@ #include "sd-network.h" +#include "macro.h" + bool network_is_online(void); + +typedef enum LinkOperationalState { + LINK_OPERSTATE_OFF, + LINK_OPERSTATE_NO_CARRIER, + LINK_OPERSTATE_DORMANT, + LINK_OPERSTATE_CARRIER, + LINK_OPERSTATE_DEGRADED, + LINK_OPERSTATE_ENSLAVED, + LINK_OPERSTATE_ROUTABLE, + _LINK_OPERSTATE_MAX, + _LINK_OPERSTATE_INVALID = -1 +} LinkOperationalState; + +const char* link_operstate_to_string(LinkOperationalState s) _const_; +LinkOperationalState link_operstate_from_string(const char *s) _pure_; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index de112a2ef8..6704c5d8a8 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -4306,15 +4306,3 @@ static const char* const link_state_table[_LINK_STATE_MAX] = { }; DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState); - -static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { - [LINK_OPERSTATE_OFF] = "off", - [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", - [LINK_OPERSTATE_DORMANT] = "dormant", - [LINK_OPERSTATE_CARRIER] = "carrier", - [LINK_OPERSTATE_DEGRADED] = "degraded", - [LINK_OPERSTATE_ENSLAVED] = "enslaved", - [LINK_OPERSTATE_ROUTABLE] = "routable", -}; - -DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index b6b7c92b4f..c4e061ca13 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -15,6 +15,7 @@ #include "sd-netlink.h" #include "list.h" +#include "network-util.h" #include "set.h" typedef enum LinkState { @@ -28,18 +29,6 @@ typedef enum LinkState { _LINK_STATE_INVALID = -1 } LinkState; -typedef enum LinkOperationalState { - LINK_OPERSTATE_OFF, - LINK_OPERSTATE_NO_CARRIER, - LINK_OPERSTATE_DORMANT, - LINK_OPERSTATE_CARRIER, - LINK_OPERSTATE_DEGRADED, - LINK_OPERSTATE_ENSLAVED, - LINK_OPERSTATE_ROUTABLE, - _LINK_OPERSTATE_MAX, - _LINK_OPERSTATE_INVALID = -1 -} LinkOperationalState; - typedef struct Manager Manager; typedef struct Network Network; typedef struct Address Address; @@ -180,9 +169,6 @@ int dhcp6_lease_pd_prefix_lost(sd_dhcp6_client *client, Link* link); const char* link_state_to_string(LinkState s) _const_; LinkState link_state_from_string(const char *s) _pure_; -const char* link_operstate_to_string(LinkOperationalState s) _const_; -LinkOperationalState link_operstate_from_string(const char *s) _pure_; - extern const sd_bus_vtable link_vtable[]; int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); From c9cc03834369abfb91fba76fbb26a2e97d3fa9ad Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 5 Mar 2019 14:41:56 +0900 Subject: [PATCH 03/10] network: introduce 'degraded-carrier' operstate to order all states Previously, 'degraded' state is ambiguous for bonding or bridge master: 1. one or more slave interfaces does not have carrier, 2. no link local address is assigned to the master, 3. combination of the above two. This makes the above case 1 and 3 are in the new 'degraded-carrier' state, and makes 'degraded' state as all slaves are active but no link local address on master. --- man/networkctl.xml | 11 ++++++++--- src/libsystemd/sd-network/network-util.c | 15 ++++++++------- src/libsystemd/sd-network/network-util.h | 1 + src/network/networkctl.c | 4 ++-- src/network/networkd-link.c | 7 +++---- test/test-network/systemd-networkd-tests.py | 4 ++-- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/man/networkctl.xml b/man/networkctl.xml index 1fc94d7eda..c513d9542a 100644 --- a/man/networkctl.xml +++ b/man/networkctl.xml @@ -115,6 +115,13 @@ the device has a carrier, but is not yet ready for normal traffic + + degraded-carrier + + for bond or bridge master, one of the bonding or bridge slave network interfaces is + in off, no-carrier, or dormant state + + carrier @@ -125,9 +132,7 @@ degraded - the link has carrier and addresses valid on the local link configured, or for bond - or bridge master, one of the bonding or bridge slave network interfaces is in off, - no-carrier, or dormant + the link has carrier and addresses valid on the local link configured diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c index 86e9b1a751..f46a3ff788 100644 --- a/src/libsystemd/sd-network/network-util.c +++ b/src/libsystemd/sd-network/network-util.c @@ -21,13 +21,14 @@ bool network_is_online(void) { } static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { - [LINK_OPERSTATE_OFF] = "off", - [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", - [LINK_OPERSTATE_DORMANT] = "dormant", - [LINK_OPERSTATE_CARRIER] = "carrier", - [LINK_OPERSTATE_DEGRADED] = "degraded", - [LINK_OPERSTATE_ENSLAVED] = "enslaved", - [LINK_OPERSTATE_ROUTABLE] = "routable", + [LINK_OPERSTATE_OFF] = "off", + [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", + [LINK_OPERSTATE_DORMANT] = "dormant", + [LINK_OPERSTATE_DEGRADED_CARRIER] = "degraded-carrier", + [LINK_OPERSTATE_CARRIER] = "carrier", + [LINK_OPERSTATE_DEGRADED] = "degraded", + [LINK_OPERSTATE_ENSLAVED] = "enslaved", + [LINK_OPERSTATE_ROUTABLE] = "routable", }; DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState); diff --git a/src/libsystemd/sd-network/network-util.h b/src/libsystemd/sd-network/network-util.h index 82a16b092e..6936fd536b 100644 --- a/src/libsystemd/sd-network/network-util.h +++ b/src/libsystemd/sd-network/network-util.h @@ -11,6 +11,7 @@ typedef enum LinkOperationalState { LINK_OPERSTATE_OFF, LINK_OPERSTATE_NO_CARRIER, LINK_OPERSTATE_DORMANT, + LINK_OPERSTATE_DEGRADED_CARRIER, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_ENSLAVED, diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 2803f5210b..9452dabcde 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -213,7 +213,7 @@ static int list_links(int argc, char *argv[], void *userdata) { (void) pager_open(arg_pager_flags); if (arg_legend) - printf("%3s %-16s %-18s %-11s %-10s\n", + printf("%3s %-16s %-18s %-16s %-10s\n", "IDX", "LINK", "TYPE", @@ -241,7 +241,7 @@ static int list_links(int argc, char *argv[], void *userdata) { t = link_get_type_string(links[i].iftype, d); - printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n", + printf("%3i %-16s %-18s %s%-16s%s %s%-10s%s\n", links[i].ifindex, links[i].name, strna(t), on_color_operational, strna(operational_state), off_color_operational, on_color_setup, strna(setup_state), off_color_setup); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 6704c5d8a8..9a4ba7a93a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -407,15 +407,14 @@ void link_update_operstate(Link *link, bool also_update_master) { link_is_enslaved(link)) operstate = LINK_OPERSTATE_ENSLAVED; - if (IN_SET(operstate, LINK_OPERSTATE_CARRIER, LINK_OPERSTATE_ENSLAVED, LINK_OPERSTATE_ROUTABLE)) { + if (operstate >= LINK_OPERSTATE_CARRIER) { Link *slave; HASHMAP_FOREACH(slave, link->slaves, i) { link_update_operstate(slave, false); - if (IN_SET(slave->operstate, - LINK_OPERSTATE_OFF, LINK_OPERSTATE_NO_CARRIER, LINK_OPERSTATE_DORMANT)) - operstate = LINK_OPERSTATE_DEGRADED; + if (slave->operstate < LINK_OPERSTATE_CARRIER) + operstate = LINK_OPERSTATE_DEGRADED_CARRIER; } } diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index eaf57cb540..1614af29b0 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -1200,7 +1200,7 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities): output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8') print(output) - self.assertRegex(output, 'State: degraded \(configured\)') + self.assertRegex(output, 'State: degraded-carrier \(configured\)') self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0) time.sleep(2) @@ -1313,7 +1313,7 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities): time.sleep(3) output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8') - self.assertRegex(output, 'State: degraded \(configured\)') + self.assertRegex(output, 'State: degraded-carrier \(configured\)') self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0) time.sleep(3) From f9974167e464bfc733b25a0aeb939a7c54c623c5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 5 Mar 2019 15:15:40 +0900 Subject: [PATCH 04/10] hashmap: add hashmap_free_free_keyp and friend --- src/basic/hashmap.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basic/hashmap.h b/src/basic/hashmap.h index e16a9f9e30..41c8adb16b 100644 --- a/src/basic/hashmap.h +++ b/src/basic/hashmap.h @@ -412,9 +412,11 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) { DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_key); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free); +DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_key); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedHashmap*, ordered_hashmap_free_free_free); #define _cleanup_hashmap_free_ _cleanup_(hashmap_freep) From 4ac77d63e999d59697c758f8304e55f19c160ecb Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Mar 2019 14:29:49 +0900 Subject: [PATCH 05/10] network: make RequiredForOnline= also take operational state This will be used by systemd-networkd-wait-online. --- src/network/networkd-link.c | 3 ++ src/network/networkd-network-gperf.gperf | 2 +- src/network/networkd-network.c | 44 ++++++++++++++++++++++++ src/network/networkd-network.h | 2 ++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 9a4ba7a93a..bc8c180665 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -4003,6 +4003,9 @@ int link_save(Link *link) { fprintf(f, "REQUIRED_FOR_ONLINE=%s\n", yes_no(link->network->required_for_online)); + fprintf(f, "REQUIRED_OPER_STATE_FOR_ONLINE=%s\n", + strempty(link_operstate_to_string(link->network->required_operstate_for_online))); + if (link->dhcp6_client) { r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); if (r < 0 && r != -ENOMSG) diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 51123d12ef..73a7fcdf08 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -36,7 +36,7 @@ Link.ARP, config_parse_tristate, Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast) Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast) Link.Unmanaged, config_parse_bool, 0, offsetof(Network, unmanaged) -Link.RequiredForOnline, config_parse_bool, 0, offsetof(Network, required_for_online) +Link.RequiredForOnline, config_parse_required_for_online, 0, 0 Network.Description, config_parse_string, 0, offsetof(Network, description) Network.Bridge, config_parse_ifname, 0, offsetof(Network, bridge_name) Network.Bond, config_parse_ifname, 0, offsetof(Network, bond_name) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 5f12df907a..fe26720103 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -366,6 +366,7 @@ int network_load_one(Manager *manager, const char *filename) { .name = TAKE_PTR(name), .required_for_online = true, + .required_operstate_for_online = LINK_OPERSTATE_DEGRADED, .dhcp = ADDRESS_FAMILY_NO, .dhcp_use_ntp = true, .dhcp_use_dns = true, @@ -1671,3 +1672,46 @@ int config_parse_iaid(const char *unit, return 0; } + +int config_parse_required_for_online( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + Network *network = data; + LinkOperationalState s; + bool required = true; + int r; + + if (isempty(rvalue)) { + network->required_for_online = true; + network->required_operstate_for_online = LINK_OPERSTATE_DEGRADED; + return 0; + } + + s = link_operstate_from_string(rvalue); + if (s < 0) { + r = parse_boolean(rvalue); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Failed to parse %s= setting, ignoring assignment: %s", + lvalue, rvalue); + return 0; + } + + required = r; + s = LINK_OPERSTATE_DEGRADED; + } + + network->required_for_online = required; + network->required_operstate_for_online = s; + + return 0; +} diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 2f7b6133fd..2561bba1bc 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -241,6 +241,7 @@ struct Network { bool iaid_set; bool required_for_online; /* Is this network required to be considered online? */ + LinkOperationalState required_operstate_for_online; LLDPMode lldp_mode; /* LLDP reception */ LLDPEmit lldp_emit; /* LLDP transmission */ @@ -324,6 +325,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class); CONFIG_PARSER_PROTOTYPE(config_parse_ntp); CONFIG_PARSER_PROTOTYPE(config_parse_iaid); +CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online); /* Legacy IPv4LL support */ CONFIG_PARSER_PROTOTYPE(config_parse_ipv4ll); From 22eab27caa87088f59a8c0070958bb2a305dea6e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Mar 2019 14:45:17 +0900 Subject: [PATCH 06/10] sd-network: add sd_network_link_get_required_operstate_for_online() It reads $REQUIRED_OPER_STATE_FOR_ONLINE in serialized link data. --- src/libsystemd/sd-network/sd-network.c | 21 +++++++++++++++++++++ src/systemd/sd-network.h | 1 + 2 files changed, 22 insertions(+) diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index 812826fe3d..2d715043e1 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -164,6 +164,27 @@ _public_ int sd_network_link_get_required_for_online(int ifindex) { return parse_boolean(s); } +_public_ int sd_network_link_get_required_operstate_for_online(int ifindex, char **state) { + _cleanup_free_ char *s = NULL; + int r; + + assert_return(state, -EINVAL); + + r = network_link_get_string(ifindex, "REQUIRED_OPER_STATE_FOR_ONLINE", &s); + if (r < 0) { + if (r != -ENODATA) + return r; + + /* For compatibility, assuming degraded. */ + s = strdup("degraded"); + if (!s) + return -ENOMEM; + } + + *state = TAKE_PTR(s); + return 0; +} + _public_ int sd_network_link_get_llmnr(int ifindex, char **llmnr) { return network_link_get_string(ifindex, "LLMNR", llmnr); } diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index cc6bca9f5e..166c30185a 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -89,6 +89,7 @@ int sd_network_link_get_setup_state(int ifindex, char **state); * -ENODATA: networkd is not aware of the link */ int sd_network_link_get_operational_state(int ifindex, char **state); +int sd_network_link_get_required_operstate_for_online(int ifindex, char **state); /* Indicates whether the network is relevant to being online. * Possible return codes: From f023184e6dfbb2c238643e596a3a4b4a22dbf484 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Mar 2019 23:46:33 +0900 Subject: [PATCH 07/10] wait-online: support $REQUIRED_OPER_STATE_FOR_ONLINE= in state file This also make wait-online optionally take operstate in -i option, and adds '--operstate' option to wait-online which also takes operstate. Also, this contains huge refactoring for wait-online. --- src/network/wait-online/link.c | 80 ++++++++++++++----- src/network/wait-online/link.h | 5 +- src/network/wait-online/manager.c | 111 +++++++++++++++++--------- src/network/wait-online/manager.h | 10 ++- src/network/wait-online/wait-online.c | 94 ++++++++++++++++++---- 5 files changed, 223 insertions(+), 77 deletions(-) diff --git a/src/network/wait-online/link.c b/src/network/wait-online/link.c index 87d54fe654..201be477c2 100644 --- a/src/network/wait-online/link.c +++ b/src/network/wait-online/link.c @@ -10,6 +10,7 @@ int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { _cleanup_(link_freep) Link *l = NULL; + _cleanup_free_ char *n = NULL; int r; assert(m); @@ -23,30 +24,33 @@ int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { if (r < 0) return r; - l = new0(Link, 1); + n = strdup(ifname); + if (!n) + return -ENOMEM; + + l = new(Link, 1); if (!l) return -ENOMEM; - l->manager = m; - - l->ifname = strdup(ifname); - if (!l->ifname) - return -ENOMEM; + *l = (Link) { + .manager = m, + .ifname = TAKE_PTR(n), + .ifindex = ifindex, + .required_operstate = LINK_OPERSTATE_DEGRADED, + }; r = hashmap_put(m->links_by_name, l->ifname, l); if (r < 0) return r; - l->ifindex = ifindex; - r = hashmap_put(m->links, INT_TO_PTR(ifindex), l); if (r < 0) return r; if (ret) *ret = l; - l = NULL; + TAKE_PTR(l); return 0; } @@ -60,6 +64,7 @@ Link *link_free(Link *l) { hashmap_remove(l->manager->links_by_name, l->ifname); } + free(l->state); free(l->ifname); return mfree(l); } @@ -87,9 +92,8 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) { if (!new_ifname) return -ENOMEM; - hashmap_remove(l->manager->links_by_name, l->ifname); - free(l->ifname); - l->ifname = new_ifname; + assert_se(hashmap_remove(l->manager->links_by_name, l->ifname) == l); + free_and_replace(l->ifname, new_ifname); r = hashmap_put(l->manager->links_by_name, l->ifname, l); if (r < 0) @@ -100,17 +104,55 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) { } int link_update_monitor(Link *l) { + _cleanup_free_ char *operstate = NULL, *required_operstate = NULL, *state = NULL; + LinkOperationalState s; + int r, ret = 0; + assert(l); + assert(l->ifname); - l->required_for_online = sd_network_link_get_required_for_online(l->ifindex) != 0; + r = sd_network_link_get_required_for_online(l->ifindex); + if (r < 0) + ret = log_debug_errno(r, + "Failed to get whether link %s is required for online or not, " + "ignoring: %m", l->ifname); + else + l->required_for_online = r > 0; - l->operational_state = mfree(l->operational_state); + r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate); + if (r < 0) + ret = log_debug_errno(r, "Failed to get required operational state for link %s to be online, " + "ignoring: %m", l->ifname); + else { + s = link_operstate_from_string(required_operstate); + if (s < 0) + ret = log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse required operational state for link %s to be online, " + "ignoring: %m", l->ifname); + else + l->required_operstate = s; + } - sd_network_link_get_operational_state(l->ifindex, &l->operational_state); + r = sd_network_link_get_operational_state(l->ifindex, &operstate); + if (r < 0) + ret = log_debug_errno(r, "Failed to get operational state of link %s, ignoring: %m", + l->ifname); + else { + s = link_operstate_from_string(operstate); + if (s < 0) + ret = log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Failed to parse operational state of link %s, ignoring: %m", + l->ifname); + else + l->operational_state = s; + } - l->state = mfree(l->state); + r = sd_network_link_get_setup_state(l->ifindex, &state); + if (r < 0) + ret = log_debug_errno(r, "Failed to get setup state of link %s, ignoring: %m", + l->ifname); + else + free_and_replace(l->state, state); - sd_network_link_get_setup_state(l->ifindex, &l->state); - - return 0; + return ret; } diff --git a/src/network/wait-online/link.h b/src/network/wait-online/link.h index 57e8f12e03..07c2499e16 100644 --- a/src/network/wait-online/link.h +++ b/src/network/wait-online/link.h @@ -3,6 +3,8 @@ #include "sd-netlink.h" +#include "network-util.h" + typedef struct Link Link; typedef struct Manager Manager; @@ -14,7 +16,8 @@ struct Link { unsigned flags; bool required_for_online; - char *operational_state; + LinkOperationalState required_operstate; + LinkOperationalState operational_state; char *state; }; diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c index 67218b6db3..48f197e74f 100644 --- a/src/network/wait-online/manager.c +++ b/src/network/wait-online/manager.c @@ -13,7 +13,7 @@ #include "time-util.h" #include "util.h" -bool manager_ignore_link(Manager *m, Link *link) { +static bool manager_ignore_link(Manager *m, Link *link) { assert(m); assert(link); @@ -22,7 +22,7 @@ bool manager_ignore_link(Manager *m, Link *link) { return true; /* if interfaces are given on the command line, ignore all others */ - if (m->interfaces && !strv_contains(m->interfaces, link->ifname)) + if (m->interfaces && !hashmap_contains(m->interfaces, link->ifname)) return true; if (!link->required_for_online) @@ -32,45 +32,76 @@ bool manager_ignore_link(Manager *m, Link *link) { return strv_fnmatch(m->ignore, link->ifname, 0); } -bool manager_all_configured(Manager *m) { - Iterator i; - Link *l; - char **ifname; - bool one_ready = false; +static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) { + /* This returns the following: + * -EAGAIN: not processed by udev or networkd + * 0: operstate is not enough + * 1: online */ - /* wait for all the links given on the command line to appear */ - STRV_FOREACH(ifname, m->interfaces) { - l = hashmap_get(m->links_by_name, *ifname); - if (!l) { - log_debug("still waiting for %s", *ifname); - return false; - } + if (!l->state) { + log_debug("link %s has not yet been processed by udev", + l->ifname); + return -EAGAIN; } + if (STR_IN_SET(l->state, "configuring", "pending")) { + log_debug("link %s is being processed by networkd", + l->ifname); + return -EAGAIN; + } + + if (s < 0) + s = m->required_operstate >= 0 ? m->required_operstate : l->required_operstate; + + if (l->operational_state < s) { + log_debug("Operational state of link %s does not reach to %s", + l->ifname, link_operstate_to_string(s)); + return 0; + } + + return 1; +} + +bool manager_all_configured(Manager *m) { + bool one_ready = false; + Iterator i; + const char *ifname; + void *p; + Link *l; + int r; + + /* wait for all the links given on the command line to appear */ + HASHMAP_FOREACH_KEY(p, ifname, m->interfaces, i) { + LinkOperationalState s = PTR_TO_INT(p); + + l = hashmap_get(m->links_by_name, ifname); + if (!l) { + log_debug("still waiting for %s", ifname); + return false; + } + + if (manager_link_is_online(m, l, s) <= 0) + return false; + } + + if (!hashmap_isempty(m->interfaces)) + /* all interfaces given by the command line are online. */ + return true; + /* wait for all links networkd manages to be in admin state 'configured' - and at least one link to gain a carrier */ + * and at least one link to gain a carrier */ HASHMAP_FOREACH(l, m->links, i) { if (manager_ignore_link(m, l)) { log_info("ignoring: %s", l->ifname); continue; } - if (!l->state) { - log_debug("link %s has not yet been processed by udev", - l->ifname); + r = manager_link_is_online(m, l, _LINK_OPERSTATE_INVALID); + if (r < 0) return false; - } - - if (STR_IN_SET(l->state, "configuring", "pending")) { - log_debug("link %s is being processed by networkd", - l->ifname); - return false; - } - - if (l->operational_state && - STR_IN_SET(l->operational_state, "degraded", "routable")) + if (r > 0) /* we wait for at least one link to be ready, - regardless of who manages it */ + * regardless of who manages it */ one_ready = true; } @@ -120,15 +151,15 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void * r = link_new(m, &l, ifindex, ifname); if (r < 0) return log_error_errno(r, "Failed to create link object: %m"); - - r = link_update_monitor(l); - if (r < 0) - return log_error_errno(r, "Failed to initialize link object: %m"); } r = link_update_rtnl(l, mm); if (r < 0) - return log_warning_errno(r, "Failed to process RTNL link message: %m");; + log_warning_errno(r, "Failed to process RTNL link message, ignoring: %m"); + + r = link_update_monitor(l); + if (r < 0) + log_warning_errno(r, "Failed to initialize link object, ignoring: %m"); break; @@ -251,18 +282,22 @@ static int manager_network_monitor_listen(Manager *m) { return 0; } -int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout) { +int manager_new(Manager **ret, Hashmap *interfaces, char **ignore, + LinkOperationalState required_operstate, usec_t timeout) { _cleanup_(manager_freep) Manager *m = NULL; int r; assert(ret); - m = new0(Manager, 1); + m = new(Manager, 1); if (!m) return -ENOMEM; - m->interfaces = interfaces; - m->ignore = ignore; + *m = (Manager) { + .interfaces = interfaces, + .ignore = ignore, + .required_operstate = required_operstate, + }; r = sd_event_default(&m->event); if (r < 0) diff --git a/src/network/wait-online/manager.h b/src/network/wait-online/manager.h index 0fde272ddb..eb81e106e1 100644 --- a/src/network/wait-online/manager.h +++ b/src/network/wait-online/manager.h @@ -6,6 +6,7 @@ #include "sd-network.h" #include "hashmap.h" +#include "network-util.h" typedef struct Manager Manager; typedef struct Link Link; @@ -14,9 +15,12 @@ struct Manager { Hashmap *links; Hashmap *links_by_name; - char **interfaces; + /* Do not free the two members below. */ + Hashmap *interfaces; char **ignore; + LinkOperationalState required_operstate; + sd_netlink *rtnl; sd_event_source *rtnl_event_source; @@ -27,9 +31,9 @@ struct Manager { }; void manager_free(Manager *m); -int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout); +int manager_new(Manager **ret, Hashmap *interfaces, char **ignore, + LinkOperationalState required_operstate, usec_t timeout); DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); bool manager_all_configured(Manager *m); -bool manager_ignore_link(Manager *m, Link *link); diff --git a/src/network/wait-online/wait-online.c b/src/network/wait-online/wait-online.c index 71b6cf6b87..a5eddf3ca2 100644 --- a/src/network/wait-online/wait-online.c +++ b/src/network/wait-online/wait-online.c @@ -9,14 +9,16 @@ #include "manager.h" #include "pretty-print.h" #include "signal-util.h" +#include "socket-util.h" #include "strv.h" static bool arg_quiet = false; static usec_t arg_timeout = 120 * USEC_PER_SEC; -static char **arg_interfaces = NULL; +static Hashmap *arg_interfaces = NULL; static char **arg_ignore = NULL; +static LinkOperationalState arg_required_operstate = _LINK_OPERSTATE_INVALID; -STATIC_DESTRUCTOR_REGISTER(arg_interfaces, strv_freep); +STATIC_DESTRUCTOR_REGISTER(arg_interfaces, hashmap_free_free_keyp); STATIC_DESTRUCTOR_REGISTER(arg_ignore, strv_freep); static int help(void) { @@ -32,8 +34,11 @@ static int help(void) { " -h --help Show this help\n" " --version Print version string\n" " -q --quiet Do not show status information\n" - " -i --interface=INTERFACE Block until at least these interfaces have appeared\n" + " -i --interface=INTERFACE[:OPERSTATE]\n" + " Block until at least these interfaces have appeared\n" " --ignore=INTERFACE Don't take these interfaces into account\n" + " -o --operational-state=OPERSTATE\n" + " Required operational state\n" " --timeout=SECS Maximum time to wait for network connectivity\n" "\nSee the %s for details.\n" , program_invocation_short_name @@ -43,6 +48,52 @@ static int help(void) { return 0; } +static int parse_interface_with_operstate(const char *str) { + _cleanup_free_ char *ifname = NULL; + LinkOperationalState s; + const char *p; + int r; + + assert(str); + + p = strchr(str, ':'); + if (p) { + if (isempty(p + 1)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Operational state is empty."); + + s = link_operstate_from_string(p + 1); + if (s < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid operational state '%s'", p + 1); + + ifname = strndup(optarg, p - optarg); + } else { + s = _LINK_OPERSTATE_INVALID; + ifname = strdup(str); + } + if (!ifname) + return log_oom(); + + if (!ifname_valid(ifname)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid interface name '%s'", ifname); + + r = hashmap_ensure_allocated(&arg_interfaces, &string_hash_ops); + if (r < 0) + return log_oom(); + + r = hashmap_put(arg_interfaces, ifname, INT_TO_PTR(s)); + if (r < 0) + return log_error_errno(r, "Failed to store interface name: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Interface name %s is already specified", ifname); + + TAKE_PTR(ifname); + return 0; +} + static int parse_argv(int argc, char *argv[]) { enum { @@ -52,12 +103,13 @@ static int parse_argv(int argc, char *argv[]) { }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "quiet", no_argument, NULL, 'q' }, - { "interface", required_argument, NULL, 'i' }, - { "ignore", required_argument, NULL, ARG_IGNORE }, - { "timeout", required_argument, NULL, ARG_TIMEOUT }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "quiet", no_argument, NULL, 'q' }, + { "interface", required_argument, NULL, 'i' }, + { "ignore", required_argument, NULL, ARG_IGNORE }, + { "operational-state", required_argument, NULL, 'o' }, + { "timeout", required_argument, NULL, ARG_TIMEOUT }, {} }; @@ -66,7 +118,7 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0) + while ((c = getopt_long(argc, argv, "hi:qo:", options, NULL)) >= 0) switch (c) { @@ -82,9 +134,9 @@ static int parse_argv(int argc, char *argv[]) { return version(); case 'i': - if (strv_extend(&arg_interfaces, optarg) < 0) - return log_oom(); - + r = parse_interface_with_operstate(optarg); + if (r < 0) + return r; break; case ARG_IGNORE: @@ -93,11 +145,21 @@ static int parse_argv(int argc, char *argv[]) { break; + case 'o': { + LinkOperationalState s; + + s = link_operstate_from_string(optarg); + if (s < 0) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Invalid operational state '%s'", optarg); + + arg_required_operstate = s; + break; + } case ARG_TIMEOUT: r = parse_sec(optarg, &arg_timeout); if (r < 0) return r; - break; case '?': @@ -124,11 +186,11 @@ static int run(int argc, char *argv[]) { return r; if (arg_quiet) - log_set_max_level(LOG_WARNING); + log_set_max_level(LOG_ERR); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); - r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout); + r = manager_new(&m, arg_interfaces, arg_ignore, arg_required_operstate, arg_timeout); if (r < 0) return log_error_errno(r, "Could not create manager: %m"); From 8d6082e4dda2b90e26da95021bab73d68bd23786 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Mar 2019 23:47:29 +0900 Subject: [PATCH 08/10] man: update wait-online and RequiredForOnline= setting --- man/systemd-networkd-wait-online.service.xml | 46 +++++++++++++++++--- man/systemd.network.xml | 16 ++++--- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/man/systemd-networkd-wait-online.service.xml b/man/systemd-networkd-wait-online.service.xml index 95abf5b873..1b1bcf96fa 100644 --- a/man/systemd-networkd-wait-online.service.xml +++ b/man/systemd-networkd-wait-online.service.xml @@ -6,7 +6,8 @@ SPDX-License-Identifier: LGPL-2.1+ --> - + systemd-networkd-wait-online.service @@ -48,8 +49,8 @@ - - + INTERFACE:OPERSTATE + INTERFACE:OPERSTATE Network interface to wait for before deciding if the system is online. This is useful when a system has @@ -57,21 +58,53 @@ one is necessary to access some network resources. This option may be used more than once to wait for multiple network interfaces. When used, all other interfaces are ignored. + Optinally, required minimum operational state can be + specified after a colon :. Please see + networkctl1 + for possible operational states. If the operational state is not specified here, then + the value from RequiredForOnline= in the corresponding + .network file is used if present, and degraded otherwise. + - + INTERFACE + Network interfaces to be ignored when deciding if the system is online. By default, only the loopback interface is ignored. This option may be used more than once to ignore multiple network interfaces. + - + OPERSTATE + OPERSTATE + + Takes an operational state. Please see + networkctl1 + for possible operational states. If set, the specified value overrides + RequiredForOnline= settings in .network files. + But this does not override operational states specified in option. + + + + + SECS + Fail the service if the network is not online by the time the timeout elapses. A timeout of 0 disables the timeout. Defaults to 120 seconds. + + + + + + Suppress log messages. + + + + @@ -80,7 +113,8 @@ systemd1, systemd.service5, - systemd-networkd.service8 + systemd-networkd.service8, + networkctl1 diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 1a3d24aa76..0dd553adc1 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -255,15 +255,19 @@ RequiredForOnline= - Takes a boolean. When yes, the network is deemed - required when determining whether the system is online when running - systemd-networkd-wait-online. - When no, the network is ignored when checking for - online state. Defaults to yes. + Takes a boolean or operational state. Please see + networkctl1 + for possible operational states. When yes, the network is deemed required when + determining whether the system is online when running + systemd-networkd-wait-online. When no, the network is ignored + when checking for online state. When an operational state is set, yes is implied, + and this controls the operational state required for the network interface to be considered online. + Defaults to yes. + The network will be brought up normally in all cases, but in the event that there is no address being assigned by DHCP or the cable is not plugged in, the link will simply remain offline and be - skipped automatically by systemd-networkd-wait-online + skipped automatically by systemd-networkd-wait-online if RequiredForOnline=no. From e67ae9f5e60de4d3f969d06988954dbcdcf9bcae Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 6 Mar 2019 23:54:57 +0900 Subject: [PATCH 09/10] network: move log_link_debug() or friends to log-link.h --- src/network/networkd-link.h | 25 +------------------------ src/shared/log-link.h | 37 +++++++++++++++++++++++++++++++++++++ src/shared/meson.build | 1 + 3 files changed, 39 insertions(+), 24 deletions(-) create mode 100644 src/shared/log-link.h diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index c4e061ca13..e65246c87d 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -15,6 +15,7 @@ #include "sd-netlink.h" #include "list.h" +#include "log-link.h" #include "network-util.h" #include "set.h" @@ -179,30 +180,6 @@ uint32_t link_get_vrf_table(Link *link); uint32_t link_get_dhcp_route_table(Link *link); uint32_t link_get_ipv6_accept_ra_route_table(Link *link); -/* Macros which append INTERFACE= to the message */ - -#define log_link_full(link, level, error, ...) \ - ({ \ - const Link *_l = (link); \ - _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ - log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ - }) \ - -#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) -#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) - -#define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) -#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) -#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) -#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) -#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) - -#define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ -#define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname - #define ADDRESS_FMT_VAL(address) \ be32toh((address).s_addr) >> 24, \ (be32toh((address).s_addr) >> 16) & 0xFFu, \ diff --git a/src/shared/log-link.h b/src/shared/log-link.h new file mode 100644 index 0000000000..99efc0cbab --- /dev/null +++ b/src/shared/log-link.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ +#pragma once + +#include "log.h" + +/* + * The following macros append INTERFACE= to the message. + * The macros require a struct named 'Link' which contains 'char *ifname': + * + * typedef struct Link { + * char *ifname; + * } Link; + * + * See, network/networkd-link.h for example. + */ + +#define log_link_full(link, level, error, ...) \ + ({ \ + const Link *_l = (link); \ + (_l && _l->ifname) ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \ + log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + }) \ + +#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) +#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) +#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) +#define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) + +#define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ +#define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname diff --git a/src/shared/meson.build b/src/shared/meson.build index 1a5ba8c0f4..83a9df24cb 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -93,6 +93,7 @@ shared_sources = files(''' json.h lockfile-util.c lockfile-util.h + log-link.h logs-show.c logs-show.h loop-util.c From 07e1ffe4ae239ce7c8d92fa4c21ef7492c96dda7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 7 Mar 2019 00:16:54 +0900 Subject: [PATCH 10/10] wait-online: use log_link_debug() or friends --- src/network/wait-online/link.c | 24 +++++++++--------------- src/network/wait-online/link.h | 1 + src/network/wait-online/manager.c | 31 ++++++++++++++----------------- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/network/wait-online/link.c b/src/network/wait-online/link.c index 201be477c2..a13373f7d7 100644 --- a/src/network/wait-online/link.c +++ b/src/network/wait-online/link.c @@ -113,44 +113,38 @@ int link_update_monitor(Link *l) { r = sd_network_link_get_required_for_online(l->ifindex); if (r < 0) - ret = log_debug_errno(r, - "Failed to get whether link %s is required for online or not, " - "ignoring: %m", l->ifname); + ret = log_link_debug_errno(l, r, "Failed to determine whether the link is required for online or not, " + "ignoring: %m"); else l->required_for_online = r > 0; r = sd_network_link_get_required_operstate_for_online(l->ifindex, &required_operstate); if (r < 0) - ret = log_debug_errno(r, "Failed to get required operational state for link %s to be online, " - "ignoring: %m", l->ifname); + ret = log_link_debug_errno(l, r, "Failed to get required operational state, ignoring: %m"); else { s = link_operstate_from_string(required_operstate); if (s < 0) - ret = log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "Failed to parse required operational state for link %s to be online, " - "ignoring: %m", l->ifname); + ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), + "Failed to parse required operational state, ignoring: %m"); else l->required_operstate = s; } r = sd_network_link_get_operational_state(l->ifindex, &operstate); if (r < 0) - ret = log_debug_errno(r, "Failed to get operational state of link %s, ignoring: %m", - l->ifname); + ret = log_link_debug_errno(l, r, "Failed to get operational state, ignoring: %m"); else { s = link_operstate_from_string(operstate); if (s < 0) - ret = log_debug_errno(SYNTHETIC_ERRNO(EINVAL), - "Failed to parse operational state of link %s, ignoring: %m", - l->ifname); + ret = log_link_debug_errno(l, SYNTHETIC_ERRNO(EINVAL), + "Failed to parse operational state, ignoring: %m"); else l->operational_state = s; } r = sd_network_link_get_setup_state(l->ifindex, &state); if (r < 0) - ret = log_debug_errno(r, "Failed to get setup state of link %s, ignoring: %m", - l->ifname); + ret = log_link_debug_errno(l, r, "Failed to get setup state, ignoring: %m"); else free_and_replace(l->state, state); diff --git a/src/network/wait-online/link.h b/src/network/wait-online/link.h index 07c2499e16..d58129dfe8 100644 --- a/src/network/wait-online/link.h +++ b/src/network/wait-online/link.h @@ -3,6 +3,7 @@ #include "sd-netlink.h" +#include "log-link.h" #include "network-util.h" typedef struct Link Link; diff --git a/src/network/wait-online/manager.c b/src/network/wait-online/manager.c index 48f197e74f..eb551f116a 100644 --- a/src/network/wait-online/manager.c +++ b/src/network/wait-online/manager.c @@ -38,24 +38,21 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalState s) { * 0: operstate is not enough * 1: online */ - if (!l->state) { - log_debug("link %s has not yet been processed by udev", - l->ifname); - return -EAGAIN; - } + if (!l->state) + return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN), + "link has not yet been processed by udev"); - if (STR_IN_SET(l->state, "configuring", "pending")) { - log_debug("link %s is being processed by networkd", - l->ifname); - return -EAGAIN; - } + if (STR_IN_SET(l->state, "configuring", "pending")) + return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN), + "link is being processed by networkd"); if (s < 0) s = m->required_operstate >= 0 ? m->required_operstate : l->required_operstate; if (l->operational_state < s) { - log_debug("Operational state of link %s does not reach to %s", - l->ifname, link_operstate_to_string(s)); + log_link_debug(l, "Operational state '%s' is below '%s'", + link_operstate_to_string(l->operational_state), + link_operstate_to_string(s)); return 0; } @@ -92,7 +89,7 @@ bool manager_all_configured(Manager *m) { * and at least one link to gain a carrier */ HASHMAP_FOREACH(l, m->links, i) { if (manager_ignore_link(m, l)) { - log_info("ignoring: %s", l->ifname); + log_link_info(l, "link is ignored"); continue; } @@ -155,17 +152,17 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void * r = link_update_rtnl(l, mm); if (r < 0) - log_warning_errno(r, "Failed to process RTNL link message, ignoring: %m"); + log_link_warning_errno(l, r, "Failed to process RTNL link message, ignoring: %m"); r = link_update_monitor(l); if (r < 0) - log_warning_errno(r, "Failed to initialize link object, ignoring: %m"); + log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m"); break; case RTM_DELLINK: if (l) { - log_debug("Removing link %i", l->ifindex); + log_link_debug(l, "Removing link"); link_free(l); } @@ -248,7 +245,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void * HASHMAP_FOREACH(l, m->links, i) { r = link_update_monitor(l); if (r < 0) - log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); + log_link_warning_errno(l, r, "Failed to update monitor information: %m"); } if (manager_all_configured(m))