Commit 84ef3f0b authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'introduce bpf_strncmp() helper'

Hou Tao says:

====================

Hi,

The motivation for introducing bpf_strncmp() helper comes from
two aspects:

(1) clang doesn't always replace strncmp() automatically
In tracing program, sometimes we need to using a home-made
strncmp() to check whether or not the file name is expected.

(2) the performance of home-made strncmp is not so good
As shown in the benchmark in patch #4, the performance of
bpf_strncmp() helper is 18% or 33% better than home-made strncmp()
under x86-64 or arm64 when the compared string length is 64. When
the string length grows to 4095, the performance win will be
179% or 600% under x86-64 or arm64.

Any comments are welcome.
Regards,
Tao

Change Log:
v2:
 * rebased on bpf-next
 * drop patch "selftests/bpf: factor out common helpers for benchmarks"
   (suggested by Andrii)
 * remove unnecessary inline functions and add comments for programs which
   will be rejected by verifier in patch 4 (suggested by Andrii)
 * rename variables used in will-fail programs to clarify the purposes.

v1: https://lore.kernel.org/bpf/20211130142215.1237217-1-houtao1@huawei.com
 * change API to bpf_strncmp(const char *s1, u32 s1_sz, const char *s2)
 * add benchmark refactor and benchmark between bpf_strncmp() and strncmp()

RFC: https://lore.kernel.org/bpf/20211106132822.1396621-1-houtao1@huawei.com/


====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 259172bb bdbee82b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2163,6 +2163,7 @@ extern const struct bpf_func_proto bpf_sk_getsockopt_proto;
extern const struct bpf_func_proto bpf_kallsyms_lookup_name_proto;
extern const struct bpf_func_proto bpf_find_vma_proto;
extern const struct bpf_func_proto bpf_loop_proto;
extern const struct bpf_func_proto bpf_strncmp_proto;

const struct bpf_func_proto *tracing_prog_func_proto(
  enum bpf_func_id func_id, const struct bpf_prog *prog);
+11 −0
Original line number Diff line number Diff line
@@ -4983,6 +4983,16 @@ union bpf_attr {
 *	Return
 *		The number of loops performed, **-EINVAL** for invalid **flags**,
 *		**-E2BIG** if **nr_loops** exceeds the maximum number of loops.
 *
 * long bpf_strncmp(const char *s1, u32 s1_sz, const char *s2)
 *	Description
 *		Do strncmp() between **s1** and **s2**. **s1** doesn't need
 *		to be null-terminated and **s1_sz** is the maximum storage
 *		size of **s1**. **s2** must be a read-only string.
 *	Return
 *		An integer less than, equal to, or greater than zero
 *		if the first **s1_sz** bytes of **s1** is found to be
 *		less than, to match, or be greater than **s2**.
 */
#define __BPF_FUNC_MAPPER(FN)		\
	FN(unspec),			\
@@ -5167,6 +5177,7 @@ union bpf_attr {
	FN(kallsyms_lookup_name),	\
	FN(find_vma),			\
	FN(loop),			\
	FN(strncmp),			\
	/* */

/* integer value in 'imm' field of BPF_CALL instruction selects which helper
+16 −0
Original line number Diff line number Diff line
@@ -565,6 +565,20 @@ const struct bpf_func_proto bpf_strtoul_proto = {
};
#endif

BPF_CALL_3(bpf_strncmp, const char *, s1, u32, s1_sz, const char *, s2)
{
	return strncmp(s1, s2, s1_sz);
}

const struct bpf_func_proto bpf_strncmp_proto = {
	.func		= bpf_strncmp,
	.gpl_only	= false,
	.ret_type	= RET_INTEGER,
	.arg1_type	= ARG_PTR_TO_MEM,
	.arg2_type	= ARG_CONST_SIZE,
	.arg3_type	= ARG_PTR_TO_CONST_STR,
};

BPF_CALL_4(bpf_get_ns_current_pid_tgid, u64, dev, u64, ino,
	   struct bpf_pidns_info *, nsdata, u32, size)
{
@@ -1378,6 +1392,8 @@ bpf_base_func_proto(enum bpf_func_id func_id)
		return &bpf_for_each_map_elem_proto;
	case BPF_FUNC_loop:
		return &bpf_loop_proto;
	case BPF_FUNC_strncmp:
		return &bpf_strncmp_proto;
	default:
		break;
	}
+11 −0
Original line number Diff line number Diff line
@@ -4983,6 +4983,16 @@ union bpf_attr {
 *	Return
 *		The number of loops performed, **-EINVAL** for invalid **flags**,
 *		**-E2BIG** if **nr_loops** exceeds the maximum number of loops.
 *
 * long bpf_strncmp(const char *s1, u32 s1_sz, const char *s2)
 *	Description
 *		Do strncmp() between **s1** and **s2**. **s1** doesn't need
 *		to be null-terminated and **s1_sz** is the maximum storage
 *		size of **s1**. **s2** must be a read-only string.
 *	Return
 *		An integer less than, equal to, or greater than zero
 *		if the first **s1_sz** bytes of **s1** is found to be
 *		less than, to match, or be greater than **s2**.
 */
#define __BPF_FUNC_MAPPER(FN)		\
	FN(unspec),			\
@@ -5167,6 +5177,7 @@ union bpf_attr {
	FN(kallsyms_lookup_name),	\
	FN(find_vma),			\
	FN(loop),			\
	FN(strncmp),			\
	/* */

/* integer value in 'imm' field of BPF_CALL instruction selects which helper
+3 −1
Original line number Diff line number Diff line
@@ -537,6 +537,7 @@ $(OUTPUT)/bench_ringbufs.o: $(OUTPUT)/ringbuf_bench.skel.h \
			    $(OUTPUT)/perfbuf_bench.skel.h
$(OUTPUT)/bench_bloom_filter_map.o: $(OUTPUT)/bloom_filter_bench.skel.h
$(OUTPUT)/bench_bpf_loop.o: $(OUTPUT)/bpf_loop_bench.skel.h
$(OUTPUT)/bench_strncmp.o: $(OUTPUT)/strncmp_bench.skel.h
$(OUTPUT)/bench.o: bench.h testing_helpers.h $(BPFOBJ)
$(OUTPUT)/bench: LDLIBS += -lm
$(OUTPUT)/bench: $(OUTPUT)/bench.o \
@@ -547,7 +548,8 @@ $(OUTPUT)/bench: $(OUTPUT)/bench.o \
		 $(OUTPUT)/bench_trigger.o \
		 $(OUTPUT)/bench_ringbufs.o \
		 $(OUTPUT)/bench_bloom_filter_map.o \
		 $(OUTPUT)/bench_bpf_loop.o
		 $(OUTPUT)/bench_bpf_loop.o \
		 $(OUTPUT)/bench_strncmp.o
	$(call msg,BINARY,,$@)
	$(Q)$(CC) $(LDFLAGS) $(filter %.a %.o,$^) $(LDLIBS) -o $@

Loading