summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-06-20 13:36:30 +0200
committerGitHub <noreply@github.com>2019-06-20 13:36:30 +0200
commit762267cdc117895dd2b50657ebd6ea085a1aff8a (patch)
treecbd71c950ef890af675adc266f6b2e3ed7cd80d2
parent64ef83139cf84a700b95e8150a458b0bb9f720de (diff)
parent1a65093774862728d1eed1411d692101581c0db8 (diff)
downloadsystemd-762267cdc117895dd2b50657ebd6ea085a1aff8a.tar.gz
Merge pull request #12762 from yuwata/network-introduce-carrier-and-network-state-12752
network: introduce carrier and address state to fix network_is_online()
-rw-r--r--src/libsystemd/sd-network/network-util.c30
-rw-r--r--src/libsystemd/sd-network/network-util.h25
-rw-r--r--src/libsystemd/sd-network/sd-network.c28
-rw-r--r--src/network/meson.build1
-rw-r--r--src/network/networkd-link-bus.c27
-rw-r--r--src/network/networkd-link-bus.h20
-rw-r--r--src/network/networkd-link.c137
-rw-r--r--src/network/networkd-link.h8
-rw-r--r--src/network/networkd-manager-bus.c16
-rw-r--r--src/network/networkd-manager.c47
-rw-r--r--src/network/networkd-manager.h4
-rw-r--r--src/network/networkd-speed-meter.c1
-rw-r--r--src/systemd/sd-network.h4
13 files changed, 270 insertions, 78 deletions
diff --git a/src/libsystemd/sd-network/network-util.c b/src/libsystemd/sd-network/network-util.c
index f46a3ff788..08ed942638 100644
--- a/src/libsystemd/sd-network/network-util.c
+++ b/src/libsystemd/sd-network/network-util.c
@@ -7,14 +7,19 @@
#include "strv.h"
bool network_is_online(void) {
- _cleanup_free_ char *state = NULL;
+ _cleanup_free_ char *carrier_state = NULL, *addr_state = NULL;
int r;
- r = sd_network_get_operational_state(&state);
+ r = sd_network_get_carrier_state(&carrier_state);
if (r < 0) /* if we don't know anything, we consider the system online */
return true;
- if (STR_IN_SET(state, "routable", "degraded"))
+ r = sd_network_get_address_state(&addr_state);
+ if (r < 0) /* if we don't know anything, we consider the system online */
+ return true;
+
+ if (STR_IN_SET(carrier_state, "degraded-carrier", "carrier") &&
+ STR_IN_SET(addr_state, "routable", "degraded"))
return true;
return false;
@@ -32,3 +37,22 @@ static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = {
};
DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState);
+
+static const char* const link_carrier_state_table[_LINK_CARRIER_STATE_MAX] = {
+ [LINK_CARRIER_STATE_OFF] = "off",
+ [LINK_CARRIER_STATE_NO_CARRIER] = "no-carrier",
+ [LINK_CARRIER_STATE_DORMANT] = "dormant",
+ [LINK_CARRIER_STATE_DEGRADED_CARRIER] = "degraded-carrier",
+ [LINK_CARRIER_STATE_CARRIER] = "carrier",
+ [LINK_CARRIER_STATE_ENSLAVED] = "enslaved",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(link_carrier_state, LinkCarrierState);
+
+static const char* const link_address_state_table[_LINK_ADDRESS_STATE_MAX] = {
+ [LINK_ADDRESS_STATE_OFF] = "off",
+ [LINK_ADDRESS_STATE_DEGRADED] = "degraded",
+ [LINK_ADDRESS_STATE_ROUTABLE] = "routable",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(link_address_state, LinkAddressState);
diff --git a/src/libsystemd/sd-network/network-util.h b/src/libsystemd/sd-network/network-util.h
index 6936fd536b..a19435393d 100644
--- a/src/libsystemd/sd-network/network-util.h
+++ b/src/libsystemd/sd-network/network-util.h
@@ -20,5 +20,30 @@ typedef enum LinkOperationalState {
_LINK_OPERSTATE_INVALID = -1
} LinkOperationalState;
+typedef enum LinkCarrierState {
+ LINK_CARRIER_STATE_OFF = LINK_OPERSTATE_OFF,
+ LINK_CARRIER_STATE_NO_CARRIER = LINK_OPERSTATE_NO_CARRIER,
+ LINK_CARRIER_STATE_DORMANT = LINK_OPERSTATE_DORMANT,
+ LINK_CARRIER_STATE_DEGRADED_CARRIER = LINK_OPERSTATE_DEGRADED_CARRIER,
+ LINK_CARRIER_STATE_CARRIER = LINK_OPERSTATE_CARRIER,
+ LINK_CARRIER_STATE_ENSLAVED = LINK_OPERSTATE_ENSLAVED,
+ _LINK_CARRIER_STATE_MAX,
+ _LINK_CARRIER_STATE_INVALID = -1
+} LinkCarrierState;
+
+typedef enum LinkAddressState {
+ LINK_ADDRESS_STATE_OFF,
+ LINK_ADDRESS_STATE_DEGRADED,
+ LINK_ADDRESS_STATE_ROUTABLE,
+ _LINK_ADDRESS_STATE_MAX,
+ _LINK_ADDRESS_STATE_INVALID = -1
+} LinkAddressState;
+
const char* link_operstate_to_string(LinkOperationalState s) _const_;
LinkOperationalState link_operstate_from_string(const char *s) _pure_;
+
+const char* link_carrier_state_to_string(LinkCarrierState s) _const_;
+LinkCarrierState link_carrier_state_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_;
diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c
index 2d715043e1..a3c0542d7a 100644
--- a/src/libsystemd/sd-network/sd-network.c
+++ b/src/libsystemd/sd-network/sd-network.c
@@ -18,13 +18,13 @@
#include "strv.h"
#include "util.h"
-_public_ int sd_network_get_operational_state(char **state) {
+static int network_get_string(const char *field, char **ret) {
_cleanup_free_ char *s = NULL;
int r;
- assert_return(state, -EINVAL);
+ assert_return(ret, -EINVAL);
- r = parse_env_file(NULL, "/run/systemd/netif/state", "OPER_STATE", &s);
+ r = parse_env_file(NULL, "/run/systemd/netif/state", field, &s);
if (r == -ENOENT)
return -ENODATA;
if (r < 0)
@@ -32,11 +32,23 @@ _public_ int sd_network_get_operational_state(char **state) {
if (isempty(s))
return -ENODATA;
- *state = TAKE_PTR(s);
+ *ret = TAKE_PTR(s);
return 0;
}
+_public_ int sd_network_get_operational_state(char **state) {
+ return network_get_string("OPER_STATE", state);
+}
+
+_public_ int sd_network_get_carrier_state(char **state) {
+ return network_get_string("CARRIER_STATE", state);
+}
+
+_public_ int sd_network_get_address_state(char **state) {
+ return network_get_string("ADDRESS_STATE", state);
+}
+
static int network_get_strv(const char *key, char ***ret) {
_cleanup_strv_free_ char **a = NULL;
_cleanup_free_ char *s = NULL;
@@ -149,6 +161,14 @@ _public_ int sd_network_link_get_operational_state(int ifindex, char **state) {
return network_link_get_string(ifindex, "OPER_STATE", state);
}
+_public_ int sd_network_link_get_carrier_state(int ifindex, char **state) {
+ return network_link_get_string(ifindex, "CARRIER_STATE", state);
+}
+
+_public_ int sd_network_link_get_address_state(int ifindex, char **state) {
+ return network_link_get_string(ifindex, "ADDRESS_STATE", state);
+}
+
_public_ int sd_network_link_get_required_for_online(int ifindex) {
_cleanup_free_ char *s = NULL;
int r;
diff --git a/src/network/meson.build b/src/network/meson.build
index 959421fc5c..4eda3abef1 100644
--- a/src/network/meson.build
+++ b/src/network/meson.build
@@ -63,6 +63,7 @@ sources = files('''
networkd-ipv6-proxy-ndp.c
networkd-ipv6-proxy-ndp.h
networkd-link-bus.c
+ networkd-link-bus.h
networkd-link.c
networkd-link.h
networkd-lldp-rx.c
diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
index 076845421c..eda0325c2b 100644
--- a/src/network/networkd-link-bus.c
+++ b/src/network/networkd-link-bus.c
@@ -3,12 +3,15 @@
#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-util.h"
+#include "networkd-link-bus.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "parse-util.h"
#include "strv.h"
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
+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);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
static int property_get_bit_rates(
@@ -60,13 +63,15 @@ const sd_bus_vtable link_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_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),
SD_BUS_VTABLE_END
};
-static char *link_bus_path(Link *link) {
+char *link_bus_path(Link *link) {
_cleanup_free_ char *ifindex = NULL;
char *p;
int r;
@@ -145,17 +150,15 @@ int link_object_find(sd_bus *bus, const char *path, const char *interface, void
return 1;
}
-int link_send_changed(Link *link, const char *property, ...) {
+int link_send_changed_strv(Link *link, char **properties) {
_cleanup_free_ char *p = NULL;
- char **l;
assert(link);
assert(link->manager);
+ assert(properties);
if (!link->manager->bus)
- return 0; /* replace with assert when we have kdbus */
-
- l = strv_from_stdarg_alloca(property);
+ return 0;
p = link_bus_path(link);
if (!p)
@@ -165,5 +168,13 @@ int link_send_changed(Link *link, const char *property, ...) {
link->manager->bus,
p,
"org.freedesktop.network1.Link",
- l);
+ properties);
+}
+
+int link_send_changed(Link *link, const char *property, ...) {
+ char **properties;
+
+ properties = strv_from_stdarg_alloca(property);
+
+ return link_send_changed_strv(link, properties);
}
diff --git a/src/network/networkd-link-bus.h b/src/network/networkd-link-bus.h
new file mode 100644
index 0000000000..58005a4bbe
--- /dev/null
+++ b/src/network/networkd-link-bus.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-bus.h"
+
+#include "macro.h"
+
+typedef struct Link Link;
+
+extern const sd_bus_vtable link_vtable[];
+
+char *link_bus_path(Link *link);
+int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
+int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
+int link_send_changed_strv(Link *link, char **properties);
+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);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 4d843651c9..9f228a9d30 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -20,6 +20,8 @@
#include "network-internal.h"
#include "networkd-can.h"
#include "networkd-ipv6-proxy-ndp.h"
+#include "networkd-link-bus.h"
+#include "networkd-link.h"
#include "networkd-lldp-tx.h"
#include "networkd-manager.h"
#include "networkd-ndisc.h"
@@ -358,69 +360,110 @@ static void link_update_master_operstate(Link *link, NetDev *netdev) {
void link_update_operstate(Link *link, bool also_update_master) {
LinkOperationalState operstate;
+ LinkCarrierState carrier_state;
+ LinkAddressState address_state;
+ _cleanup_strv_free_ char **p = NULL;
+ uint8_t scope = RT_SCOPE_NOWHERE;
+ bool changed = false;
+ Address *address;
Iterator i;
assert(link);
if (link->kernel_operstate == IF_OPER_DORMANT)
- operstate = LINK_OPERSTATE_DORMANT;
+ carrier_state = LINK_CARRIER_STATE_DORMANT;
else if (link_has_carrier(link)) {
- Address *address;
- uint8_t scope = RT_SCOPE_NOWHERE;
+ if (link_is_enslaved(link))
+ carrier_state = LINK_CARRIER_STATE_ENSLAVED;
+ else
+ carrier_state = LINK_CARRIER_STATE_CARRIER;
+ } else if (link->flags & IFF_UP)
+ carrier_state = LINK_CARRIER_STATE_NO_CARRIER;
+ else
+ carrier_state = LINK_CARRIER_STATE_OFF;
- /* if we have carrier, check what addresses we have */
- SET_FOREACH(address, link->addresses, i) {
- if (!address_is_ready(address))
- continue;
+ if (carrier_state >= LINK_CARRIER_STATE_CARRIER) {
+ Link *slave;
+
+ SET_FOREACH(slave, link->slaves, i) {
+ link_update_operstate(slave, false);
- if (address->scope < scope)
- scope = address->scope;
+ if (slave->carrier_state < LINK_CARRIER_STATE_CARRIER)
+ carrier_state = LINK_CARRIER_STATE_DEGRADED_CARRIER;
}
+ }
- /* for operstate we also take foreign addresses into account */
- SET_FOREACH(address, link->addresses_foreign, i) {
- if (!address_is_ready(address))
- continue;
+ SET_FOREACH(address, link->addresses, i) {
+ if (!address_is_ready(address))
+ continue;
- if (address->scope < scope)
- scope = address->scope;
- }
+ if (address->scope < scope)
+ scope = address->scope;
+ }
- if (scope < RT_SCOPE_SITE)
- /* universally accessible addresses found */
- operstate = LINK_OPERSTATE_ROUTABLE;
- else if (scope < RT_SCOPE_HOST)
- /* only link or site local addresses found */
- operstate = LINK_OPERSTATE_DEGRADED;
- else
- /* no useful addresses found */
- operstate = LINK_OPERSTATE_CARRIER;
- } else if (link->flags & IFF_UP)
- operstate = LINK_OPERSTATE_NO_CARRIER;
+ /* for operstate we also take foreign addresses into account */
+ SET_FOREACH(address, link->addresses_foreign, i) {
+ if (!address_is_ready(address))
+ continue;
+
+ if (address->scope < scope)
+ scope = address->scope;
+ }
+
+ if (scope < RT_SCOPE_SITE)
+ /* universally accessible addresses found */
+ address_state = LINK_ADDRESS_STATE_ROUTABLE;
+ else if (scope < RT_SCOPE_HOST)
+ /* only link or site local addresses found */
+ address_state = LINK_ADDRESS_STATE_DEGRADED;
else
- operstate = LINK_OPERSTATE_OFF;
+ /* no useful addresses found */
+ address_state = LINK_ADDRESS_STATE_OFF;
+
+ /* Mapping of address and carrier state vs operational state
+ * carrier state
+ * | off | no-carrier | dormant | degraded-carrier | carrier | enslaved
+ * ------------------------------------------------------------------------------
+ * off | off | no-carrier | dormant | degraded-carrier | carrier | enslaved
+ * address_state degraded | off | no-carrier | dormant | degraded-carrier | degraded | enslaved
+ * routable | off | no-carrier | dormant | degraded-carrier | routable | routable
+ */
- if (IN_SET(operstate, LINK_OPERSTATE_DEGRADED, LINK_OPERSTATE_CARRIER) &&
- link_is_enslaved(link))
+ if (carrier_state < LINK_CARRIER_STATE_CARRIER || address_state == LINK_ADDRESS_STATE_OFF)
+ operstate = (LinkOperationalState) carrier_state;
+ else if (address_state == LINK_ADDRESS_STATE_ROUTABLE)
+ operstate = LINK_OPERSTATE_ROUTABLE;
+ else if (carrier_state == LINK_CARRIER_STATE_CARRIER)
+ operstate = LINK_OPERSTATE_DEGRADED;
+ else
operstate = LINK_OPERSTATE_ENSLAVED;
- if (operstate >= LINK_OPERSTATE_CARRIER) {
- Link *slave;
-
- SET_FOREACH(slave, link->slaves, i) {
- link_update_operstate(slave, false);
+ if (link->carrier_state != carrier_state) {
+ link->carrier_state = carrier_state;
+ changed = true;
+ if (strv_extend(&p, "CarrierState") < 0)
+ log_oom();
+ }
- if (slave->operstate < LINK_OPERSTATE_CARRIER)
- operstate = LINK_OPERSTATE_DEGRADED_CARRIER;
- }
+ if (link->address_state != address_state) {
+ link->address_state = address_state;
+ changed = true;
+ if (strv_extend(&p, "AddressState") < 0)
+ log_oom();
}
if (link->operstate != operstate) {
link->operstate = operstate;
- link_send_changed(link, "OperationalState", NULL);
- link_dirty(link);
+ changed = true;
+ if (strv_extend(&p, "OperationalState") < 0)
+ log_oom();
}
+ if (p)
+ link_send_changed_strv(link, p);
+ if (changed)
+ link_dirty(link);
+
if (also_update_master && link->network) {
link_update_master_operstate(link, link->network->bond);
link_update_master_operstate(link, link->network->bridge);
@@ -3563,7 +3606,7 @@ static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) {
int link_save(Link *link) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
- const char *admin_state, *oper_state;
+ const char *admin_state, *oper_state, *carrier_state, *address_state;
Address *a;
Route *route;
Iterator i;
@@ -3587,6 +3630,12 @@ int link_save(Link *link) {
oper_state = link_operstate_to_string(link->operstate);
assert(oper_state);
+ carrier_state = link_carrier_state_to_string(link->carrier_state);
+ assert(carrier_state);
+
+ address_state = link_address_state_to_string(link->address_state);
+ assert(address_state);
+
r = fopen_temporary(link->state_file, &f, &temp_path);
if (r < 0)
goto fail;
@@ -3596,8 +3645,10 @@ int link_save(Link *link) {
fprintf(f,
"# This is private data. Do not parse.\n"
"ADMIN_STATE=%s\n"
- "OPER_STATE=%s\n",
- admin_state, oper_state);
+ "OPER_STATE=%s\n"
+ "CARRIER_STATE=%s\n"
+ "ADDRESS_STATE=%s\n",
+ admin_state, oper_state, carrier_state, address_state);
if (link->network) {
char **dhcp6_domains = NULL, **dhcp_domains = NULL;
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 80fc4baee6..ac1532c066 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -60,6 +60,8 @@ typedef struct Link {
LinkState state;
LinkOperationalState operstate;
+ LinkCarrierState carrier_state;
+ LinkAddressState address_state;
unsigned address_messages;
unsigned address_label_messages;
@@ -183,12 +185,6 @@ int link_stop_clients(Link *link, bool may_keep_dhcp);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_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);
-int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
-int link_send_changed(Link *link, const char *property, ...) _sentinel_;
-
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);
diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c
index 8c527837f8..a40220d108 100644
--- a/src/network/networkd-manager-bus.c
+++ b/src/network/networkd-manager-bus.c
@@ -2,32 +2,30 @@
#include "alloc-util.h"
#include "bus-util.h"
+#include "networkd-link-bus.h"
#include "networkd-manager.h"
#include "strv.h"
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
-
const sd_bus_vtable manager_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Manager, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+ SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_VTABLE_END
};
-int manager_send_changed(Manager *manager, const char *property, ...) {
- char **l;
-
+int manager_send_changed_strv(Manager *manager, char **properties) {
assert(manager);
+ assert(properties);
if (!manager->bus)
- return 0; /* replace by assert when we have kdbus */
-
- l = strv_from_stdarg_alloca(property);
+ return 0;
return sd_bus_emit_properties_changed_strv(
manager->bus,
"/org/freedesktop/network1",
"org.freedesktop.network1.Manager",
- l);
+ properties);
}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 0b7d9210da..d80f93b3d2 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -21,6 +21,7 @@
#include "local-addresses.h"
#include "netlink-util.h"
#include "network-internal.h"
+#include "networkd-link-bus.h"
#include "networkd-manager.h"
#include "networkd-speed-meter.h"
#include "ordered-set.h"
@@ -1105,9 +1106,12 @@ static int manager_save(Manager *m) {
Link *link;
Iterator i;
_cleanup_free_ char *temp_path = NULL;
+ _cleanup_strv_free_ char **p = NULL;
_cleanup_fclose_ FILE *f = NULL;
LinkOperationalState operstate = LINK_OPERSTATE_OFF;
- const char *operstate_str;
+ LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
+ LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
+ const char *operstate_str, *carrier_state_str, *address_state_str;
int r;
assert(m);
@@ -1137,6 +1141,12 @@ static int manager_save(Manager *m) {
if (link->operstate > operstate)
operstate = link->operstate;
+ if (link->carrier_state > carrier_state)
+ carrier_state = link->carrier_state;
+
+ if (link->address_state > address_state)
+ address_state = link->address_state;
+
if (!link->network)
continue;
@@ -1208,9 +1218,18 @@ static int manager_save(Manager *m) {
}
}
+ if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED)
+ carrier_state = LINK_CARRIER_STATE_CARRIER;
+
operstate_str = link_operstate_to_string(operstate);
assert(operstate_str);
+ carrier_state_str = link_carrier_state_to_string(carrier_state);
+ assert(carrier_state_str);
+
+ address_state_str = link_address_state_to_string(address_state);
+ assert(address_state_str);
+
r = fopen_temporary(m->state_file, &f, &temp_path);
if (r < 0)
return r;
@@ -1219,7 +1238,10 @@ static int manager_save(Manager *m) {
fprintf(f,
"# This is private data. Do not parse.\n"
- "OPER_STATE=%s\n", operstate_str);
+ "OPER_STATE=%s\n"
+ "CARRIER_STATE=%s\n"
+ "ADDRESS_STATE=%s\n",
+ operstate_str, carrier_state_str, address_state_str);
ordered_set_print(f, "DNS=", dns);
ordered_set_print(f, "NTP=", ntp);
@@ -1241,9 +1263,26 @@ static int manager_save(Manager *m) {
if (m->operational_state != operstate) {
m->operational_state = operstate;
- r = manager_send_changed(m, "OperationalState", NULL);
+ if (strv_extend(&p, "OperationalState") < 0)
+ log_oom();
+ }
+
+ if (m->carrier_state != carrier_state) {
+ m->carrier_state = carrier_state;
+ if (strv_extend(&p, "CarrierState") < 0)
+ log_oom();
+ }
+
+ if (m->address_state != address_state) {
+ m->address_state = address_state;
+ if (strv_extend(&p, "AddressState") < 0)
+ log_oom();
+ }
+
+ if (p) {
+ r = manager_send_changed_strv(m, p);
if (r < 0)
- log_error_errno(r, "Could not emit changed OperationalState: %m");
+ log_error_errno(r, "Could not emit changed properties: %m");
}
m->dirty = false;
diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h
index 281e9cbac4..e0ec45aa2f 100644
--- a/src/network/networkd-manager.h
+++ b/src/network/networkd-manager.h
@@ -33,6 +33,8 @@ struct Manager {
char *state_file;
LinkOperationalState operational_state;
+ LinkCarrierState carrier_state;
+ LinkAddressState address_state;
Hashmap *links;
Hashmap *netdevs;
@@ -83,7 +85,7 @@ int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, vo
int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata);
int manager_rtnl_process_rule(sd_netlink *nl, sd_netlink_message *message, void *userdata);
-int manager_send_changed(Manager *m, const char *property, ...) _sentinel_;
+int manager_send_changed_strv(Manager *m, char **properties);
void manager_dirty(Manager *m);
int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);
diff --git a/src/network/networkd-speed-meter.c b/src/network/networkd-speed-meter.c
index 5fd30f3df8..c4fc56b019 100644
--- a/src/network/networkd-speed-meter.c
+++ b/src/network/networkd-speed-meter.c
@@ -5,6 +5,7 @@
#include "sd-event.h"
#include "sd-netlink.h"
+#include "networkd-link-bus.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-speed-meter.h"
diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h
index 9ab4426b8b..c78f7c86bb 100644
--- a/src/systemd/sd-network.h
+++ b/src/systemd/sd-network.h
@@ -49,6 +49,8 @@ _SD_BEGIN_DECLARATIONS;
* -ENODATA: networkd is not aware of any links
*/
int sd_network_get_operational_state(char **state);
+int sd_network_get_carrier_state(char **state);
+int sd_network_get_address_state(char **state);
/* Get DNS entries for all links. These are string representations of
* IP addresses */
@@ -90,6 +92,8 @@ int sd_network_link_get_setup_state(int ifindex, char **state);
*/
int sd_network_link_get_operational_state(int ifindex, char **state);
int sd_network_link_get_required_operstate_for_online(int ifindex, char **state);
+int sd_network_link_get_carrier_state(int ifindex, char **state);
+int sd_network_link_get_address_state(int ifindex, char **state);
/* Indicates whether the network is relevant to being online.
* Possible return codes: