*/
#include "bpf-filter.hh"
#include "iputils.hh"
+#include "dolog.hh"
#ifdef HAVE_EBPF
#include <sys/syscall.h>
+#include <sys/resource.h>
#include <linux/bpf.h>
#include "ext/libbpf/libbpf.h"
throw std::runtime_error("Unsupported eBPF map format, the current internal implemenation only supports the legacy format");
}
+ struct rlimit old_limit;
+ const rlim_t new_limit_size = 1024 * 1024;
+
+ if (getrlimit(RLIMIT_MEMLOCK, &old_limit) != 0) {
+ throw std::runtime_error("Unable to get memory lock limit: " + stringerror());
+ }
+
+ /* Check if the current soft memlock limit is 64k */
+ if (old_limit.rlim_cur < (64 * 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 */
+
+ 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);
+ }
+
auto maps = d_maps.lock();
maps->d_v4 = BPFFilter::Map(configs["ipv4"], d_mapFormat);
In addition to the capabilities explained above, 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. It can also be done manually for testing purposes, in a non-permanent way, by using ``ulimit -l``.
+Large map sizes might also require an increase of ``RLIMIT_MEMLOCK``, which can be done by adding ``LimitMEMLOCK=limit`` in the systemd unit file, where limit is specified using byte as unit. It can also be done manually for testing purposes, in a non-permanent way, by using ``ulimit -l``.
+
+To change the default hard limit on ``RLIMIT_MEMLOCK`` add the following line to ``/etc/security/limits.conf`` for the user, specifying a limit in units of 1k, for example:
+ > $USER hard memlock 1024
External program, maps and XDP filtering
----------------------------------------
XDP programs are more powerful than eBPF socket filtering ones as they are not limited to accepting or denying a packet, but can immediately craft and send an answer. They are also executed a bit earlier in the kernel networking path so can provide better performance.
A sample program using the maps populated by dnsdist in an external XDP program can be found in the `contrib/ directory of our git repository <https://github.com/PowerDNS/pdns/tree/master/contrib>`__. That program supports answering with a TC=1 response instead of simply dropping the packet.
+