[systemd-commits] 5 commits - Makefile.am src/import src/network units/org.freedesktop.network1.busname units/systemd-networkd.service.in

Tom Gundersen tomegun at kemper.freedesktop.org
Thu Feb 5 03:04:31 PST 2015


 Makefile.am                                  |   11 ++
 src/import/importd.c                         |    1 
 src/network/networkd-link-bus.c              |  122 +++++++++++++++++++++++++++
 src/network/networkd-link.c                  |   66 +++++++++-----
 src/network/networkd-link.h                  |   24 ++---
 src/network/networkd-manager-bus.c           |   48 ++++++++++
 src/network/networkd-manager.c               |   81 +++++++++++++++++
 src/network/networkd.c                       |    4 
 src/network/networkd.h                       |   24 +++++
 src/network/org.freedesktop.network1.conf    |   42 +++++++++
 src/network/org.freedesktop.network1.service |   12 ++
 units/org.freedesktop.network1.busname       |   14 +++
 units/systemd-networkd.service.in            |    2 
 13 files changed, 408 insertions(+), 43 deletions(-)

New commits:
commit a97dcc12e486ecff531809802930a26c4da827f2
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Feb 4 15:00:20 2015 +0100

    networkd: exit on idle
    
    We will be woken up on rtnl or dbus activity, so let's just quit if some time has passed and that is the only thing that can happen.
    
    Note that we will always stay around if we expect network activity (e.g. DHCP is enabled), as we are not restarted on that.

diff --git a/src/import/importd.c b/src/import/importd.c
index 4715785..1222bf3 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -30,6 +30,7 @@
 #include "socket-util.h"
 #include "mkdir.h"
 #include "import-util.h"
+#include "def.h"
 
 typedef struct Transfer Transfer;
 typedef struct Manager Manager;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 1442230..eff1ce9 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -35,7 +35,7 @@
 #include "conf-parser.h"
 #include "dhcp-lease-internal.h"
 
