-
Notifications
You must be signed in to change notification settings - Fork 915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
dnsdist: Raise RLIMIT_MEMLOCK automatically when eBPF is requested #11554
dnsdist: Raise RLIMIT_MEMLOCK automatically when eBPF is requested #11554
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good, I made a few suggestions that are pretty much all around logging, nothing serious. Thanks a lot!
423cc11
to
f24884b
Compare
f24884b
to
569787b
Compare
pdns/bpf-filter.cc
Outdated
@@ -320,6 +322,25 @@ BPFFilter::BPFFilter(std::unordered_map<std::string, MapConfiguration>& configs, | |||
throw std::runtime_error("Unsupported eBPF map format, the current internal implemenation only supports the legacy format"); | |||
} | |||
|
|||
struct rlimit old_limit; | |||
const size_t new_limit_size = 1073741824; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, if the target is 1024k, should that number be 1048576
? And for the 64k check, 65536
instead of 67108865
? If so, I guess we also need to change the $USER hard memlock 1073741824
line in the documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rlim_cur and rlim_max returned by getrlimit is a multiplied value of 64k, actually multiplying it by 1024. While what we set in limit.conf is exact value as you mentioned. So I should change in the documentation, but will check in the code what the getrlimit function call returns and why is the value different from what I get from ulimit -a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ulimit
uses memory sizes in kbytes. getrlimit
and setrlimit
use bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused, are we trying to raise the limit to 1024 kilobytes or more? If we are trying to raise it to 1024 kilobytes, I believe we need to replace 1024 * 1024 * 1024
by 1024 * 1024
and, 64 * 1024 * 1024
by 64 * 1024
, right?
569787b
to
5ac199f
Compare
5ac199f
to
e571a15
Compare
pdns/bpf-filter.cc
Outdated
throw std::runtime_error("Unable to get memory lock limit: " + stringerror()); | ||
} | ||
|
||
/* Check if the current soft memlock limit is 64k */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comments and code do not match. k or M?
pdns/bpf-filter.cc
Outdated
/* Check if the current soft memlock limit is 64k */ | ||
if (old_limit.rlim_cur < (64 * 1024 * 1024)) { | ||
struct rlimit new_limit; | ||
new_limit.rlim_cur = new_limit_size; /* Increase soft limit to 1024k */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: code and comment do not match.
pdns/bpf-filter.cc
Outdated
if (old_limit.rlim_cur < (64 * 1024 * 1024)) { | ||
struct rlimit new_limit; | ||
new_limit.rlim_cur = new_limit_size; /* Increase soft limit to 1024k */ | ||
new_limit.rlim_max = new_limit_size; /* Increase hard limit to 1024k */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rasing the hard limit will fail for non-root. Or are we always root at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For eBPF filter I think we need to be root at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might only have CAP_BPF
at this point, but failing is OK as long as we keep going on IMHO.
@@ -73,3 +73,6 @@ Since 1.6.0, the default BPF filter set via :func:`setDefaultBPFFilter` will aut | |||
That feature might require an increase of the memory limit associated to a socket, via the sysctl setting ``net.core.optmem_max``. | |||
When attaching an eBPF program to a socket, the size of the program is checked against this limit, and the default value might not be enough. | |||
Large map sizes might also require an increase of ``RLIMIT_MEMLOCK``, which can be done by adding ``LimitMEMLOCK=infinity`` in the systemd unit file. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like infinity limits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not going ahead with infinity limit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
infinity
is still mentioned on line 75.
Also: there is a unit confusion here: the code in bpf-filter.cc
uses 1 mega byte (setrlimit
's unit is bytes), while the /security/limits.conf
example set the limit to 1GB (it uses 1k byte as unit).
Note that LimitMEMLOCK
in a systemd unit file uses bytes as unit.
e571a15
to
877673c
Compare
877673c
to
8f29b09
Compare
8f29b09
to
d418ba4
Compare
Raise RLIMIT_MEMLOCK automatically when eBPF is requested. This PR adds changes to eBPF filter constructor which when invoked automatically raises the RLIMIT_MEMLOCK from 64k to 1024k. The hard limit for the user needs to be set in `/etc/security/limits.conf`.
d418ba4
to
dc22be5
Compare
Rebased to fix conflicts and adapted slightly. |
pdns/bpf-filter.cc
Outdated
} | ||
|
||
/* Check if the current soft memlock limit is 64k */ | ||
if (old_limit.rlim_cur < (64 * 1024)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we will only raise the limit when it is below 64k, right? But we know 64k is not enough, so perhaps it would make sense to try to raise it if it is below 1024k instead?
pdns/bpf-filter.cc
Outdated
if (old_limit.rlim_cur < (64 * 1024 * 1024)) { | ||
struct rlimit new_limit; | ||
new_limit.rlim_cur = new_limit_size; /* Increase soft limit to 1024k */ | ||
new_limit.rlim_max = new_limit_size; /* Increase hard limit to 1024k */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might only have CAP_BPF
at this point, but failing is OK as long as we keep going on IMHO.
pdns/bpf-filter.cc
Outdated
new_limit.rlim_max = new_limit_size; /* Increase hard limit to 1024k */ | ||
|
||
if (setrlimit(RLIMIT_MEMLOCK, &new_limit) != 0) { | ||
errlog("Unable to raise the maximum amount of locked memory for eBPF from %d to %d, consider raising RLIMIT_MEMLOCK or setting LimitMEMLOCK=infinity in the systemd unit: %s", old_limit.rlim_cur, new_limit.rlim_cur, stringerror()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
errlog("Unable to raise the maximum amount of locked memory for eBPF from %d to %d, consider raising RLIMIT_MEMLOCK or setting LimitMEMLOCK=infinity in the systemd unit: %s", old_limit.rlim_cur, new_limit.rlim_cur, stringerror()); | |
warnlog("Unable to raise the maximum amount of locked memory for eBPF from %d to %d, consider raising RLIMIT_MEMLOCK or setting LimitMEMLOCK=infinity in the systemd unit: %s", old_limit.rlim_cur, new_limit.rlim_cur, stringerror()); |
pdns/bpf-filter.cc
Outdated
if (setrlimit(RLIMIT_MEMLOCK, &new_limit) != 0) { | ||
errlog("Unable to raise the maximum amount of locked memory for eBPF from %d to %d, consider raising RLIMIT_MEMLOCK or setting LimitMEMLOCK=infinity in the systemd unit: %s", old_limit.rlim_cur, new_limit.rlim_cur, stringerror()); | ||
} | ||
infolog("The current limit of locked memory (soft: %d, hard: %d) is too low for eBPF, trying to raise it to %d", old_limit.rlim_cur, old_limit.rlim_max, new_limit_size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should move that comment before the setrlimit
call, otherwise we might log the failure before the attempt.
1e48578
to
ad97958
Compare
pdns/bpf-filter.cc
Outdated
const rlim_t new_limit_size = 1024 * 1024; | ||
|
||
/* Check if the current soft memlock limit is at least minimal_limit */ | ||
if (old_limit.rlim_cur < minimal_limit_size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not very useful to raise the limit if the current value is below 64k, as most systems set RLIMIT_MEMLOCK
to exactly 64k, and we know this is not enough for most usage (decent-sized maps). How about we try to raise that value to 1024k if it is below 1024k?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense indeed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks very good, thanks!
One unrelated CI failure. |
Short Description:
Raise RLIMIT_MEMLOCK automatically when eBPF is requested.
#10566
This PR adds changes to eBPF filter constructor which when invoked automatically raises the RLIMIT_MEMLOCK from 64k to 1024k.
The hard limit for the user needs to be set in
/etc/security/limits.conf
.Checklist
I have: