Add BPF helper that allows to calculate jhash of arbitrary (initialized) memory slice. Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx> --- include/uapi/linux/bpf.h | 8 ++++++++ kernel/bpf/helpers.c | 23 +++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 8 ++++++++ 3 files changed, 39 insertions(+) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 2e3048488feb..7b17e46b0be2 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -4913,6 +4913,13 @@ union bpf_attr { * Return * The number of bytes written to the buffer, or a negative error * in case of failure. + * + * u64 bpf_jhash_mem(const void *data, u32 sz, u32 seed) + * Description + * Calculate jhash of a given memory slice. + * + * Return + * Calculated hash value. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5093,6 +5100,7 @@ union bpf_attr { FN(task_pt_regs), \ FN(get_branch_snapshot), \ FN(trace_vprintk), \ + FN(jhash_mem), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index 2c604ff8c7fb..00fb1b69595c 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -15,9 +15,30 @@ #include <linux/pid_namespace.h> #include <linux/proc_ns.h> #include <linux/security.h> +#include <linux/jhash.h> #include "../../lib/kstrtox.h" +BPF_CALL_3(bpf_jhash_mem, const void *, data, u32, sz, u32, seed) +{ + if (unlikely((uintptr_t)data % 4 || sz % 4)) + return jhash(data, sz, seed); + + /* optimized 4-byte version */ + return jhash2(data, sz / 4, seed); +} + + +static const struct bpf_func_proto bpf_jhash_mem_proto = { + .func = bpf_jhash_mem, + .gpl_only = false, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_MEM, + .arg2_type = ARG_CONST_SIZE_OR_ZERO, + .arg3_type = ARG_ANYTHING, +}; + + /* If kernel subsystem is allowing eBPF programs to call this function, * inside its own verifier_ops->get_func_proto() callback it should return * bpf_map_lookup_elem_proto, so that verifier can properly check the arguments @@ -1341,6 +1362,8 @@ const struct bpf_func_proto * bpf_base_func_proto(enum bpf_func_id func_id) { switch (func_id) { + case BPF_FUNC_jhash_mem: + return &bpf_jhash_mem_proto; case BPF_FUNC_map_lookup_elem: return &bpf_map_lookup_elem_proto; case BPF_FUNC_map_update_elem: diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 2e3048488feb..7b17e46b0be2 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -4913,6 +4913,13 @@ union bpf_attr { * Return * The number of bytes written to the buffer, or a negative error * in case of failure. + * + * u64 bpf_jhash_mem(const void *data, u32 sz, u32 seed) + * Description + * Calculate jhash of a given memory slice. + * + * Return + * Calculated hash value. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5093,6 +5100,7 @@ union bpf_attr { FN(task_pt_regs), \ FN(get_branch_snapshot), \ FN(trace_vprintk), \ + FN(jhash_mem), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper -- 2.30.2