public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags
@ 2026-03-31  0:59 Eduard Zingerman
  2026-03-31 13:03 ` Puranjay Mohan
  0 siblings, 1 reply; 8+ messages in thread
From: Eduard Zingerman @ 2026-03-31  0:59 UTC (permalink / raw)
  To: bpf, ast
  Cc: andrii, daniel, martin.lau, kernel-team, yonghong.song,
	Eduard Zingerman

Impose global ordering for all decl tags used by test_loader.c based
tests: __success, __failure, __msg, etc. The tags are now sorted by
testing framework to be processed in the same order they appear in the
C source code of the test.

The ordering is necessary for gcc-bpf. Neither GCC nor the C standard
defines the order in which function attributes are consumed.
While Clang tends to preserve tags definition order in the output BTF,
GCC does not. This inconsistency causes BPF tests with multiple __msg
entries to fail when compiled with GCC.

This is based on a patch [1] from Cupertino Miranda (see patch #3) and
includes some additional cleanups for test_loader.c decl tags
declaration and processing (see patches #1, #2, #4).

[1] https://lore.kernel.org/bpf/20260305130035.192080-1-cupertino.miranda@oracle.com/

Changelog:
v1 -> v2:
- updated remaining str_has_pfx() usages (Puranjay)
- removed realloc_or_free() (Andrii)
- fixed qsort(NULL, ...) usage (Puranjay)
- skip_decl_tag_pfx() returns NULL if tag does not start from
  "comment:" (Puranjay)

v1: https://lore.kernel.org/bpf/20260326-selftests-global-tags-ordering-v1-0-5dd2ced5d9ad@gmail.com/
---
Eduard Zingerman (4):
      selftests/bpf: fix __jited_unpriv tag name
      selftests/bpf: make str_has_pfx return pointer past the prefix
      selftests/bpf: impose global ordering for test decl_tags
      selftests/bpf: inline TEST_TAG constants in test_loader.c

 tools/testing/selftests/bpf/progs/bpf_misc.h |  60 ++++----
 tools/testing/selftests/bpf/test_loader.c    | 202 +++++++++++++--------------
 2 files changed, 125 insertions(+), 137 deletions(-)
---
base-commit: b6b5e0ebd429d66ce37ae5af649a74ea1f041d92
change-id: 20260326-selftests-global-tags-ordering-8f324323d9c8

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags
  2026-03-31  0:59 Eduard Zingerman
@ 2026-03-31 13:03 ` Puranjay Mohan
  0 siblings, 0 replies; 8+ messages in thread
From: Puranjay Mohan @ 2026-03-31 13:03 UTC (permalink / raw)
  To: Eduard Zingerman, bpf, ast
  Cc: andrii, daniel, martin.lau, kernel-team, yonghong.song,
	Eduard Zingerman, Puranjay Mohan

Eduard Zingerman <eddyz87@gmail.com> writes:

> Impose global ordering for all decl tags used by test_loader.c based
> tests: __success, __failure, __msg, etc. The tags are now sorted by
> testing framework to be processed in the same order they appear in the
> C source code of the test.
>
> The ordering is necessary for gcc-bpf. Neither GCC nor the C standard
> defines the order in which function attributes are consumed.
> While Clang tends to preserve tags definition order in the output BTF,
> GCC does not. This inconsistency causes BPF tests with multiple __msg
> entries to fail when compiled with GCC.
>
> This is based on a patch [1] from Cupertino Miranda (see patch #3) and
> includes some additional cleanups for test_loader.c decl tags
> declaration and processing (see patches #1, #2, #4).
>
> [1] https://lore.kernel.org/bpf/20260305130035.192080-1-cupertino.miranda@oracle.com/
>
> Changelog:
> v1 -> v2:
> - updated remaining str_has_pfx() usages (Puranjay)
> - removed realloc_or_free() (Andrii)
> - fixed qsort(NULL, ...) usage (Puranjay)
> - skip_decl_tag_pfx() returns NULL if tag does not start from
>   "comment:" (Puranjay)
>
> v1: https://lore.kernel.org/bpf/20260326-selftests-global-tags-ordering-v1-0-5dd2ced5d9ad@gmail.com/
> ---
> Eduard Zingerman (4):
>       selftests/bpf: fix __jited_unpriv tag name
>       selftests/bpf: make str_has_pfx return pointer past the prefix
>       selftests/bpf: impose global ordering for test decl_tags
>       selftests/bpf: inline TEST_TAG constants in test_loader.c
>
>  tools/testing/selftests/bpf/progs/bpf_misc.h |  60 ++++----
>  tools/testing/selftests/bpf/test_loader.c    | 202 +++++++++++++--------------
>  2 files changed, 125 insertions(+), 137 deletions(-)
> ---
> base-commit: b6b5e0ebd429d66ce37ae5af649a74ea1f041d92
> change-id: 20260326-selftests-global-tags-ordering-8f324323d9c8


This set looks good to me, after changing the free path of realloc():

Reviewed-by: Puranjay Mohan <puranjay@kernel.org>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags
@ 2026-04-11  7:33 Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 1/4] selftests/bpf: fix __jited_unpriv tag name Eduard Zingerman
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Eduard Zingerman @ 2026-04-11  7:33 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87,
	cupertino.miranda

Impose global ordering for all decl tags used by test_loader.c based
tests: __success, __failure, __msg, etc. The tags are now sorted by
testing framework to be processed in the same order they appear in the
C source code of the test.

The ordering is necessary for gcc-bpf. Neither GCC nor the C standard
defines the order in which function attributes are consumed.
While Clang tends to preserve tags definition order in the output BTF,
GCC does not. This inconsistency causes BPF tests with multiple __msg
entries to fail when compiled with GCC.

This is based on a patch [1] from Cupertino Miranda (see patch #3) and
includes some additional cleanups for test_loader.c decl tags
declaration and processing (see patches #1, #2, #4).

[1] https://lore.kernel.org/bpf/20260305130035.192080-1-cupertino.miranda@oracle.com/

Changelog:
v2: https://lore.kernel.org/bpf/20260330-selftests-global-tags-ordering-v2-0-c0ac61e81098@gmail.com/
v2 -> v3:
- fixed free(tmp) call in collect_decl_tags() (Puranjay, bot)
- naming nit in compile_regex() (Mykyta)

v1 -> v2:
- refactoring str_has_pfx() usages missing from v1 (Puranjay)
- removed realloc_or_free() (Andrii)
- fixed qsort(NULL, ...) usage (Puranjay)
- skip_decl_tag_pfx() returns NULL if tag does not start from
  "comment:" (Puranjay)

v1: https://lore.kernel.org/bpf/20260326-selftests-global-tags-ordering-v1-0-5dd2ced5d9ad@gmail.com/
---
Eduard Zingerman (4):
      selftests/bpf: fix __jited_unpriv tag name
      selftests/bpf: make str_has_pfx return pointer past the prefix
      selftests/bpf: impose global ordering for test decl_tags
      selftests/bpf: inline TEST_TAG constants in test_loader.c

 tools/testing/selftests/bpf/progs/bpf_misc.h |  60 ++++----
 tools/testing/selftests/bpf/test_loader.c    | 202 +++++++++++++--------------
 2 files changed, 125 insertions(+), 137 deletions(-)
---
base-commit: 749b925802c2351ae7204e6960ca086e4c4e4fa7
change-id: 20260326-selftests-global-tags-ordering-8f324323d9c8

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH bpf-next v2 1/4] selftests/bpf: fix __jited_unpriv tag name
  2026-04-11  7:33 [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
@ 2026-04-11  7:33 ` Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 2/4] selftests/bpf: make str_has_pfx return pointer past the prefix Eduard Zingerman
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Eduard Zingerman @ 2026-04-11  7:33 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87,
	cupertino.miranda, Ihor Solodrai, Puranjay Mohan

__jited_unpriv was using "test_jited=" as its tag name, same as the
priv variant __jited. Fix by using "test_jited_unpriv=".

Fixes: 7d743e4c759c ("selftests/bpf: __jited test tag to check disassembly after jit")
Acked-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 tools/testing/selftests/bpf/progs/bpf_misc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index 4b313374c5f1..7e99fe8555e0 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -140,7 +140,7 @@
 #define __msg_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))
 #define __not_msg_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_not_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))
 #define __xlated_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __jited_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg)))
+#define __jited_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_jited_unpriv=" XSTR(__COUNTER__) "=" msg)))
 #define __failure_unpriv	__attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))
 #define __success_unpriv	__attribute__((btf_decl_tag("comment:test_expect_success_unpriv")))
 #define __log_level(lvl)	__attribute__((btf_decl_tag("comment:test_log_level="#lvl)))

-- 
2.53.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next v2 2/4] selftests/bpf: make str_has_pfx return pointer past the prefix
  2026-04-11  7:33 [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 1/4] selftests/bpf: fix __jited_unpriv tag name Eduard Zingerman
@ 2026-04-11  7:33 ` Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 3/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Eduard Zingerman @ 2026-04-11  7:33 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87,
	cupertino.miranda, Ihor Solodrai, Mykyta Yatsenko, Puranjay Mohan

Change str_has_pfx() to return a pointer to the first character after
the prefix, thus eliminating the repetitive (s + sizeof(PFX) - 1)
patterns.

Acked-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 tools/testing/selftests/bpf/test_loader.c | 51 ++++++++++++++-----------------
 1 file changed, 23 insertions(+), 28 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index 96ed70e01fe5..fa6147607c4d 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -11,8 +11,12 @@
 #include "cap_helpers.h"
 #include "jit_disasm_helpers.h"
 
-#define str_has_pfx(str, pfx) \
-	(strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
+static inline const char *str_has_pfx(const char *str, const char *pfx)
+{
+	size_t len = strlen(pfx);
+
+	return strncmp(str, pfx, len) == 0 ? str + len : NULL;
+}
 
 #define TEST_LOADER_LOG_BUF_SZ 2097152
 
@@ -166,21 +170,21 @@ static void free_test_spec(struct test_spec *spec)
 static int compile_regex(const char *pattern, regex_t *regex)
 {
 	char err_buf[256], buf[256] = {}, *ptr, *buf_end;
-	const char *original_pattern = pattern;
+	const char *original_pattern = pattern, *next;
 	bool in_regex = false;
 	int err;
 
 	buf_end = buf + sizeof(buf);
 	ptr = buf;
 	while (*pattern && ptr < buf_end - 2) {
-		if (!in_regex && str_has_pfx(pattern, "{{")) {
+		if (!in_regex && (next = str_has_pfx(pattern, "{{"))) {
 			in_regex = true;
-			pattern += 2;
+			pattern = next;
 			continue;
 		}
-		if (in_regex && str_has_pfx(pattern, "}}")) {
+		if (in_regex && (next = str_has_pfx(pattern, "}}"))) {
 			in_regex = false;
-			pattern += 2;
+			pattern = next;
 			continue;
 		}
 		if (in_regex) {
@@ -457,8 +461,8 @@ static int parse_test_spec(struct test_loader *tester,
 			continue;
 
 		s = btf__str_by_offset(btf, t->name_off);
-		if (str_has_pfx(s, TEST_TAG_DESCRIPTION_PFX)) {
-			description = s + sizeof(TEST_TAG_DESCRIPTION_PFX) - 1;
+		if ((val = str_has_pfx(s, TEST_TAG_DESCRIPTION_PFX))) {
+			description = val;
 		} else if (strcmp(s, TEST_TAG_EXPECT_FAILURE) == 0) {
 			spec->priv.expect_failure = true;
 			spec->mode_mask |= PRIV;
@@ -535,29 +539,24 @@ static int parse_test_spec(struct test_loader *tester,
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX)) {
-			val = s + sizeof(TEST_TAG_RETVAL_PFX) - 1;
+		} else if ((val = str_has_pfx(s, TEST_TAG_RETVAL_PFX))) {
 			err = parse_retval(val, &spec->priv.retval, "__retval");
 			if (err)
 				goto cleanup;
 			spec->priv.execute = true;
 			spec->mode_mask |= PRIV;
-		} else if (str_has_pfx(s, TEST_TAG_RETVAL_PFX_UNPRIV)) {
-			val = s + sizeof(TEST_TAG_RETVAL_PFX_UNPRIV) - 1;
+		} else if ((val = str_has_pfx(s, TEST_TAG_RETVAL_PFX_UNPRIV))) {
 			err = parse_retval(val, &spec->unpriv.retval, "__retval_unpriv");
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
 			spec->unpriv.execute = true;
 			has_unpriv_retval = true;
-		} else if (str_has_pfx(s, TEST_TAG_LOG_LEVEL_PFX)) {
-			val = s + sizeof(TEST_TAG_LOG_LEVEL_PFX) - 1;
+		} else if ((val = str_has_pfx(s, TEST_TAG_LOG_LEVEL_PFX))) {
 			err = parse_int(val, &spec->log_level, "test log level");
 			if (err)
 				goto cleanup;
-		} else if (str_has_pfx(s, TEST_TAG_PROG_FLAGS_PFX)) {
-			val = s + sizeof(TEST_TAG_PROG_FLAGS_PFX) - 1;
-
+		} else if ((val = str_has_pfx(s, TEST_TAG_PROG_FLAGS_PFX))) {
 			clear = val[0] == '!';
 			if (clear)
 				val++;
@@ -582,8 +581,7 @@ static int parse_test_spec(struct test_loader *tester,
 					goto cleanup;
 				update_flags(&spec->prog_flags, flags, clear);
 			}
-		} else if (str_has_pfx(s, TEST_TAG_ARCH)) {
-			val = s + sizeof(TEST_TAG_ARCH) - 1;
+		} else if ((val = str_has_pfx(s, TEST_TAG_ARCH))) {
 			if (strcmp(val, "X86_64") == 0) {
 				arch = ARCH_X86_64;
 			} else if (strcmp(val, "ARM64") == 0) {
@@ -601,16 +599,14 @@ static int parse_test_spec(struct test_loader *tester,
 			collect_jit = get_current_arch() == arch;
 			unpriv_jit_on_next_line = true;
 			jit_on_next_line = true;
-		} else if (str_has_pfx(s, TEST_BTF_PATH)) {
-			spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1;
-		} else if (str_has_pfx(s, TEST_TAG_CAPS_UNPRIV)) {
-			val = s + sizeof(TEST_TAG_CAPS_UNPRIV) - 1;
+		} else if ((val = str_has_pfx(s, TEST_BTF_PATH))) {
+			spec->btf_custom_path = val;
+		} else if ((val = str_has_pfx(s, TEST_TAG_CAPS_UNPRIV))) {
 			err = parse_caps(val, &spec->unpriv.caps, "test caps");
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if (str_has_pfx(s, TEST_TAG_LOAD_MODE_PFX)) {
-			val = s + sizeof(TEST_TAG_LOAD_MODE_PFX) - 1;
+		} else if ((val = str_has_pfx(s, TEST_TAG_LOAD_MODE_PFX))) {
 			if (strcmp(val, "jited") == 0) {
 				load_mask = JITED;
 			} else if (strcmp(val, "no_jited") == 0) {
@@ -640,12 +636,11 @@ static int parse_test_spec(struct test_loader *tester,
 					      &spec->unpriv.stdout);
 			if (err)
 				goto cleanup;
-		} else if (str_has_pfx(s, TEST_TAG_LINEAR_SIZE)) {
+		} else if ((val = str_has_pfx(s, TEST_TAG_LINEAR_SIZE))) {
 			switch (bpf_program__type(prog)) {
 			case BPF_PROG_TYPE_SCHED_ACT:
 			case BPF_PROG_TYPE_SCHED_CLS:
 			case BPF_PROG_TYPE_CGROUP_SKB:
-				val = s + sizeof(TEST_TAG_LINEAR_SIZE) - 1;
 				err = parse_int(val, &spec->linear_sz, "test linear size");
 				if (err)
 					goto cleanup;

-- 
2.53.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next v2 3/4] selftests/bpf: impose global ordering for test decl_tags
  2026-04-11  7:33 [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 1/4] selftests/bpf: fix __jited_unpriv tag name Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 2/4] selftests/bpf: make str_has_pfx return pointer past the prefix Eduard Zingerman
@ 2026-04-11  7:33 ` Eduard Zingerman
  2026-04-11  7:33 ` [PATCH bpf-next v2 4/4] selftests/bpf: inline TEST_TAG constants in test_loader.c Eduard Zingerman
  2026-04-11 14:20 ` [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags patchwork-bot+netdevbpf
  4 siblings, 0 replies; 8+ messages in thread
From: Eduard Zingerman @ 2026-04-11  7:33 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87,
	cupertino.miranda, Puranjay Mohan

Impose global ordering for all decl tags used by test_loader.c based
tests (__success, __failure, __msg, etc):
- change every tag to expand as
  __attribute__((btf_decl_tag("comment:" XSTR(__COUNTER__) ...)))
- change parse_test_spec() to collect all decl tags before
  processing and sort them using strverscmp().

The ordering is necessary for gcc-bpf.
Neither GCC nor the C standard defines the order in which function
attributes are consumed. While Clang tends to preserve definition order,
GCC may process them out of sequence. This inconsistency causes BPF
tests with multiple __msg entries to fail when compiled with GCC.

Signed-off-by: Cupertino Miranda <cupertino.miranda@oracle.com>
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 tools/testing/selftests/bpf/progs/bpf_misc.h |  60 +++++-----
 tools/testing/selftests/bpf/test_loader.c    | 167 +++++++++++++++------------
 2 files changed, 124 insertions(+), 103 deletions(-)

diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index 7e99fe8555e0..dcd78a3a9052 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -130,39 +130,41 @@
  * __linear_size     Specify the size of the linear area of non-linear skbs, or
  *                   0 for linear skbs.
  */
-#define __msg(msg)		__attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg)))
-#define __not_msg(msg)		__attribute__((btf_decl_tag("comment:test_expect_not_msg=" XSTR(__COUNTER__) "=" msg)))
-#define __xlated(msg)		__attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg)))
-#define __jited(msg)		__attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg)))
-#define __failure		__attribute__((btf_decl_tag("comment:test_expect_failure")))
-#define __success		__attribute__((btf_decl_tag("comment:test_expect_success")))
-#define __description(desc)	__attribute__((btf_decl_tag("comment:test_description=" desc)))
-#define __msg_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __not_msg_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_not_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __xlated_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __jited_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_jited_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __failure_unpriv	__attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))
-#define __success_unpriv	__attribute__((btf_decl_tag("comment:test_expect_success_unpriv")))
-#define __log_level(lvl)	__attribute__((btf_decl_tag("comment:test_log_level="#lvl)))
-#define __flag(flag)		__attribute__((btf_decl_tag("comment:test_prog_flags="#flag)))
-#define __retval(val)		__attribute__((btf_decl_tag("comment:test_retval="XSTR(val))))
-#define __retval_unpriv(val)	__attribute__((btf_decl_tag("comment:test_retval_unpriv="XSTR(val))))
-#define __auxiliary		__attribute__((btf_decl_tag("comment:test_auxiliary")))
-#define __auxiliary_unpriv	__attribute__((btf_decl_tag("comment:test_auxiliary_unpriv")))
-#define __btf_path(path)	__attribute__((btf_decl_tag("comment:test_btf_path=" path)))
-#define __arch(arch)		__attribute__((btf_decl_tag("comment:test_arch=" arch)))
+#define __test_tag(tag)		__attribute__((btf_decl_tag("comment:" XSTR(__COUNTER__) ":" tag)))
+
+#define __msg(msg)		__test_tag("test_expect_msg=" msg)
+#define __not_msg(msg)		__test_tag("test_expect_not_msg=" msg)
+#define __xlated(msg)		__test_tag("test_expect_xlated=" msg)
+#define __jited(msg)		__test_tag("test_jited=" msg)
+#define __failure		__test_tag("test_expect_failure")
+#define __success		__test_tag("test_expect_success")
+#define __description(desc)	__test_tag("test_description=" desc)
+#define __msg_unpriv(msg)	__test_tag("test_expect_msg_unpriv=" msg)
+#define __not_msg_unpriv(msg)	__test_tag("test_expect_not_msg_unpriv=" msg)
+#define __xlated_unpriv(msg)	__test_tag("test_expect_xlated_unpriv=" msg)
+#define __jited_unpriv(msg)	__test_tag("test_jited_unpriv=" msg)
+#define __failure_unpriv	__test_tag("test_expect_failure_unpriv")
+#define __success_unpriv	__test_tag("test_expect_success_unpriv")
+#define __log_level(lvl)	__test_tag("test_log_level=" #lvl)
+#define __flag(flag)		__test_tag("test_prog_flags=" #flag)
+#define __retval(val)		__test_tag("test_retval=" XSTR(val))
+#define __retval_unpriv(val)	__test_tag("test_retval_unpriv=" XSTR(val))
+#define __auxiliary		__test_tag("test_auxiliary")
+#define __auxiliary_unpriv	__test_tag("test_auxiliary_unpriv")
+#define __btf_path(path)	__test_tag("test_btf_path=" path)
+#define __arch(arch)		__test_tag("test_arch=" arch)
 #define __arch_x86_64		__arch("X86_64")
 #define __arch_arm64		__arch("ARM64")
 #define __arch_riscv64		__arch("RISCV64")
 #define __arch_s390x		__arch("s390x")
-#define __caps_unpriv(caps)	__attribute__((btf_decl_tag("comment:test_caps_unpriv=" EXPAND_QUOTE(caps))))
-#define __load_if_JITed()	__attribute__((btf_decl_tag("comment:load_mode=jited")))
-#define __load_if_no_JITed()	__attribute__((btf_decl_tag("comment:load_mode=no_jited")))
-#define __stderr(msg)		__attribute__((btf_decl_tag("comment:test_expect_stderr=" XSTR(__COUNTER__) "=" msg)))
-#define __stderr_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_stderr_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __stdout(msg)		__attribute__((btf_decl_tag("comment:test_expect_stdout=" XSTR(__COUNTER__) "=" msg)))
-#define __stdout_unpriv(msg)	__attribute__((btf_decl_tag("comment:test_expect_stdout_unpriv=" XSTR(__COUNTER__) "=" msg)))
-#define __linear_size(sz)	__attribute__((btf_decl_tag("comment:test_linear_size=" XSTR(sz))))
+#define __caps_unpriv(caps)	__test_tag("test_caps_unpriv=" EXPAND_QUOTE(caps))
+#define __load_if_JITed()	__test_tag("load_mode=jited")
+#define __load_if_no_JITed()	__test_tag("load_mode=no_jited")
+#define __stderr(msg)		__test_tag("test_expect_stderr=" msg)
+#define __stderr_unpriv(msg)	__test_tag("test_expect_stderr_unpriv=" msg)
+#define __stdout(msg)		__test_tag("test_expect_stdout=" msg)
+#define __stdout_unpriv(msg)	__test_tag("test_expect_stdout_unpriv=" msg)
+#define __linear_size(sz)	__test_tag("test_linear_size=" XSTR(sz))
 
 /* Define common capabilities tested using __caps_unpriv */
 #define CAP_NET_ADMIN		12
diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index fa6147607c4d..066898d0c123 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
 #include <linux/capability.h>
+#include <linux/err.h>
 #include <stdlib.h>
 #include <test_progs.h>
 #include <bpf/btf.h>
@@ -20,34 +21,34 @@ static inline const char *str_has_pfx(const char *str, const char *pfx)
 
 #define TEST_LOADER_LOG_BUF_SZ 2097152
 
-#define TEST_TAG_EXPECT_FAILURE "comment:test_expect_failure"
-#define TEST_TAG_EXPECT_SUCCESS "comment:test_expect_success"
-#define TEST_TAG_EXPECT_MSG_PFX "comment:test_expect_msg="
-#define TEST_TAG_EXPECT_NOT_MSG_PFX "comment:test_expect_not_msg="
-#define TEST_TAG_EXPECT_XLATED_PFX "comment:test_expect_xlated="
-#define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv"
-#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv"
-#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv="
-#define TEST_TAG_EXPECT_NOT_MSG_PFX_UNPRIV "comment:test_expect_not_msg_unpriv="
-#define TEST_TAG_EXPECT_XLATED_PFX_UNPRIV "comment:test_expect_xlated_unpriv="
-#define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level="
-#define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags="
-#define TEST_TAG_DESCRIPTION_PFX "comment:test_description="
-#define TEST_TAG_RETVAL_PFX "comment:test_retval="
-#define TEST_TAG_RETVAL_PFX_UNPRIV "comment:test_retval_unpriv="
-#define TEST_TAG_AUXILIARY "comment:test_auxiliary"
-#define TEST_TAG_AUXILIARY_UNPRIV "comment:test_auxiliary_unpriv"
-#define TEST_BTF_PATH "comment:test_btf_path="
-#define TEST_TAG_ARCH "comment:test_arch="
-#define TEST_TAG_JITED_PFX "comment:test_jited="
-#define TEST_TAG_JITED_PFX_UNPRIV "comment:test_jited_unpriv="
-#define TEST_TAG_CAPS_UNPRIV "comment:test_caps_unpriv="
-#define TEST_TAG_LOAD_MODE_PFX "comment:load_mode="
-#define TEST_TAG_EXPECT_STDERR_PFX "comment:test_expect_stderr="
-#define TEST_TAG_EXPECT_STDERR_PFX_UNPRIV "comment:test_expect_stderr_unpriv="
-#define TEST_TAG_EXPECT_STDOUT_PFX "comment:test_expect_stdout="
-#define TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV "comment:test_expect_stdout_unpriv="
-#define TEST_TAG_LINEAR_SIZE "comment:test_linear_size="
+#define TEST_TAG_EXPECT_FAILURE "test_expect_failure"
+#define TEST_TAG_EXPECT_SUCCESS "test_expect_success"
+#define TEST_TAG_EXPECT_MSG_PFX "test_expect_msg="
+#define TEST_TAG_EXPECT_NOT_MSG_PFX "test_expect_not_msg="
+#define TEST_TAG_EXPECT_XLATED_PFX "test_expect_xlated="
+#define TEST_TAG_EXPECT_FAILURE_UNPRIV "test_expect_failure_unpriv"
+#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "test_expect_success_unpriv"
+#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "test_expect_msg_unpriv="
+#define TEST_TAG_EXPECT_NOT_MSG_PFX_UNPRIV "test_expect_not_msg_unpriv="
+#define TEST_TAG_EXPECT_XLATED_PFX_UNPRIV "test_expect_xlated_unpriv="
+#define TEST_TAG_LOG_LEVEL_PFX "test_log_level="
+#define TEST_TAG_PROG_FLAGS_PFX "test_prog_flags="
+#define TEST_TAG_DESCRIPTION_PFX "test_description="
+#define TEST_TAG_RETVAL_PFX "test_retval="
+#define TEST_TAG_RETVAL_PFX_UNPRIV "test_retval_unpriv="
+#define TEST_TAG_AUXILIARY "test_auxiliary"
+#define TEST_TAG_AUXILIARY_UNPRIV "test_auxiliary_unpriv"
+#define TEST_BTF_PATH "test_btf_path="
+#define TEST_TAG_ARCH "test_arch="
+#define TEST_TAG_JITED_PFX "test_jited="
+#define TEST_TAG_JITED_PFX_UNPRIV "test_jited_unpriv="
+#define TEST_TAG_CAPS_UNPRIV "test_caps_unpriv="
+#define TEST_TAG_LOAD_MODE_PFX "load_mode="
+#define TEST_TAG_EXPECT_STDERR_PFX "test_expect_stderr="
+#define TEST_TAG_EXPECT_STDERR_PFX_UNPRIV "test_expect_stderr_unpriv="
+#define TEST_TAG_EXPECT_STDOUT_PFX "test_expect_stdout="
+#define TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV "test_expect_stdout_unpriv="
+#define TEST_TAG_LINEAR_SIZE "test_linear_size="
 
 /* Warning: duplicated in bpf_misc.h */
 #define POINTER_VALUE	0xbadcafe
@@ -352,33 +353,49 @@ static void update_flags(int *flags, int flag, bool clear)
 		*flags |= flag;
 }
 
-/* Matches a string of form '<pfx>[^=]=.*' and returns it's suffix.
- * Used to parse btf_decl_tag values.
- * Such values require unique prefix because compiler does not add
- * same __attribute__((btf_decl_tag(...))) twice.
- * Test suite uses two-component tags for such cases:
- *
- *   <pfx> __COUNTER__ '='
- *
- * For example, two consecutive __msg tags '__msg("foo") __msg("foo")'
- * would be encoded as:
- *
- *   [18] DECL_TAG 'comment:test_expect_msg=0=foo' type_id=15 component_idx=-1
- *   [19] DECL_TAG 'comment:test_expect_msg=1=foo' type_id=15 component_idx=-1
- *
- * And the purpose of this function is to extract 'foo' from the above.
- */
-static const char *skip_dynamic_pfx(const char *s, const char *pfx)
+static const char *skip_decl_tag_pfx(const char *s)
 {
-	const char *msg;
+	int n = 0;
 
-	if (strncmp(s, pfx, strlen(pfx)) != 0)
+	if (sscanf(s, "comment:%*d:%n", &n) < 0 || !n)
 		return NULL;
-	msg = s + strlen(pfx);
-	msg = strchr(msg, '=');
-	if (!msg)
-		return NULL;
-	return msg + 1;
+	return s + n;
+}
+
+static int compare_decl_tags(const void *a, const void *b)
+{
+	return strverscmp(*(const char **)a, *(const char **)b);
+}
+
+/*
+ * Compilers don't guarantee order in which BTF attributes would be generated,
+ * while order is important for test tags like __msg.
+ * Each test tag has the following prefix: "comment:" __COUNTER__,
+ * when sorted using strverscmp this gives same order as in the original C code.
+ */
+static const char **collect_decl_tags(struct btf *btf, int id, int *cnt)
+{
+	const char **tmp, **tags = NULL;
+	const struct btf_type *t;
+	int i;
+
+	*cnt = 0;
+	for (i = 1; i < btf__type_cnt(btf); i++) {
+		t = btf__type_by_id(btf, i);
+		if (!btf_is_decl_tag(t) || t->type != id || btf_decl_tag(t)->component_idx != -1)
+			continue;
+		tmp = realloc(tags, (*cnt + 1) * sizeof(*tags));
+		if (!tmp) {
+			free(tags);
+			return ERR_PTR(-ENOMEM);
+		}
+		tags = tmp;
+		tags[(*cnt)++] = btf__str_by_offset(btf, t->name_off);
+	}
+
+	if (*cnt)
+		qsort(tags, *cnt, sizeof(*tags), compare_decl_tags);
+	return tags;
 }
 
 enum arch {
@@ -424,7 +441,9 @@ static int parse_test_spec(struct test_loader *tester,
 	bool stdout_on_next_line = true;
 	bool unpriv_stdout_on_next_line = true;
 	bool collect_jit = false;
-	int func_id, i, err = 0;
+	const char **tags = NULL;
+	int func_id, i, nr_tags;
+	int err = 0;
 	u32 arch_mask = 0;
 	u32 load_mask = 0;
 	struct btf *btf;
@@ -447,20 +466,18 @@ static int parse_test_spec(struct test_loader *tester,
 		return -EINVAL;
 	}
 
-	for (i = 1; i < btf__type_cnt(btf); i++) {
+	tags = collect_decl_tags(btf, func_id, &nr_tags);
+	if (IS_ERR(tags))
+		return PTR_ERR(tags);
+
+	for (i = 0; i < nr_tags; i++) {
 		const char *s, *val, *msg;
-		const struct btf_type *t;
 		bool clear;
 		int flags;
 
-		t = btf__type_by_id(btf, i);
-		if (!btf_is_decl_tag(t))
+		s = skip_decl_tag_pfx(tags[i]);
+		if (!s)
 			continue;
-
-		if (t->type != func_id || btf_decl_tag(t)->component_idx != -1)
-			continue;
-
-		s = btf__str_by_offset(btf, t->name_off);
 		if ((val = str_has_pfx(s, TEST_TAG_DESCRIPTION_PFX))) {
 			description = val;
 		} else if (strcmp(s, TEST_TAG_EXPECT_FAILURE) == 0) {
@@ -483,27 +500,27 @@ static int parse_test_spec(struct test_loader *tester,
 		} else if (strcmp(s, TEST_TAG_AUXILIARY_UNPRIV) == 0) {
 			spec->auxiliary = true;
 			spec->mode_mask |= UNPRIV;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) {
 			err = push_msg(msg, false, &spec->priv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= PRIV;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_NOT_MSG_PFX))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_NOT_MSG_PFX))) {
 			err = push_msg(msg, true, &spec->priv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= PRIV;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) {
 			err = push_msg(msg, false, &spec->unpriv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_NOT_MSG_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_NOT_MSG_PFX_UNPRIV))) {
 			err = push_msg(msg, true, &spec->unpriv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_JITED_PFX))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_JITED_PFX))) {
 			if (arch_mask == 0) {
 				PRINT_FAIL("__jited used before __arch_*");
 				goto cleanup;
@@ -515,7 +532,7 @@ static int parse_test_spec(struct test_loader *tester,
 					goto cleanup;
 				spec->mode_mask |= PRIV;
 			}
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_JITED_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_JITED_PFX_UNPRIV))) {
 			if (arch_mask == 0) {
 				PRINT_FAIL("__unpriv_jited used before __arch_*");
 				goto cleanup;
@@ -527,13 +544,13 @@ static int parse_test_spec(struct test_loader *tester,
 					goto cleanup;
 				spec->mode_mask |= UNPRIV;
 			}
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) {
 			err = push_disasm_msg(msg, &xlated_on_next_line,
 					      &spec->priv.expect_xlated);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= PRIV;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) {
 			err = push_disasm_msg(msg, &unpriv_xlated_on_next_line,
 					      &spec->unpriv.expect_xlated);
 			if (err)
@@ -616,22 +633,22 @@ static int parse_test_spec(struct test_loader *tester,
 				err = -EINVAL;
 				goto cleanup;
 			}
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDERR_PFX))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDERR_PFX))) {
 			err = push_disasm_msg(msg, &stderr_on_next_line,
 					      &spec->priv.stderr);
 			if (err)
 				goto cleanup;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDERR_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDERR_PFX_UNPRIV))) {
 			err = push_disasm_msg(msg, &unpriv_stderr_on_next_line,
 					      &spec->unpriv.stderr);
 			if (err)
 				goto cleanup;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX))) {
 			err = push_disasm_msg(msg, &stdout_on_next_line,
 					      &spec->priv.stdout);
 			if (err)
 				goto cleanup;
-		} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV))) {
 			err = push_disasm_msg(msg, &unpriv_stdout_on_next_line,
 					      &spec->unpriv.stdout);
 			if (err)
@@ -734,9 +751,11 @@ static int parse_test_spec(struct test_loader *tester,
 
 	spec->valid = true;
 
+	free(tags);
 	return 0;
 
 cleanup:
+	free(tags);
 	free_test_spec(spec);
 	return err;
 }

-- 
2.53.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH bpf-next v2 4/4] selftests/bpf: inline TEST_TAG constants in test_loader.c
  2026-04-11  7:33 [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
                   ` (2 preceding siblings ...)
  2026-04-11  7:33 ` [PATCH bpf-next v2 3/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
@ 2026-04-11  7:33 ` Eduard Zingerman
  2026-04-11 14:20 ` [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags patchwork-bot+netdevbpf
  4 siblings, 0 replies; 8+ messages in thread
From: Eduard Zingerman @ 2026-04-11  7:33 UTC (permalink / raw)
  To: bpf, ast, andrii
  Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87,
	cupertino.miranda, Ihor Solodrai, Puranjay Mohan

After str_has_pfx() refactoring each TEST_TAG_* / TEST_BTF_PATH
constant is used exactly once. Since constant definitions are not
shared between BPF-side bpf_misc.h and userspace side test_loader.c,
there is no need in the additional redirection layer.

Acked-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Reviewed-by: Puranjay Mohan <puranjay@kernel.org>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
 tools/testing/selftests/bpf/test_loader.c | 84 +++++++++++--------------------
 1 file changed, 28 insertions(+), 56 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index 066898d0c123..c4c34cae6102 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -21,34 +21,6 @@ static inline const char *str_has_pfx(const char *str, const char *pfx)
 
 #define TEST_LOADER_LOG_BUF_SZ 2097152
 
-#define TEST_TAG_EXPECT_FAILURE "test_expect_failure"
-#define TEST_TAG_EXPECT_SUCCESS "test_expect_success"
-#define TEST_TAG_EXPECT_MSG_PFX "test_expect_msg="
-#define TEST_TAG_EXPECT_NOT_MSG_PFX "test_expect_not_msg="
-#define TEST_TAG_EXPECT_XLATED_PFX "test_expect_xlated="
-#define TEST_TAG_EXPECT_FAILURE_UNPRIV "test_expect_failure_unpriv"
-#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "test_expect_success_unpriv"
-#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "test_expect_msg_unpriv="
-#define TEST_TAG_EXPECT_NOT_MSG_PFX_UNPRIV "test_expect_not_msg_unpriv="
-#define TEST_TAG_EXPECT_XLATED_PFX_UNPRIV "test_expect_xlated_unpriv="
-#define TEST_TAG_LOG_LEVEL_PFX "test_log_level="
-#define TEST_TAG_PROG_FLAGS_PFX "test_prog_flags="
-#define TEST_TAG_DESCRIPTION_PFX "test_description="
-#define TEST_TAG_RETVAL_PFX "test_retval="
-#define TEST_TAG_RETVAL_PFX_UNPRIV "test_retval_unpriv="
-#define TEST_TAG_AUXILIARY "test_auxiliary"
-#define TEST_TAG_AUXILIARY_UNPRIV "test_auxiliary_unpriv"
-#define TEST_BTF_PATH "test_btf_path="
-#define TEST_TAG_ARCH "test_arch="
-#define TEST_TAG_JITED_PFX "test_jited="
-#define TEST_TAG_JITED_PFX_UNPRIV "test_jited_unpriv="
-#define TEST_TAG_CAPS_UNPRIV "test_caps_unpriv="
-#define TEST_TAG_LOAD_MODE_PFX "load_mode="
-#define TEST_TAG_EXPECT_STDERR_PFX "test_expect_stderr="
-#define TEST_TAG_EXPECT_STDERR_PFX_UNPRIV "test_expect_stderr_unpriv="
-#define TEST_TAG_EXPECT_STDOUT_PFX "test_expect_stdout="
-#define TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV "test_expect_stdout_unpriv="
-#define TEST_TAG_LINEAR_SIZE "test_linear_size="
 
 /* Warning: duplicated in bpf_misc.h */
 #define POINTER_VALUE	0xbadcafe
@@ -478,49 +450,49 @@ static int parse_test_spec(struct test_loader *tester,
 		s = skip_decl_tag_pfx(tags[i]);
 		if (!s)
 			continue;
-		if ((val = str_has_pfx(s, TEST_TAG_DESCRIPTION_PFX))) {
+		if ((val = str_has_pfx(s, "test_description="))) {
 			description = val;
-		} else if (strcmp(s, TEST_TAG_EXPECT_FAILURE) == 0) {
+		} else if (strcmp(s, "test_expect_failure") == 0) {
 			spec->priv.expect_failure = true;
 			spec->mode_mask |= PRIV;
-		} else if (strcmp(s, TEST_TAG_EXPECT_SUCCESS) == 0) {
+		} else if (strcmp(s, "test_expect_success") == 0) {
 			spec->priv.expect_failure = false;
 			spec->mode_mask |= PRIV;
-		} else if (strcmp(s, TEST_TAG_EXPECT_FAILURE_UNPRIV) == 0) {
+		} else if (strcmp(s, "test_expect_failure_unpriv") == 0) {
 			spec->unpriv.expect_failure = true;
 			spec->mode_mask |= UNPRIV;
 			has_unpriv_result = true;
-		} else if (strcmp(s, TEST_TAG_EXPECT_SUCCESS_UNPRIV) == 0) {
+		} else if (strcmp(s, "test_expect_success_unpriv") == 0) {
 			spec->unpriv.expect_failure = false;
 			spec->mode_mask |= UNPRIV;
 			has_unpriv_result = true;
-		} else if (strcmp(s, TEST_TAG_AUXILIARY) == 0) {
+		} else if (strcmp(s, "test_auxiliary") == 0) {
 			spec->auxiliary = true;
 			spec->mode_mask |= PRIV;
-		} else if (strcmp(s, TEST_TAG_AUXILIARY_UNPRIV) == 0) {
+		} else if (strcmp(s, "test_auxiliary_unpriv") == 0) {
 			spec->auxiliary = true;
 			spec->mode_mask |= UNPRIV;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_msg="))) {
 			err = push_msg(msg, false, &spec->priv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= PRIV;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_NOT_MSG_PFX))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_not_msg="))) {
 			err = push_msg(msg, true, &spec->priv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= PRIV;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_msg_unpriv="))) {
 			err = push_msg(msg, false, &spec->unpriv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_NOT_MSG_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_not_msg_unpriv="))) {
 			err = push_msg(msg, true, &spec->unpriv.expect_msgs);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_JITED_PFX))) {
+		} else if ((msg = str_has_pfx(s, "test_jited="))) {
 			if (arch_mask == 0) {
 				PRINT_FAIL("__jited used before __arch_*");
 				goto cleanup;
@@ -532,7 +504,7 @@ static int parse_test_spec(struct test_loader *tester,
 					goto cleanup;
 				spec->mode_mask |= PRIV;
 			}
-		} else if ((msg = str_has_pfx(s, TEST_TAG_JITED_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, "test_jited_unpriv="))) {
 			if (arch_mask == 0) {
 				PRINT_FAIL("__unpriv_jited used before __arch_*");
 				goto cleanup;
@@ -544,36 +516,36 @@ static int parse_test_spec(struct test_loader *tester,
 					goto cleanup;
 				spec->mode_mask |= UNPRIV;
 			}
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_XLATED_PFX))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_xlated="))) {
 			err = push_disasm_msg(msg, &xlated_on_next_line,
 					      &spec->priv.expect_xlated);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= PRIV;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_XLATED_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_xlated_unpriv="))) {
 			err = push_disasm_msg(msg, &unpriv_xlated_on_next_line,
 					      &spec->unpriv.expect_xlated);
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if ((val = str_has_pfx(s, TEST_TAG_RETVAL_PFX))) {
+		} else if ((val = str_has_pfx(s, "test_retval="))) {
 			err = parse_retval(val, &spec->priv.retval, "__retval");
 			if (err)
 				goto cleanup;
 			spec->priv.execute = true;
 			spec->mode_mask |= PRIV;
-		} else if ((val = str_has_pfx(s, TEST_TAG_RETVAL_PFX_UNPRIV))) {
+		} else if ((val = str_has_pfx(s, "test_retval_unpriv="))) {
 			err = parse_retval(val, &spec->unpriv.retval, "__retval_unpriv");
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
 			spec->unpriv.execute = true;
 			has_unpriv_retval = true;
-		} else if ((val = str_has_pfx(s, TEST_TAG_LOG_LEVEL_PFX))) {
+		} else if ((val = str_has_pfx(s, "test_log_level="))) {
 			err = parse_int(val, &spec->log_level, "test log level");
 			if (err)
 				goto cleanup;
-		} else if ((val = str_has_pfx(s, TEST_TAG_PROG_FLAGS_PFX))) {
+		} else if ((val = str_has_pfx(s, "test_prog_flags="))) {
 			clear = val[0] == '!';
 			if (clear)
 				val++;
@@ -598,7 +570,7 @@ static int parse_test_spec(struct test_loader *tester,
 					goto cleanup;
 				update_flags(&spec->prog_flags, flags, clear);
 			}
-		} else if ((val = str_has_pfx(s, TEST_TAG_ARCH))) {
+		} else if ((val = str_has_pfx(s, "test_arch="))) {
 			if (strcmp(val, "X86_64") == 0) {
 				arch = ARCH_X86_64;
 			} else if (strcmp(val, "ARM64") == 0) {
@@ -616,14 +588,14 @@ static int parse_test_spec(struct test_loader *tester,
 			collect_jit = get_current_arch() == arch;
 			unpriv_jit_on_next_line = true;
 			jit_on_next_line = true;
-		} else if ((val = str_has_pfx(s, TEST_BTF_PATH))) {
+		} else if ((val = str_has_pfx(s, "test_btf_path="))) {
 			spec->btf_custom_path = val;
-		} else if ((val = str_has_pfx(s, TEST_TAG_CAPS_UNPRIV))) {
+		} else if ((val = str_has_pfx(s, "test_caps_unpriv="))) {
 			err = parse_caps(val, &spec->unpriv.caps, "test caps");
 			if (err)
 				goto cleanup;
 			spec->mode_mask |= UNPRIV;
-		} else if ((val = str_has_pfx(s, TEST_TAG_LOAD_MODE_PFX))) {
+		} else if ((val = str_has_pfx(s, "load_mode="))) {
 			if (strcmp(val, "jited") == 0) {
 				load_mask = JITED;
 			} else if (strcmp(val, "no_jited") == 0) {
@@ -633,27 +605,27 @@ static int parse_test_spec(struct test_loader *tester,
 				err = -EINVAL;
 				goto cleanup;
 			}
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDERR_PFX))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_stderr="))) {
 			err = push_disasm_msg(msg, &stderr_on_next_line,
 					      &spec->priv.stderr);
 			if (err)
 				goto cleanup;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDERR_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_stderr_unpriv="))) {
 			err = push_disasm_msg(msg, &unpriv_stderr_on_next_line,
 					      &spec->unpriv.stderr);
 			if (err)
 				goto cleanup;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_stdout="))) {
 			err = push_disasm_msg(msg, &stdout_on_next_line,
 					      &spec->priv.stdout);
 			if (err)
 				goto cleanup;
-		} else if ((msg = str_has_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV))) {
+		} else if ((msg = str_has_pfx(s, "test_expect_stdout_unpriv="))) {
 			err = push_disasm_msg(msg, &unpriv_stdout_on_next_line,
 					      &spec->unpriv.stdout);
 			if (err)
 				goto cleanup;
-		} else if ((val = str_has_pfx(s, TEST_TAG_LINEAR_SIZE))) {
+		} else if ((val = str_has_pfx(s, "test_linear_size="))) {
 			switch (bpf_program__type(prog)) {
 			case BPF_PROG_TYPE_SCHED_ACT:
 			case BPF_PROG_TYPE_SCHED_CLS:

-- 
2.53.0

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags
  2026-04-11  7:33 [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
                   ` (3 preceding siblings ...)
  2026-04-11  7:33 ` [PATCH bpf-next v2 4/4] selftests/bpf: inline TEST_TAG constants in test_loader.c Eduard Zingerman
@ 2026-04-11 14:20 ` patchwork-bot+netdevbpf
  4 siblings, 0 replies; 8+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-04-11 14:20 UTC (permalink / raw)
  To: Eduard Zingerman
  Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
	cupertino.miranda

Hello:

This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:

On Sat, 11 Apr 2026 00:33:43 -0700 you wrote:
> Impose global ordering for all decl tags used by test_loader.c based
> tests: __success, __failure, __msg, etc. The tags are now sorted by
> testing framework to be processed in the same order they appear in the
> C source code of the test.
> 
> The ordering is necessary for gcc-bpf. Neither GCC nor the C standard
> defines the order in which function attributes are consumed.
> While Clang tends to preserve tags definition order in the output BTF,
> GCC does not. This inconsistency causes BPF tests with multiple __msg
> entries to fail when compiled with GCC.
> 
> [...]

Here is the summary with links:
  - [bpf-next,v2,1/4] selftests/bpf: fix __jited_unpriv tag name
    https://git.kernel.org/bpf/bpf-next/c/cdd54fe98c00
  - [bpf-next,v2,2/4] selftests/bpf: make str_has_pfx return pointer past the prefix
    https://git.kernel.org/bpf/bpf-next/c/5160e584c361
  - [bpf-next,v2,3/4] selftests/bpf: impose global ordering for test decl_tags
    https://git.kernel.org/bpf/bpf-next/c/713db9fd0336
  - [bpf-next,v2,4/4] selftests/bpf: inline TEST_TAG constants in test_loader.c
    https://git.kernel.org/bpf/bpf-next/c/335a6ca04158

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-04-11 14:20 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-11  7:33 [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
2026-04-11  7:33 ` [PATCH bpf-next v2 1/4] selftests/bpf: fix __jited_unpriv tag name Eduard Zingerman
2026-04-11  7:33 ` [PATCH bpf-next v2 2/4] selftests/bpf: make str_has_pfx return pointer past the prefix Eduard Zingerman
2026-04-11  7:33 ` [PATCH bpf-next v2 3/4] selftests/bpf: impose global ordering for test decl_tags Eduard Zingerman
2026-04-11  7:33 ` [PATCH bpf-next v2 4/4] selftests/bpf: inline TEST_TAG constants in test_loader.c Eduard Zingerman
2026-04-11 14:20 ` [PATCH bpf-next v2 0/4] selftests/bpf: impose global ordering for test decl_tags patchwork-bot+netdevbpf
  -- strict thread matches above, loose matches on Subject: below --
2026-03-31  0:59 Eduard Zingerman
2026-03-31 13:03 ` Puranjay Mohan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox