[systemd-commits] 5 commits - Makefile.am man/systemd-networkd-wait-online.service.xml src/libsystemd src/network src/systemd TODO units/systemd-networkd.service.in units/systemd-networkd.socket

Tom Gundersen tomegun at kemper.freedesktop.org
Mon Feb 2 03:00:19 PST 2015


 Makefile.am                                  |    2 +
 TODO                                         |    6 ---
 man/systemd-networkd-wait-online.service.xml |    7 ++++
 src/libsystemd/sd-event/sd-event.c           |   10 +++++
 src/libsystemd/sd-rtnl/sd-rtnl.c             |   27 ++++++++++++++-
 src/network/networkd-manager.c               |   47 ++++++++++++++++++++++-----
 src/network/networkd-wait-online-manager.c   |   21 ++++++++++--
 src/network/networkd-wait-online.c           |   27 ++++++++++++---
 src/network/networkd-wait-online.h           |    2 -
 src/systemd/sd-rtnl.h                        |    1 
 units/systemd-networkd.service.in            |    1 
 units/systemd-networkd.socket                |   20 +++++++++++
 12 files changed, 146 insertions(+), 25 deletions(-)

New commits:
commit 5544ee85163733eaa50f598fcf3bd9421d4a42f9
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Feb 1 22:13:26 2015 +0100

    networkd: support socket activation
    
    Still keep the non-socket activation code around for starting from the commandline, but
    will likely drop that too in the future.

diff --git a/Makefile.am b/Makefile.am
index e3ba11c..fdadda7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5668,9 +5668,11 @@ tests += \
 
 nodist_systemunit_DATA += \
 	units/systemd-networkd.service \
+	units/systemd-networkd.socket \
 	units/systemd-networkd-wait-online.service
 
 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 \
 	$(systemunitdir)/systemd-networkd-wait-online.service $(pkgsysconfdir)/system/network-online.target.wants/systemd-networkd-wait-online.service
 
diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 767c583..45ba50a 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -74,7 +74,7 @@ int sd_rtnl_new_from_netlink(sd_rtnl **ret, int fd) {
 
         assert_return(ret, -EINVAL);
 
-        r = sd_rtnl_new(ret);
+        r = sd_rtnl_new(&rtnl);
         if (r < 0)
                 return r;
 
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 4c90434..49e353a 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -35,6 +35,7 @@
 #include "virt.h"
 
 #include "sd-rtnl.h"
+#include "sd-daemon.h"
 
 /* use 8 MB for receive socket kernel queue. */
 #define RCVBUF_SIZE    (8*1024*1024)
@@ -75,9 +76,33 @@ static int setup_default_address_pool(Manager *m) {
         return 0;
 }
 
+static int systemd_netlink_fd(int *ret) {
+        int n, fd, rtnl_fd = -1;
+
+        n = sd_listen_fds(true);
+        if (n <= 0)
+                return -EINVAL;
+
+        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
+                if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
+                        if (rtnl_fd >= 0)
+                                return -EINVAL;
+
+                        rtnl_fd = fd;
+                }
+        }
+
+        if (rtnl_fd < 0)
+                return -EINVAL;
+
+        *ret = rtnl_fd;
+
+        return 0;
+}
+
 int manager_new(Manager **ret) {
         _cleanup_manager_free_ Manager *m = NULL;
-        int r;
+        int r, fd;
 
         m = new0(Manager, 1);
         if (!m)
@@ -96,14 +121,20 @@ int manager_new(Manager **ret) {
         sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
         sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
-        r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
-                         RTNLGRP_IPV6_IFADDR);
-        if (r < 0)
-                return r;
+        if (systemd_netlink_fd(&fd) < 0) {
+                r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR,
+                                 RTNLGRP_IPV6_IFADDR);
+                if (r < 0)
+                        return r;
 
-        r = sd_rtnl_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
-        if (r < 0)
-                return r;
+                r = sd_rtnl_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
+                if (r < 0)
+                        return r;
+        } else {
+                r = sd_rtnl_new_from_netlink(&m->rtnl, fd);
+                if (r < 0)
+                        return r;
+        }
 
         r = sd_bus_default_system(&m->bus);
         if (r < 0 && r != -ENOENT) /* TODO: drop when we can rely on kdbus */
diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in
index fe92da2..fab278e 100644
--- a/units/systemd-networkd.service.in
+++ b/units/systemd-networkd.service.in
@@ -29,3 +29,4 @@ WatchdogSec=1min
 
 [Install]
 WantedBy=multi-user.target
+Also=systemd-networkd.socket
diff --git a/units/systemd-networkd.socket b/units/systemd-networkd.socket
new file mode 100644
index 0000000..d15ee9e
--- /dev/null
+++ b/units/systemd-networkd.socket
@@ -0,0 +1,20 @@
+#  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=networkd rtnetlink socket
+Documentation=man:systemd-networkd.service(8) man:rtnetlink(7)
+DefaultDependencies=no
+Before=sockets.target
+
+[Socket]
+ReceiveBuffer=8M
+ListenNetlink=route 273
+PassCredentials=yes
+
+[Install]
+WantedBy=sockets.target

commit a9944163fe5600bce85898dae78cd68442a6ff7c
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Feb 1 22:12:33 2015 +0100

    sd-rtnl: introduce sd_rtnl_new_from_netlink

diff --git a/src/libsystemd/sd-rtnl/sd-rtnl.c b/src/libsystemd/sd-rtnl/sd-rtnl.c
index 7f1ec30..767c583 100644
--- a/src/libsystemd/sd-rtnl/sd-rtnl.c
+++ b/src/libsystemd/sd-rtnl/sd-rtnl.c
@@ -67,6 +67,31 @@ static int sd_rtnl_new(sd_rtnl **ret) {
         return 0;
 }
 
+int sd_rtnl_new_from_netlink(sd_rtnl **ret, int fd) {
+        _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
+        socklen_t addrlen;
+        int r;
+
+        assert_return(ret, -EINVAL);
+
+        r = sd_rtnl_new(ret);
+        if (r < 0)
+                return r;
+
+        addrlen = sizeof(rtnl->sockaddr);
+
+        r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen);
+        if (r < 0)
+                return -errno;
+
+        rtnl->fd = fd;
+
+        *ret = rtnl;
+        rtnl = NULL;
+
+        return 0;
+}
+
 static bool rtnl_pid_changed(sd_rtnl *rtnl) {
         assert(rtnl);
 
@@ -126,7 +151,7 @@ static int rtnl_open_fd_ap(sd_rtnl **ret, int fd, unsigned n_groups, va_list ap)
 
         r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen);
         if (r < 0)
-                return r;
+                return -errno;
 
         rtnl->fd = fd;
 
diff --git a/src/systemd/sd-rtnl.h b/src/systemd/sd-rtnl.h
index 7919172..0eb5547 100644
--- a/src/systemd/sd-rtnl.h
+++ b/src/systemd/sd-rtnl.h
@@ -41,6 +41,7 @@ typedef struct sd_rtnl_message sd_rtnl_message;
 typedef int (*sd_rtnl_message_handler_t)(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata);
 
 /* bus */
+int sd_rtnl_new_from_netlink(sd_rtnl **nl, int fd);
 int sd_rtnl_open(sd_rtnl **nl, unsigned n_groups, ...);
 int sd_rtnl_open_fd(sd_rtnl **nl, int fd, unsigned n_groups, ...);
 int sd_rtnl_inc_rcvbuf(const sd_rtnl *const rtnl, const int size);

commit e56cdb7ae2657d62c9a8b6d3427382b209dff8e7
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Feb 1 21:04:35 2015 +0100

    networkd-wait-online: add timeout
    
    Default to timing out after 120 seconds without a network connection. Setting a
    timeout of 0 disables the timeout.

diff --git a/TODO b/TODO
index 1d9ca39..c7b530b 100644
--- a/TODO
+++ b/TODO
@@ -34,8 +34,6 @@ External:
 
 Features:
 
-* network-wait-online should have a configurable timeout, maybe as --timeout-usec=
-
 * The udev blkid built-in should expose a property that reflects
   whether media was sensed in USB CF/SD card readers. This should then
   be used to control SYSTEMD_READY=1/0 so that USB card readers aren't
