summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Stapp <mjs@voltanet.io>2020-11-17 13:30:05 -0500
committerMark Stapp <mjs@voltanet.io>2020-11-18 15:34:35 -0500
commit1a9f340b6b63cbb9e19fc1372ef01e265d529e45 (patch)
treebeae6c483a575ad05062c57aba2fa2fa6800eab0
parent85dcff6e412e5569dede949899d28f536c95ba98 (diff)
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 <mjs@voltanet.io>
-rw-r--r--doc/user/basic.rst6
-rw-r--r--lib/libfrr.c13
-rw-r--r--lib/libfrr.h4
-rw-r--r--lib/thread.c11
4 files changed, 31 insertions, 3 deletions
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 <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
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:<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)
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);