diff --git a/Knot.files b/Knot.files
index 60cab572ba5b03bb24eb172f94ee0c0fa3a7cc5a..7bee1b2ef721abdee72360b29fc8834122049c5b 100644
--- a/Knot.files
+++ b/Knot.files
@@ -73,6 +73,7 @@ src/contrib/openbsd/strlcat.c
 src/contrib/openbsd/strlcat.h
 src/contrib/openbsd/strlcpy.c
 src/contrib/openbsd/strlcpy.h
+src/contrib/os.h
 src/contrib/qp-trie/trie.c
 src/contrib/qp-trie/trie.h
 src/contrib/semaphore.c
diff --git a/doc/man/kxdpgun.8in b/doc/man/kxdpgun.8in
index c6cec46cd3dc4a62716d0c61221fb35b07d7b7a2..202d9b907af7d72056a2cb8c0524537bd9377f52 100644
--- a/doc/man/kxdpgun.8in
+++ b/doc/man/kxdpgun.8in
@@ -113,7 +113,7 @@ Linux kernel 4.18+ is required.
 .sp
 The utility has to be executed under root or with these capabilities:
 CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, and CAP_SYS_RESOURCE if maximum
-locked memory limit is too low.
+locked memory limit is too low on Linux < 5.11.
 .sp
 Sending USR1 signal to a running process triggers current statistics dump
 to the standard output.
diff --git a/doc/man_kxdpgun.rst b/doc/man_kxdpgun.rst
index fd2eccbe6c357498a390cb0edc667aeefa488489..6ecb35c98de1481b6df25f33a84b5e13f4e56e07 100644
--- a/doc/man_kxdpgun.rst
+++ b/doc/man_kxdpgun.rst
@@ -93,7 +93,7 @@ Linux kernel 4.18+ is required.
 
 The utility has to be executed under root or with these capabilities:
 CAP_NET_RAW, CAP_NET_ADMIN, CAP_SYS_ADMIN, and CAP_SYS_RESOURCE if maximum
-locked memory limit is too low.
+locked memory limit is too low on Linux < 5.11.
 
 Sending USR1 signal to a running process triggers current statistics dump
 to the standard output.
diff --git a/doc/operation.rst b/doc/operation.rst
index ac04df4ff17915aa340d02f3e48b47a386317cad..2202b42ce70bb65182e807b476b5c9818aa99748 100644
--- a/doc/operation.rst
+++ b/doc/operation.rst
@@ -1109,6 +1109,8 @@ Pre-requisites
     CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN CAP_SYS_RESOURCE
     AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN CAP_SYS_RESOURCE
 
+  The `CAP_SYS_RESOURCE` is needed on Linux < 5.11.
+
 Optimizations
 -------------
 
diff --git a/src/contrib/Makefile.inc b/src/contrib/Makefile.inc
index b7aaecbd475cf8c24bd29ce6bca9a504b41d7aea..ee987071d893ccda78f9d7fe2869159269a1e2e4 100644
--- a/src/contrib/Makefile.inc
+++ b/src/contrib/Makefile.inc
@@ -40,6 +40,7 @@ libcontrib_la_SOURCES = \
 	contrib/mempattern.h			\
 	contrib/net.c				\
 	contrib/net.h				\
+	contrib/os.h				\
 	contrib/qp-trie/trie.c			\
 	contrib/qp-trie/trie.h			\
 	contrib/semaphore.c			\
diff --git a/src/contrib/os.h b/src/contrib/os.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d4a2e21d9cddd5d63ffd36617df0d6133ab7a79
--- /dev/null
+++ b/src/contrib/os.h
@@ -0,0 +1,37 @@
+/*  Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/utsname.h>
+
+inline static bool linux_at_least(unsigned version_first, unsigned version_second)
+{
+#if defined(__linux__)
+	struct utsname info;
+	unsigned first, second;
+	if (uname(&info) != 0 || sscanf(info.release, "%u.%u.", &first, &second) != 2) {
+		return false;
+	} else {
+		return first > version_first ||
+		       (first = version_first && second >= version_second);
+	}
+#else
+	return false;
+#endif
+}
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 02e166c54f088371bff2a42b0371bc4ae45ba8ae..bac00a9dbe8ce2b133a537f2c0de2ed8a2a0b293 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -40,6 +40,7 @@
 #include "knot/worker/pool.h"
 #include "contrib/net.h"
 #include "contrib/openbsd/strlcat.h"
+#include "contrib/os.h"
 #include "contrib/sockaddr.h"
 #include "contrib/trim.h"
 
@@ -511,7 +512,7 @@ static int configure_sockets(conf_t *conf, server_t *s)
 	}
 
 #ifdef ENABLE_XDP
-	if (lisxdp_val.code == KNOT_EOK) {
+	if (lisxdp_val.code == KNOT_EOK && !linux_at_least(5, 11)) {
 		struct rlimit min_limit = { RLIM_INFINITY, RLIM_INFINITY };
 		struct rlimit cur_limit = { 0 };
 		if (getrlimit(RLIMIT_MEMLOCK, &cur_limit) != 0 ||
diff --git a/src/utils/kxdpgun/main.c b/src/utils/kxdpgun/main.c
index 0a453c7727d584dfd2b7e34b8c909a8a562e1140..2ccf0efb0b563f420619df61b8537cae45755115 100644
--- a/src/utils/kxdpgun/main.c
+++ b/src/utils/kxdpgun/main.c
@@ -43,6 +43,7 @@
 #include "contrib/mempattern.h"
 #include "contrib/openbsd/strlcat.h"
 #include "contrib/openbsd/strlcpy.h"
+#include "contrib/os.h"
 #include "contrib/sockaddr.h"
 #include "contrib/ucw/mempool.h"
 #include "utils/common/params.h"
@@ -794,14 +795,19 @@ int main(int argc, char *argv[])
 		thread_ctxs[i].thread_id = i;
 	}
 
-	struct rlimit min_limit = { RLIM_INFINITY, RLIM_INFINITY }, cur_limit = { 0 };
-	if (getrlimit(RLIMIT_MEMLOCK, &cur_limit) != 0 ||
-	    cur_limit.rlim_cur != min_limit.rlim_cur || cur_limit.rlim_max != min_limit.rlim_max) {
-		int ret = setrlimit(RLIMIT_MEMLOCK, &min_limit);
-		if (ret != 0) {
-			printf("warning: unable to increase RLIMIT_MEMLOCK: %s\n", strerror(errno));
+	if (!linux_at_least(5, 11)) {
+		struct rlimit min_limit = { RLIM_INFINITY, RLIM_INFINITY }, cur_limit = { 0 };
+		if (getrlimit(RLIMIT_MEMLOCK, &cur_limit) != 0 ||
+		    cur_limit.rlim_cur != min_limit.rlim_cur ||
+		    cur_limit.rlim_max != min_limit.rlim_max) {
+			int ret = setrlimit(RLIMIT_MEMLOCK, &min_limit);
+			if (ret != 0) {
+				printf("warning: unable to increase RLIMIT_MEMLOCK: %s\n",
+				       strerror(errno));
+			}
 		}
 	}
+
 	pthread_mutex_init(&global_stats.mutex, NULL);
 
 	struct sigaction stop_action = { .sa_handler = sigterm_handler };