-static bool link_dhcp6_enabled(Link *link) {
+bool link_dhcp6_enabled(Link *link) {
         if (link->flags & IFF_LOOPBACK)
                 return false;
 
@@ -45,7 +45,7 @@ static bool link_dhcp6_enabled(Link *link) {
         return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES);
 }
 
-static bool link_dhcp4_enabled(Link *link) {
+bool link_dhcp4_enabled(Link *link) {
         if (link->flags & IFF_LOOPBACK)
                 return false;
 
@@ -55,7 +55,7 @@ static bool link_dhcp4_enabled(Link *link) {
         return IN_SET(link->network->dhcp, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES);
 }
 
-static bool link_dhcp4_server_enabled(Link *link) {
+bool link_dhcp4_server_enabled(Link *link) {
         if (link->flags & IFF_LOOPBACK)
                 return false;
 
@@ -65,7 +65,7 @@ static bool link_dhcp4_server_enabled(Link *link) {
         return link->network->dhcp_server;
 }
 
-static bool link_ipv4ll_enabled(Link *link) {
+bool link_ipv4ll_enabled(Link *link) {
         if (link->flags & IFF_LOOPBACK)
                 return false;
 
@@ -75,7 +75,7 @@ static bool link_ipv4ll_enabled(Link *link) {
         return link->network->ipv4ll;
 }
 
-static bool link_lldp_enabled(Link *link) {
+bool link_lldp_enabled(Link *link) {
         if (link->flags & IFF_LOOPBACK)
                 return false;
 
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index b237120..ce83f24 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -114,6 +114,12 @@ int ipv4ll_configure(Link *link);
 int dhcp4_configure(Link *link);
 int icmp6_configure(Link *link);
 
+bool link_lldp_enabled(Link *link);
+bool link_ipv4ll_enabled(Link *link);
+bool link_dhcp4_server_enabled(Link *link);
+bool link_dhcp4_enabled(Link *link);
+bool link_dhcp6_enabled(Link *link);
+
 const char* link_state_to_string(LinkState s) _const_;
 LinkState link_state_from_string(const char *s) _pure_;
 
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 40328a3..02ab9f9 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -31,6 +31,8 @@
 #include "libudev-private.h"
 #include "udev-util.h"
 #include "rtnl-util.h"
+#include "bus-util.h"
+#include "def.h"
 #include "mkdir.h"
 #include "virt.h"
 
@@ -497,6 +499,46 @@ void manager_free(Manager *m) {
         free(m);
 }
 
+static bool manager_check_idle(void *userdata) {
+        Manager *m = userdata;
+        Link *link;
+        Iterator i;
+
+        assert(m);
+
+        HASHMAP_FOREACH(link, m->links, i) {
+                /* we are not woken on udev activity, so let's just wait for the
+                 * pending udev event */
+                if (link->state == LINK_STATE_PENDING)
+                        return false;
+
+                if (!link->network)
+                        continue;
+
+                /* we are not woken on netork activity, so let's stay around */
+                if (link_lldp_enabled(link) ||
+                    link_ipv4ll_enabled(link) ||
+                    link_dhcp4_server_enabled(link) ||
+                    link_dhcp4_enabled(link) ||
+                    link_dhcp6_enabled(link))
+                        return false;
+        }
+
+        return true;
+}
+
+int manager_run(Manager *m) {
+        assert(m);
+
+        return bus_event_loop_with_idle(
+                        m->event,
+                        m->bus,
+                        "org.freedesktop.network1",
+                        DEFAULT_EXIT_USEC,
+                        manager_check_idle,
+                        m);
+}
+
 int manager_load_config(Manager *m) {
         int r;
 
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 0aaef8b..571f523 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -110,7 +110,7 @@ int main(int argc, char *argv[]) {
                   "READY=1\n"
                   "STATUS=Processing requests...");
 
-        r = sd_event_loop(m->event);
+        r = manager_run(m);
         if (r < 0) {
                 log_error_errno(r, "Event loop failed: %m");
                 goto out;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 9f3a5ea..e6d84f1 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -239,6 +239,8 @@ extern const sd_bus_vtable manager_vtable[];
 int manager_new(Manager **ret);
 void manager_free(Manager *m);
 
+int manager_run(Manager *m);
+
 int manager_load_config(Manager *m);
 bool manager_should_reload(Manager *m);
 
diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
index fab278e..5a91b8e 100644
--- a/units/systemd-networkd.service.in
+++ b/units/systemd-networkd.service.in
@@ -19,7 +19,7 @@ Wants=network.target
 
 [Service]
 Type=notify
-Restart=always
+Restart=on-failure
 RestartSec=0
 ExecStart=@rootlibexecdir@/systemd-networkd
 CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW CAP_SETUID CAP_SETGID CAP_SETPCAP CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER

commit 3f171cabadfcd8699def3732d264f63f8e800562
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Feb 4 15:16:40 2015 +0100

    networkd: don't unlink state files on exit
    
    Only unlink state files on DELLINK. This allows sd-network to be used even when networkd is not running.

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index f4ab97f..1442230 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -283,12 +283,10 @@ static void link_free(Link *link) {
         sd_dhcp_client_unref(link->dhcp_client);
         sd_dhcp_lease_unref(link->dhcp_lease);
 
-        unlink(link->lease_file);
         free(link->lease_file);
 
         sd_lldp_free(link->lldp);
 
-        unlink(link->lldp_file);
         free(link->lldp_file);
 
         sd_ipv4ll_unref(link->ipv4ll);
@@ -300,7 +298,6 @@ static void link_free(Link *link) {
 
         free(link->ifname);
 
-        unlink(link->state_file);
         free(link->state_file);
 
         udev_device_unref(link->udev_device);

commit e331e24649213f2e093e16e4d3d64ee823dfc375
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Feb 4 11:44:37 2015 +0100

    networkd: add basic dbus API
    
    Only the very basics, more to come.
    
    For now:
    
    $ busctl tree org.freedesktop.network1
    └─/org/freedesktop/network1
      └─/org/freedesktop/network1/link
        ├─/org/freedesktop/network1/link/1
        ├─/org/freedesktop/network1/link/2
        ├─/org/freedesktop/network1/link/3
        ├─/org/freedesktop/network1/link/4
        ├─/org/freedesktop/network1/link/5
        ├─/org/freedesktop/network1/link/6
        ├─/org/freedesktop/network1/link/7
        ├─/org/freedesktop/network1/link/8
        └─/org/freedesktop/network1/link/9
    
    $ busctl introspect org.freedesktop.network1 /org/freedesktop/network1
    NAME                                TYPE      SIGNATURE RESULT/VALUE FLAGS
    org.freedesktop.network1.Manager    interface -         -            -
    .OperationalState                   property  s         "carrier" emits-change
    
    $ busctl introspect org.freedesktop.network1 /org/freedesktop/network1/link/1
    NAME                                TYPE      SIGNATURE RESULT/VALUE FLAGS
    org.freedesktop.network1.Link       interface -         -            -
    .AdministrativeState                property  s         "unmanaged" emits-change
    .OperationalState                   property  s         "carrier" emits-change

diff --git a/Makefile.am b/Makefile.am
index 14f6827..53ad568 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5585,6 +5585,7 @@ libsystemd_networkd_core_la_SOURCES = \
 	src/network/networkd-netdev-bond.c \
 	src/network/networkd-netdev-bridge.c \
 	src/network/networkd-link.c \
+	src/network/networkd-link-bus.c \
 	src/network/networkd-ipv4ll.c \
 	src/network/networkd-dhcp4.c \
 	src/network/networkd-dhcp6.c \
@@ -5592,6 +5593,7 @@ libsystemd_networkd_core_la_SOURCES = \
 	src/network/networkd-address.c \
 	src/network/networkd-route.c \
 	src/network/networkd-manager.c \
+	src/network/networkd-manager-bus.c \
 	src/network/networkd-fdb.c \
 	src/network/networkd-address-pool.c
 
@@ -5673,6 +5675,15 @@ nodist_systemunit_DATA += \
 	units/systemd-networkd.service \
 	units/systemd-networkd-wait-online.service
 
+dist_systemunit_DATA_busnames += \
+	units/org.freedesktop.network1.busname
+
+dist_dbussystemservice_DATA += \
+	src/network/org.freedesktop.network1.service
+
+dist_dbuspolicy_DATA += \
+	src/network/org.freedesktop.network1.conf
+
 GENERAL_ALIASES += \
 	$(systemunitdir)/systemd-networkd.socket $(pkgsysconfdir)/system/sockets.target.wants/systemd-networkd.socket \
 	$(systemunitdir)/systemd-networkd.service $(pkgsysconfdir)/system/multi-user.target.wants/systemd-networkd.service \
diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c
new file mode 100644
index 0000000..645c47a
--- /dev/null
+++ b/src/network/networkd-link-bus.c
@@ -0,0 +1,122 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Tom Gundersen
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "bus-util.h"
+#include "strv.h"
+
+#include "networkd.h"
+#include "networkd-link.h"
+
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
+
+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("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
+
+        SD_BUS_VTABLE_END
+};
+
+static char *link_bus_path(Link *link) {
+        char *p;
+
+        assert(link);
+        assert(link->ifindex > 0);
+
+        asprintf(&p, "/org/freedesktop/network1/link/%d", link->ifindex);
+
+        return p;
+}
+
+int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
+        _cleanup_strv_free_ char **l = NULL;
+        Manager *m = userdata;
+        Link *link;
+        Iterator i;
+        int r;
+
+        assert(bus);
+        assert(path);
+        assert(m);
+        assert(nodes);
+
+        HASHMAP_FOREACH(link, m->links, i) {
+                char *p;
+
+                p = link_bus_path(link);
+                if (!p)
+                        return -ENOMEM;
+
+                r = strv_consume(&l, p);
+                if (r < 0)
+                        return r;
+        }
+
+        *nodes = l;
+        l = NULL;
+
+        return 1;
+}
+
+int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
+        Manager *m = userdata;
+        Link *link;
+        int ifindex, r;
+
+        assert(bus);
+        assert(path);
+        assert(interface);
+        assert(m);
+        assert(found);
+
+        if (sscanf(path, "/org/freedesktop/network1/link/%d", &ifindex) != 1)
+                return 0;
+
+        r = link_get(m, ifindex, &link);
+        if (r < 0)
+                return 0;
+
+        *found = link;
+
+        return 1;
+}
+
+int link_send_changed(Link *link, const char *property, ...) {
+        _cleanup_free_ char *p = NULL;
+        char **l;
+
+        assert(link);
+        assert(link->manager);
+
+        l = strv_from_stdarg_alloca(property);
+
+        p = link_bus_path(link);
+        if (!p)
+                return -ENOMEM;
+
+        return sd_bus_emit_properties_changed_strv(
+                        link->manager->bus,
+                        p,
+                        "org.freedesktop.network1.Link",
+                        l);
+}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 077626c..f4ab97f 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -338,11 +338,24 @@ int link_get(Manager *m, int ifindex, Link **ret) {
         return 0;
 }
 
+static void link_set_state(Link *link, LinkState state) {
+        assert(link);
+
+        if (link->state == state)
+                return;
+
+        link->state = state;
+
+        link_send_changed(link, "AdministrativeState", NULL);
+
+        return;
+}
+
 void link_drop(Link *link) {
         if (!link || link->state == LINK_STATE_LINGER)
                 return;
 
-        link->state = LINK_STATE_LINGER;
+        link_set_state(link, LINK_STATE_LINGER);
 
         log_link_debug(link, "link removed");
 
@@ -356,7 +369,7 @@ static void link_enter_unmanaged(Link *link) {
 
         log_link_debug(link, "unmanaged");
 
-        link->state = LINK_STATE_UNMANAGED;
+        link_set_state(link, LINK_STATE_UNMANAGED);
 
         link_save(link);
 }
@@ -430,7 +443,7 @@ void link_enter_failed(Link *link) {
 
         log_link_warning(link, "failed");
 
-        link->state = LINK_STATE_FAILED;
+        link_set_state(link, LINK_STATE_FAILED);
 
         link_stop_clients(link);
 
@@ -473,7 +486,7 @@ static int link_enter_configured(Link *link) {
 
         log_link_info(link, "link configured");
 
-        link->state = LINK_STATE_CONFIGURED;
+        link_set_state(link, LINK_STATE_CONFIGURED);
 
         link_save(link);
 
@@ -536,7 +549,7 @@ static int link_enter_set_routes(Link *link) {
         assert(link->network);
         assert(link->state == LINK_STATE_SETTING_ADDRESSES);
 
-        link->state = LINK_STATE_SETTING_ROUTES;
+        link_set_state(link, LINK_STATE_SETTING_ROUTES);
 
         LIST_FOREACH(routes, rt, link->network->static_routes) {
                 r = route_configure(rt, link, &route_handler);
@@ -617,7 +630,7 @@ static int link_enter_set_addresses(Link *link) {
         assert(link->network);
         assert(link->state != _LINK_STATE_INVALID);
 
-        link->state = LINK_STATE_SETTING_ADDRESSES;
+        link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
 
         LIST_FOREACH(addresses, ad, link->network->static_addresses) {
                 r = address_configure(ad, link, &address_handler);
@@ -1153,7 +1166,7 @@ static int link_enter_join_netdev(Link *link) {
         assert(link->network);
         assert(link->state == LINK_STATE_PENDING);
 
-        link->state = LINK_STATE_ENSLAVING;
+        link_set_state(link, LINK_STATE_ENSLAVING);
 
         link_save(link);
 
@@ -1724,7 +1737,7 @@ int link_update(Link *link, sd_rtnl_message *m) {
         if (link->state == LINK_STATE_LINGER) {
                 link_ref(link);
                 log_link_info(link, "link readded");
-                link->state = LINK_STATE_ENSLAVING;
+                link_set_state(link, LINK_STATE_ENSLAVING);
         }
 
         r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname);
@@ -1843,11 +1856,11 @@ int link_update(Link *link, sd_rtnl_message *m) {
 }
 
 static void link_update_operstate(Link *link) {
-
+        LinkOperationalState operstate;
         assert(link);
 
         if (link->kernel_operstate == IF_OPER_DORMANT)
-                link->operstate = LINK_OPERSTATE_DORMANT;
+                operstate = LINK_OPERSTATE_DORMANT;
         else if (link_has_carrier(link)) {
                 Address *address;
                 uint8_t scope = RT_SCOPE_NOWHERE;
@@ -1863,17 +1876,22 @@ static void link_update_operstate(Link *link) {
 
                 if (scope < RT_SCOPE_SITE)
                         /* universally accessible addresses found */
-                        link->operstate = LINK_OPERSTATE_ROUTABLE;
+                        operstate = LINK_OPERSTATE_ROUTABLE;
                 else if (scope < RT_SCOPE_HOST)
                         /* only link or site local addresses found */
-                        link->operstate = LINK_OPERSTATE_DEGRADED;
+                        operstate = LINK_OPERSTATE_DEGRADED;
                 else
                         /* no useful addresses found */
-                        link->operstate = LINK_OPERSTATE_CARRIER;
+                        operstate = LINK_OPERSTATE_CARRIER;
         } else if (link->flags & IFF_UP)
-                link->operstate = LINK_OPERSTATE_NO_CARRIER;
+                operstate = LINK_OPERSTATE_NO_CARRIER;
         else
-                link->operstate = LINK_OPERSTATE_OFF;
+                operstate = LINK_OPERSTATE_OFF;
+
+        if (link->operstate != operstate) {
+                link->operstate = operstate;
+                link_send_changed(link, "OperationalState", NULL);
+        }
 }
 
 int link_save(Link *link) {
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 81e97fa..b237120 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -36,17 +36,6 @@ typedef enum LinkState {
         _LINK_STATE_INVALID = -1
 } LinkState;
 
-typedef enum LinkOperationalState {
-        LINK_OPERSTATE_OFF,
-        LINK_OPERSTATE_NO_CARRIER,
-        LINK_OPERSTATE_DORMANT,
-        LINK_OPERSTATE_CARRIER,
-        LINK_OPERSTATE_DEGRADED,
-        LINK_OPERSTATE_ROUTABLE,
-        _LINK_OPERSTATE_MAX,
-        _LINK_OPERSTATE_INVALID = -1
-} LinkOperationalState;
-
 struct Link {
         Manager *manager;
 
@@ -128,8 +117,11 @@ int icmp6_configure(Link *link);
 const char* link_state_to_string(LinkState s) _const_;
 LinkState link_state_from_string(const char *s) _pure_;
 
-const char* link_operstate_to_string(LinkOperationalState s) _const_;
-LinkOperationalState link_operstate_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_;
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
 #define _cleanup_link_unref_ _cleanup_(link_unrefp)
diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c
new file mode 100644
index 0000000..7753c5d
--- /dev/null
+++ b/src/network/networkd-manager-bus.c
@@ -0,0 +1,48 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2015 Tom Gundersen
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "bus-util.h"
+
+#include "networkd.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_VTABLE_END
+};
+
+int manager_send_changed(Manager *manager, const char *property, ...) {
+        char **l;
+
+        assert(manager);
+
+        l = strv_from_stdarg_alloca(property);
+
+        return sd_bus_emit_properties_changed_strv(
+                        manager->bus,
+                        "/org/freedesktop/network1",
+                        "org.freedesktop.network1.Manager",
+                        l);
+}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 4d27272..40328a3 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -151,10 +151,6 @@ int manager_connect_bus(Manager *m) {
         } if (r < 0)
                 return r;
 
-        r = sd_bus_attach_event(m->bus, m->event, 0);
-        if (r < 0)
-                return r;
-
         r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
                              "type='signal',"
                              "sender='org.freedesktop.login1',"
@@ -166,6 +162,26 @@ int manager_connect_bus(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
 
+        r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add manager object vtable: %m");
+
+        r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m);
+        if (r < 0)
+               return log_error_errno(r, "Failed to add link object vtable: %m");
+
+        r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add link enumerator: %m");
+
+        r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to register name: %m");
+
+        r = sd_bus_attach_event(m->bus, m->event, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to attach bus to event loop: %m");
+
         return 0;
 }
 
@@ -741,6 +757,13 @@ int manager_save(Manager *m) {
                 goto fail;
         }
 
+        if (m->operational_state != operstate) {
+                m->operational_state = operstate;
+                r = manager_send_changed(m, "OperationalState", NULL);
+                if (r < 0)
+                        log_error_errno(r, "Could not emit changed OperationalState: %m");
+        }
+
         return 0;
 
 fail:
diff --git a/src/network/networkd.h b/src/network/networkd.h
index e053bd6..9f3a5ea 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -72,6 +72,17 @@ typedef enum LLMNRSupport {
         _LLMNR_SUPPORT_INVALID = -1,
 } LLMNRSupport;
 
+typedef enum LinkOperationalState {
+        LINK_OPERSTATE_OFF,
+        LINK_OPERSTATE_NO_CARRIER,
+        LINK_OPERSTATE_DORMANT,
+        LINK_OPERSTATE_CARRIER,
+        LINK_OPERSTATE_DEGRADED,
+        LINK_OPERSTATE_ROUTABLE,
+        _LINK_OPERSTATE_MAX,
+        _LINK_OPERSTATE_INVALID = -1
+} LinkOperationalState;
+
 struct FdbEntry {
         Network *network;
         unsigned section;
@@ -209,6 +220,7 @@ struct Manager {
         bool enumerating;
 
         char *state_file;
+        LinkOperationalState operational_state;
 
         Hashmap *links;
         Hashmap *netdevs;
@@ -222,6 +234,8 @@ extern const char* const network_dirs[];
 
 /* Manager */
 
+extern const sd_bus_vtable manager_vtable[];
+
 int manager_new(Manager **ret);
 void manager_free(Manager *m);
 
@@ -231,6 +245,7 @@ bool manager_should_reload(Manager *m);
 int manager_rtnl_enumerate_links(Manager *m);
 int manager_rtnl_enumerate_addresses(Manager *m);
 
+int manager_send_changed(Manager *m, const char *property, ...) _sentinel_;
 int manager_save(Manager *m);
 
 int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found);
@@ -394,3 +409,8 @@ const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
 AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
 
 int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+/* Opeartional State */
+
+const char* link_operstate_to_string(LinkOperationalState s) _const_;
+LinkOperationalState link_operstate_from_string(const char *s) _pure_;
diff --git a/src/network/org.freedesktop.network1.conf b/src/network/org.freedesktop.network1.conf
new file mode 100644
index 0000000..52dad33
--- /dev/null
+++ b/src/network/org.freedesktop.network1.conf
@@ -0,0 +1,42 @@
+<?xml version="1.0"?> <!--*-nxml-*-->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+        "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!--
+  This file is part of systemd.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+-->
+
+<busconfig>
+
+        <policy user="systemd-network">
+                <allow own="org.freedesktop.network1"/>
+                <allow send_destination="org.freedesktop.network1"/>
+                <allow receive_sender="org.freedesktop.network1"/>
+        </policy>
+
+        <policy context="default">
+                <deny send_destination="org.freedesktop.network1"/>
+
+                <allow send_destination="org.freedesktop.network1"
+                       send_interface="org.freedesktop.DBus.Introspectable"/>
+
+                <allow send_destination="org.freedesktop.network1"
+                       send_interface="org.freedesktop.DBus.Peer"/>
+
+                <allow send_destination="org.freedesktop.network1"
+                       send_interface="org.freedesktop.DBus.Properties"
+                       send_member="Get"/>
+
+                <allow send_destination="org.freedesktop.network1"
+                       send_interface="org.freedesktop.DBus.Properties"
+                       send_member="GetAll"/>
+
+                <allow receive_sender="org.freedesktop.network1"/>
+        </policy>
+
+</busconfig>
diff --git a/src/network/org.freedesktop.network1.service b/src/network/org.freedesktop.network1.service
new file mode 100644
index 0000000..bea885f
--- /dev/null
+++ b/src/network/org.freedesktop.network1.service
@@ -0,0 +1,12 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[D-BUS Service]
+Name=org.freedesktop.network1
+Exec=/bin/false
+User=root
+SystemdService=dbus-org.freedesktop.network1.service
diff --git a/units/org.freedesktop.network1.busname b/units/org.freedesktop.network1.busname
new file mode 100644
index 0000000..c68f4ad
--- /dev/null
+++ b/units/org.freedesktop.network1.busname
@@ -0,0 +1,14 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+[Unit]
+Description=Network Service Bus Name
+Documentation=man:systemd-networkd.service(8)
+
+[BusName]
+Service=systemd-networkd.service
+AllowWorld=talk

commit 6a24f1484fcc1f59f89617afbe4282667a358eab
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Feb 4 10:08:12 2015 +0100

    networkd: don't warn about missing links unnecessarily
    
    If we get a NEWLINK + NEWADDR between enumerating the links and enumerating the addresses, we
    would get a warning that the link corresponding to the address does not exist. This is a false
    warning as both the NEWLINK and NEWADDR would be processed after enumerating completed, so drop
    it.

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 22864bd..077626c 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1492,7 +1492,10 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use
         } else {
                 r = link_get(m, ifindex, &link);
                 if (r < 0 || !link) {
-                        log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
+                        /* when enumerating we might be out of sync, but we will
+                         * get the address again, so just ignore it */
+                        if (!m->enumerating)
+                                log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
                         return 0;
                 }
         }
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 3786330..4d27272 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -525,9 +525,13 @@ int manager_rtnl_enumerate_links(Manager *m) {
         for (link = reply; link; link = sd_rtnl_message_next(link)) {
                 int k;
 
+                m->enumerating = true;
+
                 k = manager_rtnl_process_link(m->rtnl, link, m);
                 if (k < 0)
                         r = k;
+
+                m->enumerating = false;
         }
 
         return r;
@@ -556,9 +560,13 @@ int manager_rtnl_enumerate_addresses(Manager *m) {
         for (addr = reply; addr; addr = sd_rtnl_message_next(addr)) {
                 int k;
 
+                m->enumerating = true;
+
                 k = link_rtnl_process_address(m->rtnl, addr, m);
                 if (k < 0)
                         r = k;
+
+                m->enumerating = false;
         }
 
         return r;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 075aefe..e053bd6 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -206,6 +206,8 @@ struct Manager {
         struct udev_monitor *udev_monitor;
         sd_event_source *udev_event_source;
 
+        bool enumerating;
+
         char *state_file;
 
         Hashmap *links;

commit 73432d67b590c8c8954cf2f8954d174a55d58c7b
Author: Tom Gundersen <teg at jklm.no>
Date:   Wed Feb 4 09:47:50 2015 +0100

    networkd: log when finished enumerating links and addresses

diff --git a/src/network/networkd.c b/src/network/networkd.c
index 0b4af90..0aaef8b 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -104,6 +104,8 @@ int main(int argc, char *argv[]) {
                 goto out;
         }
 
+        log_info("Enumeration completed");
+
         sd_notify(false,
                   "READY=1\n"
                   "STATUS=Processing requests...");



More information about the systemd-commits mailing list