Merge pull request #19163 from sipraga/online-if-required

network: introduce an online state that respects RequiredForOnline=
This commit is contained in:
Yu Watanabe
2021-05-19 23:08:18 +09:00
committed by GitHub
17 changed files with 225 additions and 35 deletions

View File

@@ -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>

View File

@@ -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>
@@ -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>

View File

@@ -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;
}
@@ -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;

View File

@@ -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_;
@@ -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;

View File

@@ -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;
@@ -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);
}

View File

@@ -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;
@@ -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;
@@ -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");
@@ -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)
@@ -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;
@@ -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();
@@ -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);

View File

@@ -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;

View File

@@ -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(
@@ -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),

View File

@@ -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);

View File

@@ -202,6 +202,7 @@ void link_update_operstate(Link *link, bool also_update_master) {
LinkOperationalState operstate;
LinkCarrierState carrier_state;
LinkAddressState ipv4_address_state, ipv6_address_state, address_state;
LinkOnlineState online_state;
_cleanup_strv_free_ char **p = NULL;
uint8_t ipv4_scope = RT_SCOPE_NOWHERE, ipv6_scope = RT_SCOPE_NOWHERE;
bool changed = false;
@@ -277,6 +278,38 @@ void link_update_operstate(Link *link, bool also_update_master) {
else
operstate = LINK_OPERSTATE_ENSLAVED;
/* Only determine online state for managed links with RequiredForOnline=yes */
if (!link->network || !link->network->required_for_online)
online_state = _LINK_ONLINE_STATE_INVALID;
else if (operstate < link->network->required_operstate_for_online.min ||
operstate > link->network->required_operstate_for_online.max)
online_state = LINK_ONLINE_STATE_OFFLINE;
else {
AddressFamily required_family = link->network->required_family_for_online;
bool needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
bool needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
/* The operational state is within the range required for online.
* If a particular address family is also required, we might revert
* to offline in the blocks below.
*/
online_state = LINK_ONLINE_STATE_ONLINE;
if (link->network->required_operstate_for_online.min >= LINK_OPERSTATE_DEGRADED) {
if (needs_ipv4 && ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED)
online_state = LINK_ONLINE_STATE_OFFLINE;
if (needs_ipv6 && ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED)
online_state = LINK_ONLINE_STATE_OFFLINE;
}
if (link->network->required_operstate_for_online.min >= LINK_OPERSTATE_ROUTABLE) {
if (needs_ipv4 && ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE)
online_state = LINK_ONLINE_STATE_OFFLINE;
if (needs_ipv6 && ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE)
online_state = LINK_ONLINE_STATE_OFFLINE;
}
}
if (link->carrier_state != carrier_state) {
link->carrier_state = carrier_state;
changed = true;
@@ -312,6 +345,13 @@ void link_update_operstate(Link *link, bool also_update_master) {
log_oom();
}
if (link->online_state != online_state) {
link->online_state = online_state;
changed = true;
if (strv_extend(&p, "OnlineState") < 0)
log_oom();
}
if (p)
link_send_changed_strv(link, p);
if (changed)
@@ -2330,6 +2370,7 @@ static int link_initialized_and_synced(Link *link) {
}
link->network = network_ref(network);
link_update_operstate(link, false);
link_dirty(link);
}
@@ -2466,6 +2507,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
*link = (Link) {
.n_ref = 1,
.state = LINK_STATE_PENDING,
.online_state = _LINK_ONLINE_STATE_INVALID,
.ifindex = ifindex,
.iftype = iftype,
.ifname = TAKE_PTR(ifname),

View File

@@ -77,6 +77,7 @@ typedef struct Link {
LinkAddressState address_state;
LinkAddressState ipv4_address_state;
LinkAddressState ipv6_address_state;
LinkOnlineState online_state;
unsigned address_label_messages;
unsigned static_address_messages;

View File

@@ -271,6 +271,7 @@ const sd_bus_vtable manager_vtable[] = {
SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Manager, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Manager, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("OnlineState", "s", property_get_online_state, offsetof(Manager, online_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_METHOD_WITH_ARGS("ListLinks",
SD_BUS_NO_ARGS,

View File

@@ -380,6 +380,7 @@ int manager_new(Manager **ret) {
*m = (Manager) {
.speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
.online_state = _LINK_ONLINE_STATE_INVALID,
.manage_foreign_routes = true,
.manage_foreign_rules = true,
.ethtool_fd = -1,

View File

@@ -42,6 +42,7 @@ struct Manager {
LinkAddressState address_state;
LinkAddressState ipv4_address_state;
LinkAddressState ipv6_address_state;
LinkOnlineState online_state;
Hashmap *links;
Hashmap *netdevs;

View File

@@ -105,11 +105,13 @@ static int ordered_set_put_in4_addrv(
int manager_save(Manager *m) {
_cleanup_ordered_set_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
const char *operstate_str, *carrier_state_str, *address_state_str, *ipv4_address_state_str, *ipv6_address_state_str;
const char *operstate_str, *carrier_state_str, *address_state_str, *ipv4_address_state_str, *ipv6_address_state_str, *online_state_str;
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
LinkAddressState ipv4_address_state = LINK_ADDRESS_STATE_OFF, ipv6_address_state = LINK_ADDRESS_STATE_OFF,
address_state = LINK_ADDRESS_STATE_OFF;
LinkOnlineState online_state;
size_t links_offline = 0, links_online = 0;
_cleanup_(unlink_and_freep) char *temp_path = NULL;
_cleanup_strv_free_ char **p = NULL;
_cleanup_fclose_ FILE *f = NULL;
@@ -134,6 +136,13 @@ int manager_save(Manager *m) {
if (!link->network)
continue;
if (link->network->required_for_online) {
if (link->online_state == LINK_ONLINE_STATE_OFFLINE)
links_offline++;
else if (link->online_state == LINK_ONLINE_STATE_ONLINE)
links_online++;
}
/* First add the static configured entries */
if (link->n_dns != UINT_MAX)
r = ordered_set_put_dns_servers(&dns, link->ifindex, link->dns, link->n_dns);
@@ -215,6 +224,10 @@ int manager_save(Manager *m) {
if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED)
carrier_state = LINK_CARRIER_STATE_CARRIER;
online_state = links_online > 0 ?
(links_offline > 0 ? LINK_ONLINE_STATE_PARTIAL : LINK_ONLINE_STATE_ONLINE) :
(links_offline > 0 ? LINK_ONLINE_STATE_OFFLINE : _LINK_ONLINE_STATE_INVALID);
operstate_str = link_operstate_to_string(operstate);
assert(operstate_str);
@@ -245,6 +258,10 @@ int manager_save(Manager *m) {
"IPV6_ADDRESS_STATE=%s\n",
operstate_str, carrier_state_str, address_state_str, ipv4_address_state_str, ipv6_address_state_str);
online_state_str = link_online_state_to_string(online_state);
if (online_state_str)
fprintf(f, "ONLINE_STATE=%s\n", online_state_str);
ordered_set_print(f, "DNS=", dns);
ordered_set_print(f, "NTP=", ntp);
ordered_set_print(f, "SIP=", sip);
@@ -291,6 +308,12 @@ int manager_save(Manager *m) {
log_oom();
}
if (m->online_state != online_state) {
m->online_state = online_state;
if (strv_extend(&p, "OnlineState") < 0)
log_oom();
}
if (p) {
r = manager_send_changed_strv(m, p);
if (r < 0)
@@ -445,9 +468,13 @@ int link_save(Link *link) {
if (link->network) {
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
const char *dhcp_domainname = NULL, *p;
const char *dhcp_domainname = NULL, *online_state, *p;
bool space;
online_state = link_online_state_to_string(link->online_state);
if (online_state)
fprintf(f, "ONLINE_STATE=%s\n", online_state);
fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
yes_no(link->network->required_for_online));

View File

@@ -53,6 +53,7 @@ int sd_network_get_carrier_state(char **state);
int sd_network_get_address_state(char **state);
int sd_network_get_ipv4_address_state(char **state);
int sd_network_get_ipv6_address_state(char **state);
int sd_network_get_online_state(char **state);
/* Get DNS entries for all links. These are string representations of
* IP addresses */
@@ -99,6 +100,7 @@ int sd_network_link_get_carrier_state(int ifindex, char **state);
int sd_network_link_get_address_state(int ifindex, char **state);
int sd_network_link_get_ipv4_address_state(int ifindex, char **state);
int sd_network_link_get_ipv6_address_state(int ifindex, char **state);
int sd_network_link_get_online_state(int ifindex, char **state);
/* Indicates whether the network is relevant to being online.
* Possible return codes:

View File

@@ -412,6 +412,7 @@ DHCP={dhcp_mode}
out = subprocess.check_output(['networkctl', '-n', '0', 'status', self.iface])
self.assertRegex(out, br'Type:\s+ether')
self.assertRegex(out, br'State:\s+routable.*configured')
self.assertRegex(out, br'Online state:\s+online')
self.assertRegex(out, br'Address:\s+192.168.5.\d+')
if ipv6:
self.assertRegex(out, br'2600::')