Skip to content

Commit bcdcc59

Browse files
sipragayuwata
authored andcommitted
network: add an online state for links and manager
Add a new state of type LinkOnlineState which indicates whether a link is online or not. The state is also used by networkd's manager to expose the overall online state of the system. The possible states are: offline the link (or system) is offline partial at least one required link is online (see below) online all required links are online For links, a link is defined to be "online" if: - it is managed; and - its operational state is within the range defined by RequiredForOnline=; and - it has an IPv4 address if RequiredFamilyForOnline=ipv4 or =both; and - it has an IPv6 address if RequiredFamilyForOnline=ipv6 or =both. A link is defined to be "offline" if: - it is managed; and - it is not online, i.e. its operational state is not within the range defined by RequiredForOnline=, and/or it is missing an IP address in a required address family. Otherwise, the link online state is undefined (represented internally as _LINK_ONLINE_STATUS_INVALID or -EINVAL). Put another way, networkd will only offer a meaningful online state for managed links where RequiredForOnline=yes. For the manager, the online state is a function of the online state of all links which are requried for online, i.e. RequiredForOnline=yes. If all required links are online, then the manager online state is defined to be "online". If at least one of the required links is online, then the manager online state is defined to be "partial". If none of the required links are online, then the manager online state is defined to be "offline". If there are no managed links, or RequiredForOnline=no for all managed links, then the manager online state is undefined as above. The purpose of the "partial" state is analogous to the --any switch in systemd-networkd-wait-online.service(8). For example, a required link which lacks a carrier on boot will not force the overall (manager) online state to "offline" if there is an alternative link available.
1 parent e7901ab commit bcdcc59

File tree

13 files changed

+109
-3
lines changed

13 files changed

+109
-3
lines changed

src/libsystemd/sd-network/network-util.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = {
7373

7474
DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState);
7575

76+
static const char *const link_online_state_table[_LINK_ONLINE_STATE_MAX] = {
77+
[LINK_ONLINE_STATE_OFFLINE] = "offline",
78+
[LINK_ONLINE_STATE_PARTIAL] = "partial",
79+
[LINK_ONLINE_STATE_ONLINE] = "online",
80+
};
81+
82+
DEFINE_STRING_TABLE_LOOKUP(link_online_state, LinkOnlineState);
83+
7684
int parse_operational_state_range(const char *str, LinkOperationalStateRange *out) {
7785
LinkOperationalStateRange range = { _LINK_OPERSTATE_INVALID, _LINK_OPERSTATE_INVALID };
7886
_cleanup_free_ const char *min = NULL;

src/libsystemd/sd-network/network-util.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ typedef enum LinkAddressState {
5454
_LINK_ADDRESS_STATE_INVALID = -EINVAL,
5555
} LinkAddressState;
5656

57+
typedef enum LinkOnlineState {
58+
LINK_ONLINE_STATE_OFFLINE,
59+
LINK_ONLINE_STATE_PARTIAL,
60+
LINK_ONLINE_STATE_ONLINE,
61+
_LINK_ONLINE_STATE_MAX,
62+
_LINK_ONLINE_STATE_INVALID = -EINVAL,
63+
} LinkOnlineState;
64+
5765
const char* link_operstate_to_string(LinkOperationalState s) _const_;
5866
LinkOperationalState link_operstate_from_string(const char *s) _pure_;
5967

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

77+
const char* link_online_state_to_string(LinkOnlineState s) _const_;
78+
LinkOnlineState link_online_state_from_string(const char *s) _pure_;
79+
6980
typedef struct LinkOperationalStateRange {
7081
LinkOperationalState min;
7182
LinkOperationalState max;

src/libsystemd/sd-network/sd-network.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ _public_ int sd_network_get_ipv6_address_state(char **state) {
5656
return network_get_string("IPV6_ADDRESS_STATE", state);
5757
}
5858

59+
_public_ int sd_network_get_online_state(char **state) {
60+
return network_get_string("ONLINE_STATE", state);
61+
}
62+
5963
static int network_get_strv(const char *key, char ***ret) {
6064
_cleanup_strv_free_ char **a = NULL;
6165
_cleanup_free_ char *s = NULL;
@@ -204,6 +208,10 @@ _public_ int sd_network_link_get_ipv6_address_state(int ifindex, char **state) {
204208
return network_link_get_string(ifindex, "IPV6_ADDRESS_STATE", state);
205209
}
206210

211+
_public_ int sd_network_link_get_online_state(int ifindex, char **state) {
212+
return network_link_get_string(ifindex, "ONLINE_STATE", state);
213+
}
214+
207215
_public_ int sd_network_link_get_dhcp6_client_iaid_string(int ifindex, char **iaid) {
208216
return network_link_get_string(ifindex, "DHCP6_CLIENT_IAID", iaid);
209217
}

src/network/networkd-json.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ int link_build_json(Link *link, JsonVariant **ret) {
6060
JSON_BUILD_PAIR("CarrierState", JSON_BUILD_STRING(link_carrier_state_to_string(link->carrier_state))),
6161
JSON_BUILD_PAIR("AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->address_state))),
6262
JSON_BUILD_PAIR("IPv4AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv4_address_state))),
63-
JSON_BUILD_PAIR("IPv6AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv6_address_state)))));
63+
JSON_BUILD_PAIR("IPv6AddressState", JSON_BUILD_STRING(link_address_state_to_string(link->ipv6_address_state))),
64+
JSON_BUILD_PAIR("OnlineState", JSON_BUILD_STRING(link_online_state_to_string(link->online_state)))));
6465
if (r < 0)
6566
return r;
6667

src/network/networkd-link-bus.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
2525
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_carrier_state, link_carrier_state, LinkCarrierState);
2626
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_address_state, link_address_state, LinkAddressState);
27+
BUS_DEFINE_PROPERTY_GET_ENUM(property_get_online_state, link_online_state, LinkOnlineState);
2728
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
2829

2930
static int property_get_bit_rates(
@@ -716,6 +717,7 @@ const sd_bus_vtable link_vtable[] = {
716717
SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
717718
SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Link, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
718719
SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Link, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
720+
SD_BUS_PROPERTY("OnlineState", "s", property_get_online_state, offsetof(Link, online_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
719721
SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
720722
SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),
721723

src/network/networkd-link-bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ int link_send_changed(Link *link, const char *property, ...) _sentinel_;
1818
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);
1919
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);
2020
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);
21+
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);
2122

2223
int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error);
2324
int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error);

