chiark / gitweb /
networkd: add support for Uplink Failure Detection
[elogind.git] / src / network / networkd-wait-online-manager.c
index 649a21c80c7949fd99cce8a23d3c92478717fab0..1c997a50a4b3f4c9790fb06d93f0ff67ca2b4201 100644 (file)
 
 #include <netinet/ether.h>
 #include <linux/if.h>
+#include <fnmatch.h>
 
 #include "rtnl-util.h"
 
-#include "network-util.h"
 #include "network-internal.h"
 #include "networkd-wait-online-link.h"
 #include "networkd-wait-online.h"
 
 #include "util.h"
+#include "time-util.h"
+
+bool manager_ignore_link(Manager *m, Link *link) {
+        char **ignore;
+
+        assert(m);
+        assert(link);
+
+        if (link->flags & IFF_LOOPBACK)
+                return true;
+
+        STRV_FOREACH(ignore, m->ignore)
+                if (fnmatch(*ignore, link->ifname, 0) == 0)
+                        return true;
+
+        return false;
+}
 
 bool manager_all_configured(Manager *m) {
         Iterator i;
@@ -37,7 +54,7 @@ bool manager_all_configured(Manager *m) {
         char **ifname;
         bool one_ready = false;
 
-        /* wait for all the links given on the commandline to appear */
+        /* wait for all the links given on the command line to appear */
         STRV_FOREACH(ifname, m->interfaces) {
                 l = hashmap_get(m->links_by_name, *ifname);
                 if (!l) {
@@ -49,8 +66,8 @@ bool manager_all_configured(Manager *m) {
         /* wait for all links networkd manages to be in admin state 'configured'
            and at least one link to gain a carrier */
         HASHMAP_FOREACH(l, m->links, i) {
-                if (!link_relevant(l)) {
-                        log_info("ignore irrelevant link: %s", l->ifname);
+                if (manager_ignore_link(m, l)) {
+                        log_info("ignoring: %s", l->ifname);
                         continue;
                 }
 
@@ -80,7 +97,7 @@ static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userda
         Manager *m = userdata;
         uint16_t type;
         Link *l;
-        char *ifname;
+        const char *ifname;
         int ifindex, r;
 
         assert(rtnl);
@@ -134,7 +151,7 @@ static int manager_process_link(sd_rtnl *rtnl, sd_rtnl_message *mm, void *userda
         return 0;
 
 fail:
-        log_warning("Failed to process RTNL link message: %s", strerror(-r));
+        log_warning_errno(r, "Failed to process RTNL link message: %m");
         return 0;
 }
 
@@ -159,7 +176,7 @@ static int manager_rtnl_listen(Manager *m) {
 
         assert(m);
 
-        /* First, subscibe to interfaces coming and going */
+        /* First, subscribe to interfaces coming and going */
         r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
         if (r < 0)
                 return r;
@@ -211,7 +228,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
         HASHMAP_FOREACH(l, m->links, i) {
                 r = link_update_monitor(l);
                 if (r < 0)
-                        log_warning("Failed to update monitor information for %i: %s", l->ifindex, strerror(-r));
+                        log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex);
         }
 
         if (manager_all_configured(m))
@@ -245,7 +262,7 @@ static int manager_network_monitor_listen(Manager *m) {
         return 0;
 }
 
-int manager_new(Manager **ret, char **interfaces) {
+int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout) {
         _cleanup_(manager_freep) Manager *m = NULL;
         int r;
 
@@ -256,6 +273,7 @@ int manager_new(Manager **ret, char **interfaces) {
                 return -ENOMEM;
 
         m->interfaces = interfaces;
+        m->ignore = ignore;
 
         r = sd_event_default(&m->event);
         if (r < 0)
@@ -264,6 +282,16 @@ int manager_new(Manager **ret, char **interfaces) {
         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);