@@ -156,8 +154,6 @@ Features:
 
 * timesyncd + resolved: add ugly bus calls to set NTP and DNS servers per-interface, for usage by NM
 
-* networkd-wait-online really should have a timeout by default
-
 * add infrastructure to allocate dynamic/transient users and UID ranges, for use in user-namespaced containers, per-seat gdm login screens and gdm guest sessions
 
 * machined: add an API so that libvirt-lxc can inform us about network interfaces being removed or added to an existing machine
diff --git a/man/systemd-networkd-wait-online.service.xml b/man/systemd-networkd-wait-online.service.xml
index 0cb41a3..4f039fe 100644
--- a/man/systemd-networkd-wait-online.service.xml
+++ b/man/systemd-networkd-wait-online.service.xml
@@ -90,6 +90,13 @@
                                 more than once to ignore multiple network interfaces.
                                 </para></listitem>
                         </varlistentry>
+                        <varlistentry>
+                                <term><option>--timeout=</option></term>
+                                <listitem><para>Fail the service if the network is not
+                                online by the time the timeout elapses. A timeout of 0
+                                disables the timeout. Defaults to 120 seconds.
+                                </para></listitem>
+                        </varlistentry>
                 </variablelist>
         </refsect1>
 
diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c
index d127372..cafe110 100644
--- a/src/network/networkd-wait-online-manager.c
+++ b/src/network/networkd-wait-online-manager.c
@@ -31,6 +31,7 @@
 #include "networkd-wait-online.h"
 
 #include "util.h"
