[Babel-users] [PATCH v2] Smarter sysctl handling

Toke Høiland-Jørgensen toke at toke.dk
Mon Aug 10 22:34:43 UTC 2015


Babeld will exit with a fatal error if it is unable to write sysctls.
When running in a container, however, /proc/sys may be mounted
read-only, which causes babeld to fail.

This patch adds a config option to consider sysctl failures as
non-fatal. If the option is set, the daemon won't fail to start when
unable to set the knobs.

In addition, the patch adds checks for whether each sysctl is already at
the desired value, in which case it will not be set.

Signed-off-by: Toke Høiland-Jørgensen <toke at toke.dk>
---
 babeld.c         |  1 +
 babeld.h         |  1 +
 babeld.man       |  5 ++++
 configuration.c  |  3 +++
 kernel_netlink.c | 77 +++++++++++++++++++++++++++++++++-----------------------
 5 files changed, 55 insertions(+), 32 deletions(-)

diff --git a/babeld.c b/babeld.c
index 943f042..0e2266a 100644
--- a/babeld.c
+++ b/babeld.c
@@ -67,6 +67,7 @@ int default_wired_hello_interval = -1;
 int resend_delay = -1;
 int random_id = 0;
 int do_daemonise = 0;
+int sysctl_nonfatal = 0;
 const char *logfile = NULL,
     *pidfile = "/var/run/babeld.pid",
     *state_file = "/var/lib/babel-state";
diff --git a/babeld.h b/babeld.h
index 92ce9b5..c1f26fe 100644
--- a/babeld.h
+++ b/babeld.h
@@ -86,6 +86,7 @@ extern time_t reboot_time;
 extern int default_wireless_hello_interval, default_wired_hello_interval;
 extern int resend_delay;
 extern int random_id;
+extern int sysctl_nonfatal;
 extern int do_daemonise;
 extern const char *logfile, *pidfile, *state_file;
 extern int link_detect;
diff --git a/babeld.man b/babeld.man
index ec600c2..7fd2888 100644
--- a/babeld.man
+++ b/babeld.man
@@ -253,6 +253,11 @@ This specifies whether to daemonize at startup, and is equivalent to
 the command-line option
 .BR \-D .
 .TP
+.BR sysctl-nonfatal " {" true | false }
+This controls whether to consider failures writing to sysctl as fatal. If set,
+warn of the failures, but continue running. This is useful when running babeld
+on a system that mounts /proc/sys as read-only (for instance, in a container).
+.TP
 .BI state-file " filename"
 This specifies the name of the file used for preserving long-term
 information between invocations of the
diff --git a/configuration.c b/configuration.c
index 6a9c09d..571e220 100644
--- a/configuration.c
+++ b/configuration.c
@@ -691,6 +691,7 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
               strcmp(token, "link-detect") == 0 ||
               strcmp(token, "random-id") == 0 ||
               strcmp(token, "daemonise") == 0 ||
