Skip to content

Commit

Permalink
Merge pull request systemd#19163 from sipraga/online-if-required
Browse files Browse the repository at this point in the history
network: introduce an online state that respects RequiredForOnline=
  • Loading branch information
yuwata committed May 19, 2021
2 parents a9833ed + 7e59cfe commit 6db7b53
Show file tree
Hide file tree
Showing 17 changed files with 225 additions and 35 deletions.
48 changes: 40 additions & 8 deletions man/networkctl.xml
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,46 @@

<para>Produces output similar to:
<programlisting>
● State: routable
Address: 10.193.76.5 on eth0
192.168.122.1 on virbr0
169.254.190.105 on eth0
fe80::5054:aa:bbbb:cccc on eth0
Gateway: 10.193.11.1 (CISCO SYSTEMS, INC.) on eth0
DNS: 8.8.8.8
8.8.4.4</programlisting></para>
● State: routable
Online state: online
Address: 10.193.76.5 on eth0
192.168.122.1 on virbr0
169.254.190.105 on eth0
fe80::5054:aa:bbbb:cccc on eth0
Gateway: 10.193.11.1 (CISCO SYSTEMS, INC.) on eth0
DNS: 8.8.8.8
8.8.4.4</programlisting></para>

<para>In the overall network status, the online state depends on the individual online state of all
required links. Managed links are required for online by default. In this case, the online state is
one of the following:
<variablelist>
<varlistentry>
<term>unknown</term>
<listitem>
<para>all links have unknown online status (i.e. there are no required links)</para>
</listitem>
</varlistentry>
<varlistentry>
<term>offline</term>
<listitem>
<para>all required links are offline</para>
</listitem>
</varlistentry>
<varlistentry>
<term>partial</term>
<listitem>
<para>some, but not all, required links are online</para>
</listitem>
</varlistentry>
<varlistentry>
<term>online</term>
<listitem>
<para>all required links are online</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</listitem>

</varlistentry>
Expand Down
20 changes: 10 additions & 10 deletions man/systemd.network.xml
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@
<para>Takes a boolean or a minimum operational state and an optional maximum operational state.
Please see <citerefentry><refentrytitle>networkctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
for possible operational states. When <literal>yes</literal>, the network is deemed required when
determining whether the system is online when running
<command>systemd-networkd-wait-online</command>. When <literal>no</literal>, the network is ignored
when checking for online state. When a minimum operational state and an optional maximum operational
determining whether the system is online (including when running
<command>systemd-networkd-wait-online</command>). When <literal>no</literal>, the network is ignored
when determining the online state. When a minimum operational state and an optional maximum operational
state are set, <literal>yes</literal> is implied, and this controls the minimum and maximum
operational state required for the network interface to be considered online.
Defaults to <literal>yes</literal>.</para>
Expand All @@ -232,13 +232,13 @@
<varlistentry>
<term><varname>RequiredFamilyForOnline=</varname></term>
<listitem>
<para>Specifies an address family. When specified,
<command>systemd-networkd-wait-online</command> waits for at least one routable or link-local
IP address in the family should be configured on the link. Takes one of
<literal>ipv4</literal>, <literal>ipv6</literal>, <literal>both</literal>, or
<literal>any</literal>. Defaults to <literal>any</literal>. Note that this will be used only
when <varname>RequiredForOnline=</varname> is true, or its minimum operational state is
<literal>degraded</literal> or above. Otherwise, it will be ignored.</para>
<para>Takes an address family. When specified, an IP address in the given family is deemed required
when determining whether the link is online (including when running
<command>systemd-networkd-wait-online</command>). Takes one of <literal>ipv4</literal>,
<literal>ipv6</literal>, <literal>both</literal>, or <literal>any</literal>. Defaults to
<literal>any</literal>. Note that this option has no effect if
<literal>RequiredForOnline=no</literal>, or if <literal>RequiredForOnline=</literal> specifies a
minimum operational state below <literal>degraded</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
Expand Down
40 changes: 31 additions & 9 deletions src/libsystemd/sd-network/network-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,34 @@
#include "strv.h"