+#include "time-util.h"
 
 bool manager_ignore_link(Manager *m, Link *link) {
         char **ignore;
@@ -262,7 +263,7 @@ static int manager_network_monitor_listen(Manager *m) {
         return 0;
 }
 
-int manager_new(Manager **ret, char **interfaces, char **ignore) {
+int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
 
@@ -282,6 +283,16 @@ int manager_new(Manager **ret, char **interfaces, char **ignore) {
         sd_event_add_signal(m->event, NULL, SIGTERM, NULL,  NULL);
         sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
 
+        if (timeout > 0) {
+                usec_t usec;
+
+                usec = now(clock_boottime_or_monotonic()) + timeout;
+
+                r = sd_event_add_time(m->event, NULL, clock_boottime_or_monotonic(), usec, 0, NULL, INT_TO_PTR(-ETIMEDOUT));
+                if (r < 0)
+                        return r;
+        }
+
         sd_event_set_watchdog(m->event, true);
 
         r = manager_network_monitor_listen(m);
diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c
index 826ab92..f0ca6de 100644
--- a/src/network/networkd-wait-online.c
+++ b/src/network/networkd-wait-online.c
@@ -28,6 +28,7 @@
 #include "build.h"
 
 static bool arg_quiet = false;
+static usec_t arg_timeout = 120 * USEC_PER_SEC;
 static char **arg_interfaces = NULL;
 static char **arg_ignore = NULL;
 
@@ -39,6 +40,7 @@ static void help(void) {
                "  -q --quiet                Do not show status information\n"
                "  -i --interface=INTERFACE  Block until at least these interfaces have appeared\n"
                "     --ignore=INTERFACE     Don't take these interfaces into account\n"
+               "     --timeout=SECS         Maximum time to wait for network connectivity\n"
                , program_invocation_short_name);
 }
 
@@ -47,6 +49,7 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_VERSION = 0x100,
                 ARG_IGNORE,
+                ARG_TIMEOUT,
         };
 
         static const struct option options[] = {
@@ -55,10 +58,11 @@ static int parse_argv(int argc, char *argv[]) {
                 { "quiet",           no_argument,       NULL, 'q'         },
                 { "interface",       required_argument, NULL, 'i'         },
                 { "ignore",          required_argument, NULL, ARG_IGNORE  },
+                { "timeout",         required_argument, NULL, ARG_TIMEOUT  },
                 {}
         };
 
-        int c;
+        int c, r;
 
         assert(argc >= 0);
         assert(argv);
@@ -92,6 +96,13 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
+                case ARG_TIMEOUT:
+                        r = parse_sec(optarg, &arg_timeout);
+                        if (r < 0)
+                                return r;
+
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -121,7 +132,7 @@ int main(int argc, char *argv[]) {
 
         assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
 
-        r = manager_new(&m, arg_interfaces, arg_ignore);
+        r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout);
         if (r < 0) {
                 log_error_errno(r, "Could not create manager: %m");
                 goto finish;
@@ -143,10 +154,16 @@ int main(int argc, char *argv[]) {
         }
 
 finish:
-        sd_notify(false, "STATUS=All interfaces configured...");
-
         strv_free(arg_interfaces);
         strv_free(arg_ignore);
 
-        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+        if (r >= 0) {
+                sd_notify(false, "STATUS=All interfaces configured...");
+
+                return EXIT_SUCCESS;
+        } else {
+                sd_notify(false, "STATUS=Failed waiting for network connectivity...");
+
+                return EXIT_FAILURE;
+        }
 }
diff --git a/src/network/networkd-wait-online.h b/src/network/networkd-wait-online.h
index eb78647..66b865c 100644
--- a/src/network/networkd-wait-online.h
+++ b/src/network/networkd-wait-online.h
@@ -49,7 +49,7 @@ struct Manager {
 };
 
 void manager_free(Manager *m);
-int manager_new(Manager **ret, char **interfaces, char **ignore);
+int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 

commit c4f1aff2306e4fb10efeda75f7015e5d043d4e8d
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Feb 1 18:06:40 2015 +0100

    sd-event: treat NULL callback for timer events like sig events
    
    In both cases exit the event loop.

diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index f9fa54d..25089a0 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -891,6 +891,12 @@ static int event_setup_timer_fd(
         return 0;
 }
 
+static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) {
+        assert(s);
+
+        return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata));
+}
+
 _public_ int sd_event_add_time(
                 sd_event *e,
                 sd_event_source **ret,
@@ -908,10 +914,12 @@ _public_ int sd_event_add_time(
         assert_return(e, -EINVAL);
         assert_return(usec != (uint64_t) -1, -EINVAL);
         assert_return(accuracy != (uint64_t) -1, -EINVAL);
-        assert_return(callback, -EINVAL);
         assert_return(e->state != SD_EVENT_FINISHED, -ESTALE);
         assert_return(!event_pid_changed(e), -ECHILD);
 
+        if (!callback)
+                callback = time_exit_callback;
+
         type = clock_to_event_source_type(clock);
         assert_return(type >= 0, -ENOTSUP);
 

commit 5d8689d749ffc50ade3d5c8598c1d3d11f5240f2
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Feb 1 15:13:17 2015 +0100

    networkd-wait-online: support globbing for ignored devices

diff --git a/TODO b/TODO
index e9615cc..1d9ca39 100644
--- a/TODO
+++ b/TODO
@@ -34,8 +34,6 @@ External:
 
 Features:
 
-* network-wait-online should support globbing for interfaces.
-
 * network-wait-online should have a configurable timeout, maybe as --timeout-usec=
 
 * The udev blkid built-in should expose a property that reflects
diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c
index c66470c..d127372 100644
--- a/src/network/networkd-wait-online-manager.c
+++ b/src/network/networkd-wait-online-manager.c
@@ -21,6 +21,7 @@
 
 #include <netinet/ether.h>
 #include <linux/if.h>
+#include <fnmatch.h>
 
 #include "rtnl-util.h"
 
@@ -32,14 +33,17 @@
 #include "util.h"
 
 bool manager_ignore_link(Manager *m, Link *link) {
+        char **ignore;
+
         assert(m);
         assert(link);
 
         if (link->flags & IFF_LOOPBACK)
                 return true;
 
-        if (strv_contains(m->ignore, link->ifname))
-                return true;
+        STRV_FOREACH(ignore, m->ignore)
+                if (fnmatch(*ignore, link->ifname, 0) == 0)
+                        return true;
 
         return false;
 }



More information about the systemd-commits mailing list