src/network/networkd-link.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ void link_update_operstate(Link *link, bool also_update_master) {
202202
LinkOperationalState operstate;
203203
LinkCarrierState carrier_state;
204204
LinkAddressState ipv4_address_state, ipv6_address_state, address_state;
205+
LinkOnlineState online_state;
205206
_cleanup_strv_free_ char **p = NULL;
206207
uint8_t ipv4_scope = RT_SCOPE_NOWHERE, ipv6_scope = RT_SCOPE_NOWHERE;
207208
bool changed = false;
@@ -277,6 +278,38 @@ void link_update_operstate(Link *link, bool also_update_master) {
277278
else
278279
operstate = LINK_OPERSTATE_ENSLAVED;
279280

281+
/* Only determine online state for managed links with RequiredForOnline=yes */
282+
if (!link->network || !link->network->required_for_online)
283+
online_state = _LINK_ONLINE_STATE_INVALID;
284+
else if (operstate < link->network->required_operstate_for_online.min ||
285+
operstate > link->network->required_operstate_for_online.max)
286+
online_state = LINK_ONLINE_STATE_OFFLINE;
287+
else {
288+
AddressFamily required_family = link->network->required_family_for_online;
289+
bool needs_ipv4 = required_family & ADDRESS_FAMILY_IPV4;
290+
bool needs_ipv6 = required_family & ADDRESS_FAMILY_IPV6;
291+
292+
/* The operational state is within the range required for online.
293+
* If a particular address family is also required, we might revert
294+
* to offline in the blocks below.
295+
*/
296+
online_state = LINK_ONLINE_STATE_ONLINE;
297+
298+
if (link->network->required_operstate_for_online.min >= LINK_OPERSTATE_DEGRADED) {
299+
if (needs_ipv4 && ipv4_address_state < LINK_ADDRESS_STATE_DEGRADED)
300+
online_state = LINK_ONLINE_STATE_OFFLINE;
301+
if (needs_ipv6 && ipv6_address_state < LINK_ADDRESS_STATE_DEGRADED)
302+
online_state = LINK_ONLINE_STATE_OFFLINE;
303+
}
304+
305+
if (link->network->required_operstate_for_online.min >= LINK_OPERSTATE_ROUTABLE) {
306+
if (needs_ipv4 && ipv4_address_state < LINK_ADDRESS_STATE_ROUTABLE)
307+
online_state = LINK_ONLINE_STATE_OFFLINE;
308+
if (needs_ipv6 && ipv6_address_state < LINK_ADDRESS_STATE_ROUTABLE)
309+
online_state = LINK_ONLINE_STATE_OFFLINE;
310+
}
311+
}
312+
280313
if (link->carrier_state != carrier_state) {
281314
link->carrier_state = carrier_state;
282315
changed = true;
@@ -312,6 +345,13 @@ void link_update_operstate(Link *link, bool also_update_master) {
312345
log_oom();
313346
}
314347

348+
if (link->online_state != online_state) {
349+
link->online_state = online_state;
350+
changed = true;
351+
if (strv_extend(&p, "OnlineState") < 0)
352+
log_oom();
353+
}
354+
315355
if (p)
316356
link_send_changed_strv(link, p);
317357
if (changed)
@@ -2330,6 +2370,7 @@ static int link_initialized_and_synced(Link *link) {
23302370
}
23312371

23322372
link->network = network_ref(network);
2373+
link_update_operstate(link, false);
23332374
link_dirty(link);
23342375
}
23352376

@@ -2466,6 +2507,7 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
24662507
*link = (Link) {
24672508
.n_ref = 1,
24682509
.state = LINK_STATE_PENDING,
2510+
.online_state = _LINK_ONLINE_STATE_INVALID,
24692511
.ifindex = ifindex,
24702512
.iftype = iftype,
24712513
.ifname = TAKE_PTR(ifname),

src/network/networkd-link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ typedef struct Link {
7777
LinkAddressState address_state;
7878
LinkAddressState ipv4_address_state;
7979
LinkAddressState ipv6_address_state;
80+
LinkOnlineState online_state;
8081

8182
unsigned address_label_messages;
8283
unsigned static_address_messages;

src/network/networkd-manager-bus.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ const sd_bus_vtable manager_vtable[] = {
271271
SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
272272
SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Manager, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
273273
SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Manager, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
274+
SD_BUS_PROPERTY("OnlineState", "s", property_get_online_state, offsetof(Manager, online_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
274275

275276
SD_BUS_METHOD_WITH_ARGS("ListLinks",
276277
SD_BUS_NO_ARGS,

src/network/networkd-manager.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ int manager_new(Manager **ret) {
380380

381381
*m = (Manager) {
382382
.speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
383+
.online_state = _LINK_ONLINE_STATE_INVALID,
383384
.manage_foreign_routes = true,
384385
.manage_foreign_rules = true,
385386
.ethtool_fd = -1,

0 commit comments

Comments
 (0)