bool network_is_online(void) {
_cleanup_free_ char *carrier_state = NULL, *addr_state = NULL;
_cleanup_free_ char *online_state = NULL;
LinkOnlineState state;
int r;

r = sd_network_get_carrier_state(&carrier_state);
if (r < 0) /* if we don't know anything, we consider the system online */
return true;
r = sd_network_get_online_state(&online_state);
if (r < 0)
state = _LINK_ONLINE_STATE_INVALID;
else
state = link_online_state_from_string(online_state);

r = sd_network_get_address_state(&addr_state);
if (r < 0) /* if we don't know anything, we consider the system online */
if (state >= LINK_ONLINE_STATE_PARTIAL)
return true;
else if (state < 0) {
_cleanup_free_ char *carrier_state = NULL, *addr_state = NULL;

if (STR_IN_SET(carrier_state, "degraded-carrier", "carrier") &&
STR_IN_SET(addr_state, "routable", "degraded"))
return true;
r = sd_network_get_carrier_state(&carrier_state);
if (r < 0) /* if we don't know anything, we consider the system online */
return true;

r = sd_network_get_address_state(&addr_state);
if (r < 0) /* if we don't know anything, we consider the system online */
return true;

/* we don't know the online state for certain, so make an educated guess */
if (STR_IN_SET(carrier_state, "degraded-carrier", "carrier") &&
STR_IN_SET(addr_state, "routable", "degraded"))
return true;
}

return false;
}
Expand Down Expand Up @@ -73,6 +87,14 @@ static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = {

DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState);

static const char *const link_online_state_table[_LINK_ONLINE_STATE_MAX] = {
[LINK_ONLINE_STATE_OFFLINE] = "offline",
[LINK_ONLINE_STATE_PARTIAL] = "partial",
[LINK_ONLINE_STATE_ONLINE] = "online",
};

DEFINE_STRING_TABLE_LOOKUP(link_online_state, LinkOnlineState);

int parse_operational_state_range(const char *str, LinkOperationalStateRange *out) {
LinkOperationalStateRange range = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
_cleanup_free_ const char *min = NULL;
Expand Down
11 changes: 11 additions & 0 deletions src/libsystemd/sd-network/network-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ typedef enum LinkAddressState {
_LINK_ADDRESS_STATE_INVALID = -EINVAL,
} LinkAddressState;

typedef enum LinkOnlineState {
LINK_ONLINE_STATE_OFFLINE,
LINK_ONLINE_STATE_PARTIAL,
LINK_ONLINE_STATE_ONLINE,
_LINK_ONLINE_STATE_MAX,
_LINK_ONLINE_STATE_INVALID = -EINVAL,
} LinkOnlineState;

const char* link_operstate_to_string(LinkOperationalState s) _const_;
LinkOperationalState link_operstate_from_string(const char *s) _pure_;

Expand All @@ -66,6 +74,9 @@ AddressFamily link_required_address_family_from_string(const char *s) _pure_;
const char* link_address_state_to_string(LinkAddressState s) _const_;
LinkAddressState link_address_state_from_string(const char *s) _pure_;

const char* link_online_state_to_string(LinkOnlineState s) _const_;
LinkOnlineState link_online_state_from_string(const char *s) _pure_;

typedef struct LinkOperationalStateRange {
LinkOperationalState min;
LinkOperationalState max;
Expand Down
8 changes: 8 additions & 0 deletions src/libsystemd/sd-network/sd-network.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ _public_ int sd_network_get_ipv6_address_state(char **state) {
return network_get_string("IPV6_ADDRESS_STATE", state);
}

_public_ int sd_network_get_online_state(char **state) {
return network_get_string("ONLINE_STATE", state);
}

static int network_get_strv(const char *key, char ***ret) {
_cleanup_strv_free_ char **a = NULL;
_cleanup_free_ char *s = NULL;
Expand Down Expand Up @@ -204,6 +208,10 @@ _public_ int sd_network_link_get_ipv6_address_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "IPV6_ADDRESS_STATE", state);
}

_public_ int sd_network_link_get_online_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "ONLINE_STATE", state);
}

_public_ int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid) {
return network_link_get_string(ifindex, "DHCP6_CLIENT_IAID", iaid);
}
Expand Down
47 changes: 42 additions & 5 deletions src/network/networkctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,25 @@ static void setup_state_to_color(const char *state, const char **on, const char
}
}

static void online_state_to_color(const char *state, const char **on, const char **off) {
if (streq_ptr(state, "online")) {
if (on)
*on = ansi_highlight_green();
if (off)
*off = ansi_normal();
} else if (streq_ptr(state, "partial")) {
if (on)
*on = ansi_highlight_yellow();
if (off)
*off = ansi_normal();
} else {
if (on)
*on = "";
if (off)
*off = "";
}
}

