]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: limit the number of routes to the kernel limit (#4007)
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 21 Aug 2016 13:06:28 +0000 (09:06 -0400)
committerLennart Poettering <lennart@poettering.net>
Sun, 21 Aug 2016 13:06:28 +0000 (15:06 +0200)
Fixes #3922.

src/network/networkd-route.c

index b197a5da6b390ac7f54220eae4790fafbed1991e..6f60ee5e31525a91e15b8f50b4ad042e50f73c5d 100644 (file)
 #include "parse-util.h"
 #include "set.h"
 #include "string-util.h"
+#include "sysctl-util.h"
 #include "util.h"
 
-#define ROUTES_PER_LINK_MAX 2048U
-#define STATIC_ROUTES_PER_NETWORK_MAX 1024U
+#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
+
+static unsigned routes_max(void) {
+        static thread_local unsigned cached = 0;
+
+        _cleanup_free_ char *s4 = NULL, *s6 = NULL;
+        unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY;
+
+        if (cached > 0)
+                return cached;
+
+        if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) {
+                truncate_nl(s4);
+                if (safe_atou(s4, &val4) >= 0 &&
+                    val4 == 2147483647U)
+                        /* This is the default "no limit" value in the kernel */
+                        val4 = ROUTES_DEFAULT_MAX_PER_FAMILY;
+        }
+
+        if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) {
+                truncate_nl(s6);
+                (void) safe_atou(s6, &val6);
+        }
+
+        cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) +
+                 MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6);
+        return cached;
+}
 
 int route_new(Route **ret) {
         _cleanup_route_free_ Route *route = NULL;
@@ -67,7 +94,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
                 }
         }
 
-        if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX)
+        if (network->n_static_routes >= routes_max())
                 return -E2BIG;
 
         r = route_new(&route);
@@ -484,7 +511,7 @@ int route_configure(
         assert(route->family == AF_INET || route->family == AF_INET6);
 
         if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
-            set_size(link->routes) >= ROUTES_PER_LINK_MAX)
+            set_size(link->routes) >= routes_max())
                 return -E2BIG;
 
         r = sd_rtnl_message_new_route(link->manager->rtnl, &req,