From: Mark Stapp Date: Tue, 17 Nov 2020 18:30:05 +0000 (-0500) Subject: lib: add startup option to limit fds X-Git-Tag: base_7.6~225^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=refs%2Fpull%2F7546%2Fhead;p=mirror%2Ffrr.git lib: add startup option to limit fds 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 --- diff --git a/doc/user/basic.rst b/doc/user/basic.rst index 7a450bec53..4d34c82895 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -712,6 +712,12 @@ These options apply to all |PACKAGE_NAME| daemons. Enable the transactional CLI mode. +.. option:: --limit-fds + + 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 diff --git a/lib/libfrr.c b/lib/libfrr.c index 800596c563..8e7777a1a9 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -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:\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) diff --git a/lib/libfrr.h b/lib/libfrr.h index ab72299206..2e4dcbe093 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -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)) diff --git a/lib/thread.c b/lib/thread.c index e71fd74bd9..c886058355 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -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);