Skip to content

Commit f483155

Browse files
yuwatabluca
authored andcommitted
wait-online: exit with success when all interfaces are ready or unmanaged
Previously, when neither '--any' nor '--interface' options specified, at least one of the interfaces must be in configured state. This patch makes wait-online exit with success even if all interfaces are in unmanaged state. This may break backward compatibility in a rare situation. But in most cases, this typically not change anything, as at least one interface is managed by networkd.service when it is enabled. This is mostly for making wait-online gracefully handle the case that networkd.service and wait-online.service are enabled by mistake. In such situation, all interfaces are typically not managed. Fixes #25813. (cherry picked from commit ab3aed4)
1 parent 2ea9d28 commit f483155

File tree

1 file changed

+50
-57
lines changed

1 file changed

+50
-57
lines changed

src/network/wait-online/manager.c

Lines changed: 50 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
4141
assert(l);
4242

4343
/* This returns the following:
44-
* -EAGAIN: not processed by udev or networkd
45-
* 0: operstate is not enough
46-
* 1: online */
44+
* -EAGAIN : not processed by udev
45+
* -EBUSY : being processed by networkd
46+
* -EADDRNOTAVAIL: requested conditions (operstate and/or addresses) are not satisfied
47+
* false : unmanaged
48+
* true : online */
4749

4850
if (!l->state || streq(l->state, "pending"))
4951
/* If no state string exists, networkd (and possibly also udevd) has not detected the
@@ -59,13 +61,13 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
5961
/* If the link is in unmanaged state, then ignore the interface unless the interface is
6062
* specified in '--interface/-i' option. */
6163
if (!hashmap_contains(m->command_line_interfaces_by_name, l->ifname)) {
62-
log_link_debug(l, "link is not managed by networkd (yet?).");
63-
return 0;
64+
log_link_debug(l, "link is not managed by networkd.");
65+
return false;
6466
}
6567

6668
} else if (!streq(l->state, "configured"))
6769
/* If the link is in non-configured state, return negative value here. */
68-
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EAGAIN),
70+
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EBUSY),
6971
"link is being processed by networkd: setup state is %s.",
7072
l->state);
7173

@@ -77,84 +79,75 @@ static int manager_link_is_online(Manager *m, Link *l, LinkOperationalStateRange
7779
s.max = m->required_operstate.max >= 0 ? m->required_operstate.max
7880
: l->required_operstate.max;
7981

80-
if (l->operational_state < s.min || l->operational_state > s.max) {
81-
log_link_debug(l, "Operational state '%s' is not in range ['%s':'%s']",
82-
link_operstate_to_string(l->operational_state),
83-
link_operstate_to_string(s.min), link_operstate_to_string(s.max));
84-
return 0;
85-
}
82+
if (l->operational_state < s.min || l->operational_state > s.max)
83+
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
84+
"Operational state '%s' is not in range ['%s':'%s']",
85+
link_operstate_to_string(l->operational_state),
86+
link_operstate_to_string(s.min), link_operstate_to_string(s.max));
8687

8788
required_family = m->required_family > 0 ? m->required_family : l->required_family;
8889
needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
8990
needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
9091

9192
if (s.min < LINK_OPERSTATE_ROUTABLE) {
92-
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED) {
93-
log_link_debug(l, "No routable or link-local IPv4 address is configured.");
94-
return 0;
95-
}
93+
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED)
94+
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
95+
"No routable or link-local IPv4 address is configured.");
9696

97-
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED) {
98-
log_link_debug(l, "No routable or link-local IPv6 address is configured.");
99-
return 0;
100-
}
97+
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED)
98+
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
99+
"No routable or link-local IPv6 address is configured.");
101100
} else {
102-
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE) {
103-
log_link_debug(l, "No routable IPv4 address is configured.");
104-
return 0;
105-
}
101+
if (needs_ipv4 && l->ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE)
102+
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
103+
"No routable IPv4 address is configured.");
106104

107-
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE) {
108-
log_link_debug(l, "No routable IPv6 address is configured.");
109-
return 0;
110-
}
105+
if (needs_ipv6 && l->ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE)
106+
return log_link_debug_errno(l, SYNTHETIC_ERRNO(EADDRNOTAVAIL),
107+
"No routable IPv6 address is configured.");
111108
}
112109

113110
log_link_debug(l, "link is configured by networkd and online.");
114-
return 1;
111+
return true;
115112
}
116113

117114
bool manager_configured(Manager *m) {
118-
bool one_ready = false;
119-
const char *ifname;
120115
Link *l;
121116
int r;
122117

123118
if (!hashmap_isempty(m->command_line_interfaces_by_name)) {
124119
LinkOperationalStateRange *range;
120+
const char *ifname;
125121

126122
/* wait for all the links given on the command line to appear */
127123
HASHMAP_FOREACH_KEY(range, ifname, m->command_line_interfaces_by_name) {
128124

129125
l = hashmap_get(m->links_by_name, ifname);
130-
if (!l && range->min == LINK_OPERSTATE_MISSING) {
131-
one_ready = true;
132-
continue;
133-
}
134-
135126
if (!l) {
136-
log_debug("still waiting for %s", ifname);
137-
if (!m->any)
138-
return false;
139-
continue;
140-
}
141-
142-
if (manager_link_is_online(m, l, *range) <= 0) {
143-
if (!m->any)
144-
return false;
127+
if (range->min == LINK_OPERSTATE_MISSING) {
128+
if (m->any)
129+
return true;
130+
} else {
131+
log_debug("still waiting for %s", ifname);
132+
if (!m->any)
133+
return false;
134+
}
145135
continue;
146136
}
147137

148-
one_ready = true;
138+
r = manager_link_is_online(m, l, *range);
139+
if (r <= 0 && !m->any)
140+
return false;
141+
if (r > 0 && m->any)
142+
return true;
149143
}
150144

151-
/* all interfaces given by the command line are online, or
152-
* one of the specified interfaces is online. */
153-
return one_ready;
145+
/* With '--any' : no interface is ready
146+
* Without '--any': all interfaces are ready */
147+
return !m->any;
154148
}
155149

156-
/* wait for all links networkd manages to be in admin state 'configured'
157-
* and at least one link to gain a carrier */
150+
/* wait for all links networkd manages */
158151
HASHMAP_FOREACH(l, m->links_by_index) {
159152
if (manager_ignore_link(m, l)) {
160153
log_link_debug(l, "link is ignored");
@@ -164,15 +157,15 @@ bool manager_configured(Manager *m) {
164157
r = manager_link_is_online(m, l,
165158
(LinkOperationalStateRange) { _LINK_OPERSTATE_INVALID,
166159
_LINK_OPERSTATE_INVALID });
167-
if (r < 0 && !m->any)
160+
if (r < 0 && !m->any) /* Unlike the above loop, unmanaged interfaces are ignored here. */
168161
return false;
169-
if (r > 0)
170-
/* we wait for at least one link to be ready,
171-
* regardless of who manages it */
172-
one_ready = true;
162+
if (r > 0 && m->any)
163+
return true;
173164
}
174165

175-
return one_ready;
166+
/* With '--any' : no interface is ready
167+
* Without '--any': all interfaces are ready or unmanaged */
168+
return !m->any;
176169
}
177170

178171
static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) {

0 commit comments

Comments
 (0)