network_manager: Async query all interface states
This only queries the state during startup and relies on matches to keep
up with changes from the systemd-networkd daemon.
Change-Id: I30776d443c39a52a91826ad1b515da60c7ecf641
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 4f71a46..0408219 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -18,7 +18,6 @@
#include <filesystem>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
-#include <sdbusplus/bus/match.hpp>
#include <stdplus/raw.hpp>
#include <stdplus/zstring.hpp>
#include <string>
@@ -76,8 +75,7 @@
const InterfaceInfo& info,
std::string_view objRoot,
const config::Parser& config,
- bool emitSignal,
- std::optional<bool> enabled) :
+ bool emitSignal, bool enabled) :
EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
config, emitSignal, enabled)
{
@@ -87,8 +85,7 @@
const InterfaceInfo& info,
std::string&& objPath,
const config::Parser& config,
- bool emitSignal,
- std::optional<bool> enabled) :
+ bool emitSignal, bool enabled) :
Ifaces(bus, objPath.c_str(),
emitSignal ? Ifaces::action::defer_emit
: Ifaces::action::emit_no_signals),
@@ -99,7 +96,7 @@
EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
- EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
+ EthernetInterfaceIntf::nicEnabled(enabled);
{
const auto& gws = manager.getRouteTable().getDefaultGateway();
auto it = gws.find(ifIdx);
@@ -435,91 +432,6 @@
}));
}
-bool EthernetInterface::queryNicEnabled() const
-{
- constexpr auto svc = "org.freedesktop.network1";
- constexpr auto intf = "org.freedesktop.network1.Link";
- constexpr auto prop = "AdministrativeState";
- char* rpath;
- sd_bus_path_encode("/org/freedesktop/network1/link",
- std::to_string(ifIdx).c_str(), &rpath);
- std::string path(rpath);
- free(rpath);
-
- // Store / Parser for the AdministrativeState return value
- std::optional<bool> ret;
- auto cb = [&](std::string_view state) {
- if (state != "initialized")
- {
- ret = state != "unmanaged";
- }
- };
-
- // Build a matcher before making the property call to ensure we
- // can eventually get the value.
- sdbusplus::bus::match_t match(
- bus,
- fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
- "'PropertiesChanged',arg0='{}',",
- svc, path, PROPERTY_INTERFACE, intf)
- .c_str(),
- [&](sdbusplus::message_t& m) {
- std::string intf;
- std::unordered_map<std::string, std::variant<std::string>> values;
- try
- {
- m.read(intf, values);
- auto it = values.find(prop);
- // Ignore properties that aren't AdministrativeState
- if (it != values.end())
- {
- cb(std::get<std::string>(it->second));
- }
- }
- catch (const std::exception& e)
- {
- log<level::ERR>(
- fmt::format(
- "AdministrativeState match parsing failed on {}: {}",
- interfaceName(), e.what())
- .c_str(),
- entry("INTERFACE=%s", interfaceName().c_str()),
- entry("ERROR=%s", e.what()));
- }
- });
-
- // Actively call for the value in case the interface is already configured
- auto method =
- bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
- method.append(intf, prop);
- try
- {
- auto reply = bus.call(method);
- std::variant<std::string> state;
- reply.read(state);
- cb(std::get<std::string>(state));
- }
- catch (const std::exception& e)
- {
- log<level::ERR>(
- fmt::format("Failed to get AdministrativeState on {}: {}",
- interfaceName(), e.what())
- .c_str(),
- entry("INTERFACE=%s", interfaceName().c_str()),
- entry("ERROR=%s", e.what()));
- }
-
- // The interface is not yet configured by systemd-networkd, wait until it
- // signals us a valid state.
- while (!ret)
- {
- bus.wait();
- bus.process_discard();
- }
-
- return *ret;
-}
-
bool EthernetInterface::nicEnabled(bool value)
{
if (value == EthernetInterfaceIntf::nicEnabled())