This series implements a new BPF feature probe which checks for the
commit c04c0d2b968a ("bpf: increase complexity limit and maximum program
size"), which increases the maximum program size to 1M. It's based on
the similar check in Cilium, althogh Cilium is already aiming to use
bpftool checks and eventually drop all its custom checks.
Examples of outputs:
# bpftool feature probe
[...]
Scanning miscellaneous eBPF features...
Large complexity limit and maximum program size (1M) is available
# bpftool feature probe macros
[...]
/*** eBPF misc features ***/
#define HAVE_HAVE_LARGE_INSN_LIMIT
# bpftool feature probe -j | jq '.["misc"]'
{
"have_large_insn_limit": true
}
Michal Rostecki (2):
libbpf: Add probe for large INSN limit
bpftool: Add misc secion and probe for large INSN limit
tools/bpf/bpftool/feature.c | 18 ++++++++++++++++++
tools/lib/bpf/libbpf.h | 1 +
tools/lib/bpf/libbpf.map | 1 +
tools/lib/bpf/libbpf_probes.c | 23 +++++++++++++++++++++++
4 files changed, 43 insertions(+)
--
2.16.4
Introduce a new probe section (misc) for probes not related to concrete
map types, program types, functions or kernel configuration. Introduce a
probe for large INSN limit as the first one in that section.
Signed-off-by: Michal Rostecki <[email protected]>
---
tools/bpf/bpftool/feature.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
index 03bdc5b3ac49..4a7359b9a427 100644
--- a/tools/bpf/bpftool/feature.c
+++ b/tools/bpf/bpftool/feature.c
@@ -572,6 +572,18 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
printf("\n");
}
+static void
+probe_large_insn_limit(const char *define_prefix, __u32 ifindex)
+{
+ bool res;
+
+ res = bpf_probe_large_insn_limit(ifindex);
+ print_bool_feature("have_large_insn_limit",
+ "Large complexity limit and maximum program size (1M)",
+ "HAVE_LARGE_INSN_LIMIT",
+ res, define_prefix);
+}
+
static int do_probe(int argc, char **argv)
{
enum probe_component target = COMPONENT_UNSPEC;
@@ -724,6 +736,12 @@ static int do_probe(int argc, char **argv)
probe_helpers_for_progtype(i, supported_types[i],
define_prefix, ifindex);
+ print_end_then_start_section("misc",
+ "Scanning miscellaneous eBPF features...",
+ "/*** eBPF misc features ***/",
+ define_prefix);
+ probe_large_insn_limit(define_prefix, ifindex);
+
exit_close_json:
if (json_output) {
/* End current "section" of probes */
--
2.16.4
Introduce a new probe which checks whether kernel has large maximum
program size (1M) which was increased in commit c04c0d2b968a ("bpf:
increase complexity limit and maximum program size").
Based on the similar check in Cilium[0], authored by Daniel Borkmann.
[0] https://github.com/cilium/cilium/commit/657d0f585afd26232cfa5d4e70b6f64d2ea91596
Co-authored-by: Daniel Borkmann <[email protected]>
Signed-off-by: Michal Rostecki <[email protected]>
---
tools/lib/bpf/libbpf.h | 1 +
tools/lib/bpf/libbpf.map | 1 +
tools/lib/bpf/libbpf_probes.c | 23 +++++++++++++++++++++++
3 files changed, 25 insertions(+)
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index fe592ef48f1b..26bf539f1b3c 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -521,6 +521,7 @@ LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
enum bpf_prog_type prog_type, __u32 ifindex);
+LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex);
/*
* Get bpf_prog_info in continuous memory
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index e9713a574243..b300d74c921a 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -219,6 +219,7 @@ LIBBPF_0.0.7 {
bpf_object__detach_skeleton;
bpf_object__load_skeleton;
bpf_object__open_skeleton;
+ bpf_probe_large_insn_limit;
bpf_prog_attach_xattr;
bpf_program__attach;
bpf_program__name;
diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
index a9eb8b322671..925f95106a52 100644
--- a/tools/lib/bpf/libbpf_probes.c
+++ b/tools/lib/bpf/libbpf_probes.c
@@ -17,6 +17,8 @@
#include "libbpf.h"
#include "libbpf_internal.h"
+#define INSN_REPEAT 4128
+
static bool grep(const char *buffer, const char *pattern)
{
return !!strstr(buffer, pattern);
@@ -321,3 +323,24 @@ bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,
return res;
}
+
+/*
+ * Probe for availability of kernel commit (5.3):
+ *
+ * c04c0d2b968a ("bpf: increase complexity limit and maximum program size")
+ */
+bool bpf_probe_large_insn_limit(__u32 ifindex)
+{
+ struct bpf_insn insns[INSN_REPEAT + 1];
+ int i;
+
+ for (i = 0; i < INSN_REPEAT; i++)
+ insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1);
+ insns[INSN_REPEAT] = BPF_EXIT_INSN();
+
+ errno = 0;
+ probe_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,
+ ifindex);
+
+ return errno != E2BIG && errno != EINVAL;
+}
--
2.16.4
On 12/27/19 12:06 PM, Michal Rostecki wrote:
> Introduce a new probe which checks whether kernel has large maximum
> program size (1M) which was increased in commit c04c0d2b968a ("bpf:
> increase complexity limit and maximum program size").
>
> Based on the similar check in Cilium[0], authored by Daniel Borkmann.
>
> [0] https://github.com/cilium/cilium/commit/657d0f585afd26232cfa5d4e70b6f64d2ea91596
>
> Co-authored-by: Daniel Borkmann <[email protected]>
> Signed-off-by: Michal Rostecki <[email protected]>
> ---
> tools/lib/bpf/libbpf.h | 1 +
> tools/lib/bpf/libbpf.map | 1 +
> tools/lib/bpf/libbpf_probes.c | 23 +++++++++++++++++++++++
> 3 files changed, 25 insertions(+)
>
> diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
> index fe592ef48f1b..26bf539f1b3c 100644
> --- a/tools/lib/bpf/libbpf.h
> +++ b/tools/lib/bpf/libbpf.h
> @@ -521,6 +521,7 @@ LIBBPF_API bool bpf_probe_prog_type(enum bpf_prog_type prog_type,
> LIBBPF_API bool bpf_probe_map_type(enum bpf_map_type map_type, __u32 ifindex);
> LIBBPF_API bool bpf_probe_helper(enum bpf_func_id id,
> enum bpf_prog_type prog_type, __u32 ifindex);
> +LIBBPF_API bool bpf_probe_large_insn_limit(__u32 ifindex);
>
> /*
> * Get bpf_prog_info in continuous memory
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index e9713a574243..b300d74c921a 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -219,6 +219,7 @@ LIBBPF_0.0.7 {
> bpf_object__detach_skeleton;
> bpf_object__load_skeleton;
> bpf_object__open_skeleton;
> + bpf_probe_large_insn_limit;
> bpf_prog_attach_xattr;
> bpf_program__attach;
> bpf_program__name;
> diff --git a/tools/lib/bpf/libbpf_probes.c b/tools/lib/bpf/libbpf_probes.c
> index a9eb8b322671..925f95106a52 100644
> --- a/tools/lib/bpf/libbpf_probes.c
> +++ b/tools/lib/bpf/libbpf_probes.c
> @@ -17,6 +17,8 @@
> #include "libbpf.h"
> #include "libbpf_internal.h"
>
> +#define INSN_REPEAT 4128
> +
> static bool grep(const char *buffer, const char *pattern)
> {
> return !!strstr(buffer, pattern);
> @@ -321,3 +323,24 @@ bool bpf_probe_helper(enum bpf_func_id id, enum bpf_prog_type prog_type,
>
> return res;
> }
> +
> +/*
> + * Probe for availability of kernel commit (5.3):
> + *
> + * c04c0d2b968a ("bpf: increase complexity limit and maximum program size")
> + */
> +bool bpf_probe_large_insn_limit(__u32 ifindex)
> +{
> + struct bpf_insn insns[INSN_REPEAT + 1];
> + int i;
Looks good, but lets test for 'BPF_MAXINSNS + 1' number of total insns, less
arbitrary than 4128.
> + for (i = 0; i < INSN_REPEAT; i++)
> + insns[i] = BPF_MOV64_IMM(BPF_REG_0, 1);
> + insns[INSN_REPEAT] = BPF_EXIT_INSN();
> +
> + errno = 0;
> + probe_load(BPF_PROG_TYPE_SCHED_CLS, insns, ARRAY_SIZE(insns), NULL, 0,
> + ifindex);
> +
> + return errno != E2BIG && errno != EINVAL;
> +}
>
On 12/27/19 12:06 PM, Michal Rostecki wrote:
> Introduce a new probe section (misc) for probes not related to concrete
> map types, program types, functions or kernel configuration. Introduce a
> probe for large INSN limit as the first one in that section.
>
> Signed-off-by: Michal Rostecki <[email protected]>
> ---
> tools/bpf/bpftool/feature.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/tools/bpf/bpftool/feature.c b/tools/bpf/bpftool/feature.c
> index 03bdc5b3ac49..4a7359b9a427 100644
> --- a/tools/bpf/bpftool/feature.c
> +++ b/tools/bpf/bpftool/feature.c
> @@ -572,6 +572,18 @@ probe_helpers_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
> printf("\n");
> }
>
> +static void
> +probe_large_insn_limit(const char *define_prefix, __u32 ifindex)
> +{
> + bool res;
> +
> + res = bpf_probe_large_insn_limit(ifindex);
> + print_bool_feature("have_large_insn_limit",
> + "Large complexity limit and maximum program size (1M)",
> + "HAVE_LARGE_INSN_LIMIT",
HAVE_LARGE_INSN_LIMIT is good, but official description should not explicitly
state the 1M limit since this could be subject to change. Perhaps just stating
"Large complexity and program size limit" is better suited here.
> + res, define_prefix);
> +}
> +
> static int do_probe(int argc, char **argv)
> {
> enum probe_component target = COMPONENT_UNSPEC;
> @@ -724,6 +736,12 @@ static int do_probe(int argc, char **argv)
> probe_helpers_for_progtype(i, supported_types[i],
> define_prefix, ifindex);
>
> + print_end_then_start_section("misc",
> + "Scanning miscellaneous eBPF features...",
> + "/*** eBPF misc features ***/",
> + define_prefix);
> + probe_large_insn_limit(define_prefix, ifindex);
> +
> exit_close_json:
> if (json_output) {
> /* End current "section" of probes */
>