]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add startup option to limit fds 7546/head
authorMark Stapp <mjs@voltanet.io>
Tue, 17 Nov 2020 18:30:05 +0000 (13:30 -0500)
committerMark Stapp <mjs@voltanet.io>
Wed, 18 Nov 2020 20:34:35 +0000 (15:34 -0500)
Add a startup-time option to limit the number of fds used
by the thread/event infrastructure. If nothing is configured,
the system ulimit is used.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
doc/user/basic.rst
lib/libfrr.c
lib/libfrr.h
lib/thread.c

index 7a450bec53a193190d7466c032fee3705208d8a8..4d34c828959cb07eb04e2ef9b9ae023929b3a70e 100644 (file)
@@ -712,6 +712,12 @@ These options apply to all |PACKAGE_NAME| daemons.
 
    Enable the transactional CLI mode.
 
+.. option:: --limit-fds <number>
+
+   Limit the number of file descriptors that will be used internally
+   by the FRR daemons. By default, the daemons use the system ulimit
+   value.
+
 .. _loadable-module-support:
 
 Loadable Module Support
index 800596c5639b9e8d1be1e6b41ce110c0890d1d6a..8e7777a1a9dd62624387f66ca0ab5ef0fe1e3ac9 100644 (file)
@@ -99,6 +99,7 @@ static void opt_extend(const struct optspec *os)
 #define OPTION_TCLI      1005
 #define OPTION_DB_FILE   1006
 #define OPTION_LOGGING   1007
+#define OPTION_LIMIT_FDS 1008
 
 static const struct option lo_always[] = {
        {"help", no_argument, NULL, 'h'},
@@ -113,6 +114,7 @@ static const struct option lo_always[] = {
        {"log-level", required_argument, NULL, OPTION_LOGLEVEL},
        {"tcli", no_argument, NULL, OPTION_TCLI},
        {"command-log-always", no_argument, NULL, OPTION_LOGGING},
+       {"limit-fds", required_argument, NULL, OPTION_LIMIT_FDS},
        {NULL}};
 static const struct optspec os_always = {
        "hvdM:F:N:",
@@ -126,7 +128,8 @@ static const struct optspec os_always = {
        "      --moduledir    Override modules directory\n"
        "      --log          Set Logging to stdout, syslog, or file:<name>\n"
        "      --log-level    Set Logging Level to use, debug, info, warn, etc\n"
-       "      --tcli         Use transaction-based CLI\n",
+       "      --tcli         Use transaction-based CLI\n"
+       "      --limit-fds    Limit number of fds supported\n",
        lo_always};
 
 
@@ -552,6 +555,9 @@ static int frr_opt(int opt)
        case OPTION_LOGGING:
                di->log_always = true;
                break;
+       case OPTION_LIMIT_FDS:
+               di->limit_fds = strtoul(optarg, &err, 0);
+               break;
        default:
                return 1;
        }
@@ -739,6 +745,11 @@ enum frr_cli_mode frr_get_cli_mode(void)
        return di ? di->cli_mode : FRR_CLI_CLASSIC;
 }
 
+uint32_t frr_get_fd_limit(void)
+{
+       return di ? di->limit_fds : 0;
+}
+
 static int rcvd_signal = 0;
 
 static void rcv_signal(int signum)
index ab72299206c959220702ff979708e712ad8e684a..2e4dcbe0935b63a760c51af7a2f13e5378b83ce1 100644 (file)
@@ -102,6 +102,9 @@ struct frr_daemon_info {
        size_t n_yang_modules;
 
        bool log_always;
+
+       /* Optional upper limit on the number of fds used in select/poll */
+       uint32_t limit_fds;
 };
 
 /* execname is the daemon's executable (and pidfile and configfile) name,
@@ -134,6 +137,7 @@ extern __attribute__((__noreturn__)) void frr_help_exit(int status);
 extern struct thread_master *frr_init(void);
 extern const char *frr_get_progname(void);
 extern enum frr_cli_mode frr_get_cli_mode(void);
+uint32_t frr_get_fd_limit(void);
 
 DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm))
 DECLARE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm))
index e71fd74bd96f1774642a91eee95863e35b288eaf..c88605835589fa6e5d5604c0d98802b7d2cb1fbc 100644 (file)
@@ -36,6 +36,7 @@
 #include "frr_pthread.h"
 #include "lib_errors.h"
 #include "libfrr_trace.h"
+#include "libfrr.h"
 
 DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread")
 DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master")
@@ -442,8 +443,14 @@ struct thread_master *thread_master_create(const char *name)
        rv->name = XSTRDUP(MTYPE_THREAD_MASTER, name);
 
        /* Initialize I/O task data structures */
-       getrlimit(RLIMIT_NOFILE, &limit);
-       rv->fd_limit = (int)limit.rlim_cur;
+
+       /* Use configured limit if present, ulimit otherwise. */
+       rv->fd_limit = frr_get_fd_limit();
+       if (rv->fd_limit == 0) {
+               getrlimit(RLIMIT_NOFILE, &limit);
+               rv->fd_limit = (int)limit.rlim_cur;
+       }
+
        rv->read = XCALLOC(MTYPE_THREAD_POLL,
                           sizeof(struct thread *) * rv->fd_limit);