typedef struct VxLanInfo {
uint32_t vni;
uint32_t link;
Expand Down Expand Up @@ -1514,9 +1533,9 @@ static int link_status_one(

_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL;
_cleanup_free_ char *t = NULL, *network = NULL, *iaid = NULL, *duid = NULL,
*setup_state = NULL, *operational_state = NULL, *lease_file = NULL, *activation_policy = NULL;
*setup_state = NULL, *operational_state = NULL, *online_state = NULL, *lease_file = NULL, *activation_policy = NULL;
const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL,
*on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup;
*on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup, *on_color_online;
_cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
_cleanup_(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
_cleanup_(table_unrefp) Table *table = NULL;
Expand All @@ -1529,6 +1548,9 @@ static int link_status_one(
(void) sd_network_link_get_operational_state(info->ifindex, &operational_state);
operational_state_to_color(info->name, operational_state, &on_color_operational, &off_color_operational);

(void) sd_network_link_get_online_state(info->ifindex, &online_state);
online_state_to_color(online_state, &on_color_online, NULL);

r = sd_network_link_get_setup_state(info->ifindex, &setup_state);
if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */
setup_state = strdup("unmanaged");
Expand Down Expand Up @@ -1613,6 +1635,14 @@ static int link_status_one(
if (r < 0)
return table_log_add_error(r);

r = table_add_many(table,
TABLE_EMPTY,
TABLE_STRING, "Online state:",
TABLE_STRING, online_state ?: "unknown",
TABLE_SET_COLOR, on_color_online);
if (r < 0)
return table_log_add_error(r);

strv_sort(info->alternative_names);
r = dump_list(table, "Alternative Names:", info->alternative_names);
if (r < 0)
Expand Down Expand Up @@ -2272,9 +2302,9 @@ static int link_status_one(
}

static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
_cleanup_free_ char *operational_state = NULL;
_cleanup_free_ char *operational_state = NULL, *online_state = NULL;
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
const char *on_color_operational;
const char *on_color_operational, *on_color_online;
_cleanup_(table_unrefp) Table *table = NULL;
TableCell *cell;
int r;
Expand All @@ -2284,6 +2314,9 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
(void) sd_network_get_operational_state(&operational_state);
operational_state_to_color(NULL, operational_state, &on_color_operational, NULL);

(void) sd_network_get_online_state(&online_state);
online_state_to_color(online_state, &on_color_online, NULL);

table = table_new("dot", "key", "value");
if (!table)
return log_oom();
Expand All @@ -2305,7 +2338,11 @@ static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) {
TABLE_SET_COLOR, on_color_operational,
TABLE_STRING, "State:",
TABLE_STRING, strna(operational_state),
TABLE_SET_COLOR, on_color_operational);
TABLE_SET_COLOR, on_color_operational,
TABLE_EMPTY,
TABLE_STRING, "Online state:",
TABLE_STRING, online_state ?: "unknown",
TABLE_SET_COLOR, on_color_online);
if (r < 0)
return table_log_add_error(r);

Expand Down
3 changes: 2 additions & 1 deletion src/network/networkd-json.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ int link_build_json(Link *link, JsonVariant **ret) {
JSON_BUILD_PAIR("CarrierState", JSON_BUILD_STRING(link_carrier_state_to_string(link->carrier_state))),
JSON_BUILD_PAIR("AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->address_state))),
JSON_BUILD_PAIR("IPv4AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv4_address_state))),
JSON_BUILD_PAIR("IPv6AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv6_address_state)))));
JSON_BUILD_PAIR("IPv6AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv6_address_state))),
JSON_BUILD_PAIR("OnlineState", JSON_BUILD_STRING(link_online_state_to_string(link->online_state)))));
if (r < 0)
return r;

Expand Down
2 changes: 2 additions & 0 deletions src/network/networkd-link-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_carrier_state, link_carrier_state, LinkCarrierState);
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_address_state, link_address_state, LinkAddressState);
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_online_state, link_online_state, LinkOnlineState);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);

static int property_get_bit_rates(
Expand Down Expand Up @@ -716,6 +717,7 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Link, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Link, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("OnlineState", "s", property_get_online_state, offsetof(Link, online_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),

Expand Down
1 change: 1 addition & 0 deletions src/network/networkd-link-bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ int link_send_changed(Link *link, const char *property, ...) _sentinel_;
int property_get_operational_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int property_get_carrier_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int property_get_address_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int property_get_online_state(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);

int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error);
Expand Down
Loading

0 comments on commit 6db7b53

Please sign in to comment.