tools: bpftool: adjust rlimit RLIMIT_MEMLOCK when loading programs, maps
authorQuentin Monnet <quentin.monnet@netronome.com>
Wed, 7 Nov 2018 12:29:30 +0000 (12:29 +0000)
committerDaniel Borkmann <daniel@iogearbox.net>
Wed, 7 Nov 2018 21:22:21 +0000 (22:22 +0100)
The limit for memory locked in the kernel by a process is usually set to
64 kbytes by default. This can be an issue when creating large BPF maps
and/or loading many programs. A workaround is to raise this limit for
the current process before trying to create a new BPF map. Changing the
hard limit requires the CAP_SYS_RESOURCE and can usually only be done by
root user (for non-root users, a call to setrlimit fails (and sets
errno) and the program simply goes on with its rlimit unchanged).

There is no API to get the current amount of memory locked for a user,
therefore we cannot raise the limit only when required. One solution,
used by bcc, is to try to create the map, and on getting a EPERM error,
raising the limit to infinity before giving another try. Another
approach, used in iproute2, is to raise the limit in all cases, before
trying to create the map.

Here we do the same as in iproute2: the rlimit is raised to infinity
before trying to load programs or to create maps with bpftool.

Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
tools/bpf/bpftool/common.c
tools/bpf/bpftool/main.h
tools/bpf/bpftool/map.c
tools/bpf/bpftool/prog.c

index 25af85304ebee3b073d9e7d0036038c5c4c05d68..1149565be4b168a97ce862e13c1512e3f1fbe8f0 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/magic.h>
 #include <net/if.h>
 #include <sys/mount.h>
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/vfs.h>
@@ -99,6 +100,13 @@ static bool is_bpffs(char *path)
        return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
 }
 
+void set_max_rlimit(void)
+{
+       struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
+
+       setrlimit(RLIMIT_MEMLOCK, &rinf);
+}
+
 static int mnt_bpffs(const char *target, char *buff, size_t bufflen)
 {
        bool bind_done = false;
index 28322ace285653f91a9fe42e69a29483b0a1280b..14857c273bf67656444674c486cbebae0384be2e 100644 (file)
@@ -100,6 +100,8 @@ bool is_prefix(const char *pfx, const char *str);
 void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
 void usage(void) __noreturn;
 
+void set_max_rlimit(void);
+
 struct pinned_obj_table {
        DECLARE_HASHTABLE(table, 16);
 };
index 7bf38f0e152e07054abfa761c945a7a85a1b239a..101b8a8812259046c2f1a1754e73dcc9e76e901f 100644 (file)
@@ -1140,6 +1140,8 @@ static int do_create(int argc, char **argv)
                return -1;
        }
 
+       set_max_rlimit();
+
        fd = bpf_create_map_xattr(&attr);
        if (fd < 0) {
                p_err("map create failed: %s", strerror(errno));
index 5302ee282409eb039458447ad40215f24516c48a..b9b84553bec446b6a969bcc296b49f7caa7e4963 100644 (file)
@@ -995,6 +995,8 @@ static int do_load(int argc, char **argv)
                goto err_close_obj;
        }
 
+       set_max_rlimit();
+
        err = bpf_object__load(obj);
        if (err) {
                p_err("failed to load object file");