+              strcmp(token, "sysctl-nonfatal") == 0 ||
               strcmp(token, "ipv6-subtrees") == 0 ||
               strcmp(token, "reflect-kernel-metric") == 0) {
         int b;
@@ -706,6 +707,8 @@ parse_option(int c, gnc_t gnc, void *closure, char *token)
             random_id = b;
         else if(strcmp(token, "daemonise") == 0)
             do_daemonise = b;
+        else if(strcmp(token, "sysctl-nonfatal") == 0)
+            sysctl_nonfatal = b;
         else if(strcmp(token, "ipv6-subtrees") == 0)
             has_ipv6_subtrees = b;
         else if(strcmp(token, "reflect-kernel-metric") == 0)
diff --git a/kernel_netlink.c b/kernel_netlink.c
index ab63d33..173a6a1 100644
--- a/kernel_netlink.c
+++ b/kernel_netlink.c
@@ -480,6 +480,11 @@ netlink_send_dump(int type, void *data, int len) {
     return 0;
 }
 
+#define WANT_FORWARDING 1
+#define WANT_IPV4_FORWARDING 1
+#define WANT_ACCEPT_REDIRECTS 0
+#define WANT_RP_FILTER 0
+
 int
 kernel_setup(int setup)
 {
@@ -505,54 +510,62 @@ kernel_setup(int setup)
 
         old_forwarding = read_proc("/proc/sys/net/ipv6/conf/all/forwarding");
         if(old_forwarding < 0) {
-            perror("Couldn't read forwarding knob.");
+            perror("Couldn't read forwarding knob");
             return -1;
         }
 
-        rc = write_proc("/proc/sys/net/ipv6/conf/all/forwarding", 1);
-        if(rc < 0) {
-            perror("Couldn't write forwarding knob.");
-            return -1;
+        if(old_forwarding != WANT_FORWARDING) {
+            rc = write_proc("/proc/sys/net/ipv6/conf/all/forwarding", WANT_FORWARDING);
+            if(rc < 0) {
+                perror("Couldn't write forwarding knob");
+                if(!sysctl_nonfatal) return -1;
+            }
         }
 
         old_ipv4_forwarding =
             read_proc("/proc/sys/net/ipv4/conf/all/forwarding");
         if(old_ipv4_forwarding < 0) {
-            perror("Couldn't read IPv4 forwarding knob.");
+            perror("Couldn't read IPv4 forwarding knob");
             return -1;
         }
 
-        rc = write_proc("/proc/sys/net/ipv4/conf/all/forwarding", 1);
-        if(rc < 0) {
-            perror("Couldn't write IPv4 forwarding knob.");
-            return -1;
+        if(old_ipv4_forwarding != WANT_IPV4_FORWARDING) {
+            rc = write_proc("/proc/sys/net/ipv4/conf/all/forwarding", WANT_IPV4_FORWARDING);
+            if(rc < 0) {
+                perror("Couldn't write IPv4 forwarding knob");
+                if(!sysctl_nonfatal) return -1;
+            }
         }
 
 
         old_accept_redirects =
             read_proc("/proc/sys/net/ipv6/conf/all/accept_redirects");
         if(old_accept_redirects < 0) {
-            perror("Couldn't read accept_redirects knob.");
+            perror("Couldn't read accept_redirects knob");
             return -1;
         }
 
-        rc = write_proc("/proc/sys/net/ipv6/conf/all/accept_redirects", 0);
-        if(rc < 0) {
-            perror("Couldn't write accept_redirects knob.");
-            return -1;
+        if(old_accept_redirects != WANT_ACCEPT_REDIRECTS) {
+            rc = write_proc("/proc/sys/net/ipv6/conf/all/accept_redirects", WANT_ACCEPT_REDIRECTS);
+            if(rc < 0) {
+                perror("Couldn't write accept_redirects knob");
+                if(!sysctl_nonfatal) return -1;
+            }
         }
 
         old_rp_filter =
             read_proc("/proc/sys/net/ipv4/conf/all/rp_filter");
         if(old_rp_filter < 0) {
-            perror("Couldn't read rp_filter knob.");
+            perror("Couldn't read rp_filter knob");
             return -1;
         }
 
-        rc = write_proc("/proc/sys/net/ipv4/conf/all/rp_filter", 0);
-        if(rc < 0) {
-            perror("Couldn't write rp_filter knob.");
-            return -1;
+        if(old_rp_filter != WANT_RP_FILTER) {
+            rc = write_proc("/proc/sys/net/ipv4/conf/all/rp_filter", WANT_RP_FILTER);
+            if(rc < 0) {
+                perror("Couldn't write rp_filter knob");
+                if(!sysctl_nonfatal) return -1;
+            }
         }
 
         return 1;
@@ -561,39 +574,39 @@ kernel_setup(int setup)
         close(dgram_socket);
         dgram_socket = -1;
 
-        if(old_forwarding >= 0) {
+        if(old_forwarding >= 0 && old_forwarding != WANT_FORWARDING) {
             rc = write_proc("/proc/sys/net/ipv6/conf/all/forwarding",
                             old_forwarding);
             if(rc < 0) {
-                perror("Couldn't write forwarding knob.\n");
-                return -1;
+                perror("Couldn't write forwarding knob");
+                if(!sysctl_nonfatal) return -1;
             }
         }
 
-        if(old_ipv4_forwarding >= 0) {
+        if(old_ipv4_forwarding >= 0 && old_ipv4_forwarding != WANT_IPV4_FORWARDING) {
             rc = write_proc("/proc/sys/net/ipv4/conf/all/forwarding",
                             old_ipv4_forwarding);
             if(rc < 0) {
-                perror("Couldn't write IPv4 forwarding knob.\n");
-                return -1;
+                perror("Couldn't write IPv4 forwarding knob");
+                if(!sysctl_nonfatal) return -1;
             }
         }
 
-        if(old_accept_redirects >= 0) {
+        if(old_accept_redirects >= 0 && old_accept_redirects != WANT_ACCEPT_REDIRECTS) {
             rc = write_proc("/proc/sys/net/ipv6/conf/all/accept_redirects",
                             old_accept_redirects);
             if(rc < 0) {
-                perror("Couldn't write accept_redirects knob.\n");
-                return -1;
+                perror("Couldn't write accept_redirects knob");
+                if(!sysctl_nonfatal) return -1;
             }
         }
 
-        if(old_rp_filter >= 0) {
+        if(old_rp_filter >= 0 && old_rp_filter != WANT_RP_FILTER) {
             rc = write_proc("/proc/sys/net/ipv4/conf/all/rp_filter",
                             old_rp_filter);
             if(rc < 0) {
-                perror("Couldn't write rp_filter knob.\n");
-                return -1;
+                perror("Couldn't write rp_filter knob");
+                if(!sysctl_nonfatal) return -1;
             }
         }
 
-- 
2.5.0



More information about the Babel-users mailing list