Skip to content

Commit

Permalink
Automatically bump memlock ulimit
Browse files Browse the repository at this point in the history
Instead of requiring the user to bump the ulimit in their shell before
starting a bcc script, try to setrlimit automatically when a failure
occurs. Since there is no getrusage for memlock limit, unfortunately we
have to brute force setting the limit. For now, just try bpf() once and
then try to set unlimited ulimit, then try bpf() again.

Fixes: iovisor#281
Signed-off-by: Brenden Blanco <[email protected]>
  • Loading branch information
Brenden Blanco committed Nov 30, 2015
1 parent ee8e543 commit 4b4bd27
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 3 deletions.
33 changes: 32 additions & 1 deletion src/cc/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <unistd.h>

#include "libbpf.h"
Expand Down Expand Up @@ -67,7 +68,19 @@ int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size, int
attr.value_size = value_size;
attr.max_entries = max_entries;

return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
int ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
if (ret < 0 && errno == EPERM) {
// see note below about the rationale for this retry

struct rlimit rl = {};
if (getrlimit(RLIMIT_MEMLOCK, &rl) == 0) {
rl.rlim_max = RLIM_INFINITY;
rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0)
ret = syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
}
}
return ret;
}

int bpf_update_elem(int fd, void *key, void *value, unsigned long long flags)
Expand Down Expand Up @@ -138,6 +151,24 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
log_buf[0] = 0;

int ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
if (ret < 0 && errno == EPERM) {
// When EPERM is returned, two reasons are possible:
// 1. user has no permissions for bpf()
// 2. user has insufficent rlimit for locked memory
// Unfortunately, there is no api to inspect the current usage of locked
// mem for the user, so an accurate calculation of how much memory to lock
// for this new program is difficult to calculate. As a hack, bump the limit
// to unlimited. If program load fails again, return the error.

struct rlimit rl = {};
if (getrlimit(RLIMIT_MEMLOCK, &rl) == 0) {
rl.rlim_max = RLIM_INFINITY;
rl.rlim_cur = rl.rlim_max;
if (setrlimit(RLIMIT_MEMLOCK, &rl) == 0)
ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}
}

if (ret < 0 && !log_buf) {
// caller did not specify log_buf but failure should be printed,
// so call recursively and print the result to stderr
Expand Down
4 changes: 2 additions & 2 deletions tests/wrapper.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ function ns_run() {
sudo ip netns exec $ns ethtool -K eth0 tx off
sudo ip addr add dev $ns.out 172.16.1.1/24
sudo ip link set $ns.out up
sudo bash -c "ulimit -l 10240; PYTHONPATH=$PYTHONPATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH ip netns exec $ns $cmd $1 $2"
sudo bash -c "PYTHONPATH=$PYTHONPATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH ip netns exec $ns $cmd $1 $2"
return $?
}
function sudo_run() {
sudo bash -c "ulimit -l 10240; PYTHONPATH=$PYTHONPATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH $cmd $1 $2"
sudo bash -c "PYTHONPATH=$PYTHONPATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH $cmd $1 $2"
return $?
}
function simple_run() {
Expand Down

0 comments on commit 4b4bd27

Please sign in to comment.