diff options
Diffstat (limited to 'tools/lib/bpf/bpf_helpers.h')
| -rw-r--r-- | tools/lib/bpf/bpf_helpers.h | 110 | 
1 files changed, 109 insertions, 1 deletions
diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h index 5ec1871acb2f..929a3baca8ef 100644 --- a/tools/lib/bpf/bpf_helpers.h +++ b/tools/lib/bpf/bpf_helpers.h @@ -174,8 +174,13 @@ enum libbpf_tristate {  #define __kconfig __attribute__((section(".kconfig")))  #define __ksym __attribute__((section(".ksyms"))) +#define __kptr_untrusted __attribute__((btf_type_tag("kptr_untrusted")))  #define __kptr __attribute__((btf_type_tag("kptr"))) -#define __kptr_ref __attribute__((btf_type_tag("kptr_ref"))) + +#define bpf_ksym_exists(sym) ({									\ +	_Static_assert(!__builtin_constant_p(!!sym), #sym " should be marked as __weak");	\ +	!!sym;											\ +})  #ifndef ___bpf_concat  #define ___bpf_concat(a, b) a ## b @@ -286,4 +291,107 @@ enum libbpf_tristate {  /* Helper macro to print out debug messages */  #define bpf_printk(fmt, args...) ___bpf_pick_printk(args)(fmt, ##args) +struct bpf_iter_num; + +extern int bpf_iter_num_new(struct bpf_iter_num *it, int start, int end) __weak __ksym; +extern int *bpf_iter_num_next(struct bpf_iter_num *it) __weak __ksym; +extern void bpf_iter_num_destroy(struct bpf_iter_num *it) __weak __ksym; + +#ifndef bpf_for_each +/* bpf_for_each(iter_type, cur_elem, args...) provides generic construct for + * using BPF open-coded iterators without having to write mundane explicit + * low-level loop logic. Instead, it provides for()-like generic construct + * that can be used pretty naturally. E.g., for some hypothetical cgroup + * iterator, you'd write: + * + * struct cgroup *cg, *parent_cg = <...>; + * + * bpf_for_each(cgroup, cg, parent_cg, CG_ITER_CHILDREN) { + *     bpf_printk("Child cgroup id = %d", cg->cgroup_id); + *     if (cg->cgroup_id == 123) + *         break; + * } + * + * I.e., it looks almost like high-level for each loop in other languages, + * supports continue/break, and is verifiable by BPF verifier. + * + * For iterating integers, the difference betwen bpf_for_each(num, i, N, M) + * and bpf_for(i, N, M) is in that bpf_for() provides additional proof to + * verifier that i is in [N, M) range, and in bpf_for_each() case i is `int + * *`, not just `int`. So for integers bpf_for() is more convenient. + * + * Note: this macro relies on C99 feature of allowing to declare variables + * inside for() loop, bound to for() loop lifetime. It also utilizes GCC + * extension: __attribute__((cleanup(<func>))), supported by both GCC and + * Clang. + */ +#define bpf_for_each(type, cur, args...) for (							\ +	/* initialize and define destructor */							\ +	struct bpf_iter_##type ___it __attribute__((aligned(8), /* enforce, just in case */,	\ +						    cleanup(bpf_iter_##type##_destroy))),	\ +	/* ___p pointer is just to call bpf_iter_##type##_new() *once* to init ___it */		\ +			       *___p __attribute__((unused)) = (				\ +					bpf_iter_##type##_new(&___it, ##args),			\ +	/* this is a workaround for Clang bug: it currently doesn't emit BTF */			\ +	/* for bpf_iter_##type##_destroy() when used from cleanup() attribute */		\ +					(void)bpf_iter_##type##_destroy, (void *)0);		\ +	/* iteration and termination check */							\ +	(((cur) = bpf_iter_##type##_next(&___it)));						\ +) +#endif /* bpf_for_each */ + +#ifndef bpf_for +/* bpf_for(i, start, end) implements a for()-like looping construct that sets + * provided integer variable *i* to values starting from *start* through, + * but not including, *end*. It also proves to BPF verifier that *i* belongs + * to range [start, end), so this can be used for accessing arrays without + * extra checks. + * + * Note: *start* and *end* are assumed to be expressions with no side effects + * and whose values do not change throughout bpf_for() loop execution. They do + * not have to be statically known or constant, though. + * + * Note: similarly to bpf_for_each(), it relies on C99 feature of declaring for() + * loop bound variables and cleanup attribute, supported by GCC and Clang. + */ +#define bpf_for(i, start, end) for (								\ +	/* initialize and define destructor */							\ +	struct bpf_iter_num ___it __attribute__((aligned(8), /* enforce, just in case */	\ +						 cleanup(bpf_iter_num_destroy))),		\ +	/* ___p pointer is necessary to call bpf_iter_num_new() *once* to init ___it */		\ +			    *___p __attribute__((unused)) = (					\ +				bpf_iter_num_new(&___it, (start), (end)),			\ +	/* this is a workaround for Clang bug: it currently doesn't emit BTF */			\ +	/* for bpf_iter_num_destroy() when used from cleanup() attribute */			\ +				(void)bpf_iter_num_destroy, (void *)0);				\ +	({											\ +		/* iteration step */								\ +		int *___t = bpf_iter_num_next(&___it);						\ +		/* termination and bounds check */						\ +		(___t && ((i) = *___t, (i) >= (start) && (i) < (end)));				\ +	});											\ +) +#endif /* bpf_for */ + +#ifndef bpf_repeat +/* bpf_repeat(N) performs N iterations without exposing iteration number + * + * Note: similarly to bpf_for_each(), it relies on C99 feature of declaring for() + * loop bound variables and cleanup attribute, supported by GCC and Clang. + */ +#define bpf_repeat(N) for (									\ +	/* initialize and define destructor */							\ +	struct bpf_iter_num ___it __attribute__((aligned(8), /* enforce, just in case */	\ +						 cleanup(bpf_iter_num_destroy))),		\ +	/* ___p pointer is necessary to call bpf_iter_num_new() *once* to init ___it */		\ +			    *___p __attribute__((unused)) = (					\ +				bpf_iter_num_new(&___it, 0, (N)),				\ +	/* this is a workaround for Clang bug: it currently doesn't emit BTF */			\ +	/* for bpf_iter_num_destroy() when used from cleanup() attribute */			\ +				(void)bpf_iter_num_destroy, (void *)0);				\ +	bpf_iter_num_next(&___it);								\ +	/* nothing here  */									\ +) +#endif /* bpf_repeat */ +  #endif  |