Skip to contentSkip to conversation

Introduce libbpf_attach_type_by_name

PATCH Applied Andrey Ignatov 3 participants 10 messages Sep 27, 2018 – Sep 28, 2018

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

cover Introduce libbpf_attach_type_by_name

This patch set introduces libbpf_attach_type_by_name function in libbpf to identify attach type by section name.

This is useful to avoid writing same logic over and over again in user space applications that leverage libbpf.

Patch 1 has more details on the new function and problem being solved. Patches 2 and 3 add support for new section names.
Patch 4 uses new function in a selftest.
Patch 5 adds selftest for libbpf_{prog,attach}_type_by_name.

As a side note there are a lot of inconsistencies now between names used by libbpf and bpftool (e.g. cgroup/skb vs cgroup_skb, cgroup_device and device vs cgroup/dev, sockops vs sock_ops, etc). This patch set does not address it but it tries not to make it harder to address it in the future.

Andrey Ignatov (5):
libbpf: Introduce libbpf_attach_type_by_name
libbpf: Support cgroup_skb/{e,in}gress section names
libbpf: Support sk_skb/stream_{parser,verdict} section names selftests/bpf: Use libbpf_attach_type_by_name in test_socket_cookie selftests/bpf: Test libbpf_{prog,attach}_type_by_name

 tools/lib/bpf/libbpf.c                        | 129 +++++++----
 tools/lib/bpf/libbpf.h                        |   2 +
 tools/testing/selftests/bpf/Makefile          |   2 +-
 .../selftests/bpf/test_section_names.c        | 208 ++++++++++++++++++
 .../selftests/bpf/test_socket_cookie.c        |   6 +-
 5 files changed, 302 insertions(+), 45 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/test_section_names.c
Signature · 1 line
2.17.1
#1 lore raw

PATCH 1/5 libbpf: Introduce libbpf_attach_type_by_name

There is a common use-case when ELF object contains multiple BPF programs and every program has its own section name. If it's cgroup-bpf then programs have to be 1) loaded and 2) attached to a cgroup.

It's convenient to have information necessary to load BPF program together with program itself. This is where section name works fine in conjunction with libbpf_prog_type_by_name that identifies prog_type and expected_attach_type and these can be used with BPF_PROG_LOAD.

But there is currently no way to identify attach_type by section name and it leads to messy code in user space that reinvents guessing logic every time it has to identify attach type to use with BPF_PROG_ATTACH.

The patch introduces libbpf_attach_type_by_name that guesses attach type by section name if a program can be attached.

The difference between expected_attach_type provided by libbpf_prog_type_by_name and attach_type provided by libbpf_attach_type_by_name is the former is used at BPF_PROG_LOAD time and can be zero if a program of prog_type X has only one corresponding attach type Y whether the latter provides specific attach type to use with BPF_PROG_ATTACH.

No new section names were added to section_names array. Only existing ones were reorganized and attach_type was added where appropriate.

---
 tools/lib/bpf/libbpf.c | 121 ++++++++++++++++++++++++++++-------------
 tools/lib/bpf/libbpf.h |   2 +
 2 files changed, 84 insertions(+), 39 deletions(-)
tools/lib/bpf/libbpf.c +82 -39
index 4f8d43ae20d2..59e589a64d5c 100644
@@ -2085,58 +2085,82 @@ void bpf_program__set_expected_attach_type(struct bpf_program *prog,
 	prog->expected_attach_type = type;
 }
 
-#define BPF_PROG_SEC_FULL(string, ptype, atype) \
-	{ string, sizeof(string) - 1, ptype, atype }
+#define BPF_PROG_SEC_IMPL(string, ptype, eatype, atype) \
+	{ string, sizeof(string) - 1, ptype, eatype, atype }
 
-#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_FULL(string, ptype, 0)
+/* Programs that can NOT be attached. */
+#define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, -EINVAL)
 
-#define BPF_S_PROG_SEC(string, ptype) \
-	BPF_PROG_SEC_FULL(string, BPF_PROG_TYPE_CGROUP_SOCK, ptype)
+/* Programs that can be attached. */
+#define BPF_APROG_SEC(string, ptype, atype) \
+	BPF_PROG_SEC_IMPL(string, ptype, 0, atype)
 
-#define BPF_SA_PROG_SEC(string, ptype) \
-	BPF_PROG_SEC_FULL(string, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, ptype)
+/* Programs that must specify expected attach type at load time. */
+#define BPF_EAPROG_SEC(string, ptype, eatype) \
+	BPF_PROG_SEC_IMPL(string, ptype, eatype, eatype)
+
+/* Programs that can be attached but attach type can't be identified by section
+ * name. Kept for backward compatibility.
+ */
+#define BPF_APROG_COMPAT(string, ptype) BPF_PROG_SEC(string, ptype)
 
 static const struct {
 	const char *sec;
 	size_t len;
 	enum bpf_prog_type prog_type;
 	enum bpf_attach_type expected_attach_type;
+	enum bpf_attach_type attach_type;
 } section_names[] = {
-	BPF_PROG_SEC("socket",		BPF_PROG_TYPE_SOCKET_FILTER),
-	BPF_PROG_SEC("kprobe/",		BPF_PROG_TYPE_KPROBE),
-	BPF_PROG_SEC("kretprobe/",	BPF_PROG_TYPE_KPROBE),
-	BPF_PROG_SEC("classifier",	BPF_PROG_TYPE_SCHED_CLS),
-	BPF_PROG_SEC("action",		BPF_PROG_TYPE_SCHED_ACT),
-	BPF_PROG_SEC("tracepoint/",	BPF_PROG_TYPE_TRACEPOINT),
-	BPF_PROG_SEC("raw_tracepoint/",	BPF_PROG_TYPE_RAW_TRACEPOINT),
-	BPF_PROG_SEC("xdp",		BPF_PROG_TYPE_XDP),
-	BPF_PROG_SEC("perf_event",	BPF_PROG_TYPE_PERF_EVENT),
-	BPF_PROG_SEC("cgroup/skb",	BPF_PROG_TYPE_CGROUP_SKB),
-	BPF_PROG_SEC("cgroup/sock",	BPF_PROG_TYPE_CGROUP_SOCK),
-	BPF_PROG_SEC("cgroup/dev",	BPF_PROG_TYPE_CGROUP_DEVICE),
-	BPF_PROG_SEC("lwt_in",		BPF_PROG_TYPE_LWT_IN),
-	BPF_PROG_SEC("lwt_out",		BPF_PROG_TYPE_LWT_OUT),
-	BPF_PROG_SEC("lwt_xmit",	BPF_PROG_TYPE_LWT_XMIT),
-	BPF_PROG_SEC("lwt_seg6local",	BPF_PROG_TYPE_LWT_SEG6LOCAL),
-	BPF_PROG_SEC("sockops",		BPF_PROG_TYPE_SOCK_OPS),
-	BPF_PROG_SEC("sk_skb",		BPF_PROG_TYPE_SK_SKB),
-	BPF_PROG_SEC("sk_msg",		BPF_PROG_TYPE_SK_MSG),
-	BPF_PROG_SEC("lirc_mode2",	BPF_PROG_TYPE_LIRC_MODE2),
-	BPF_PROG_SEC("flow_dissector",	BPF_PROG_TYPE_FLOW_DISSECTOR),
-	BPF_SA_PROG_SEC("cgroup/bind4",	BPF_CGROUP_INET4_BIND),
-	BPF_SA_PROG_SEC("cgroup/bind6",	BPF_CGROUP_INET6_BIND),
-	BPF_SA_PROG_SEC("cgroup/connect4", BPF_CGROUP_INET4_CONNECT),
-	BPF_SA_PROG_SEC("cgroup/connect6", BPF_CGROUP_INET6_CONNECT),
-	BPF_SA_PROG_SEC("cgroup/sendmsg4", BPF_CGROUP_UDP4_SENDMSG),
-	BPF_SA_PROG_SEC("cgroup/sendmsg6", BPF_CGROUP_UDP6_SENDMSG),
-	BPF_S_PROG_SEC("cgroup/post_bind4", BPF_CGROUP_INET4_POST_BIND),
-	BPF_S_PROG_SEC("cgroup/post_bind6", BPF_CGROUP_INET6_POST_BIND),
+	BPF_PROG_SEC("socket",			BPF_PROG_TYPE_SOCKET_FILTER),
+	BPF_PROG_SEC("kprobe/",			BPF_PROG_TYPE_KPROBE),
+	BPF_PROG_SEC("kretprobe/",		BPF_PROG_TYPE_KPROBE),
+	BPF_PROG_SEC("classifier",		BPF_PROG_TYPE_SCHED_CLS),
+	BPF_PROG_SEC("action",			BPF_PROG_TYPE_SCHED_ACT),
+	BPF_PROG_SEC("tracepoint/",		BPF_PROG_TYPE_TRACEPOINT),
+	BPF_PROG_SEC("raw_tracepoint/",		BPF_PROG_TYPE_RAW_TRACEPOINT),
+	BPF_PROG_SEC("xdp",			BPF_PROG_TYPE_XDP),
+	BPF_PROG_SEC("perf_event",		BPF_PROG_TYPE_PERF_EVENT),
+	BPF_PROG_SEC("lwt_in",			BPF_PROG_TYPE_LWT_IN),
+	BPF_PROG_SEC("lwt_out",			BPF_PROG_TYPE_LWT_OUT),
+	BPF_PROG_SEC("lwt_xmit",		BPF_PROG_TYPE_LWT_XMIT),
+	BPF_PROG_SEC("lwt_seg6local",		BPF_PROG_TYPE_LWT_SEG6LOCAL),
+	BPF_APROG_COMPAT("cgroup/skb",		BPF_PROG_TYPE_CGROUP_SKB),
+	BPF_APROG_SEC("cgroup/sock",		BPF_PROG_TYPE_CGROUP_SOCK,
+						BPF_CGROUP_INET_SOCK_CREATE),
+	BPF_EAPROG_SEC("cgroup/post_bind4",	BPF_PROG_TYPE_CGROUP_SOCK,
+						BPF_CGROUP_INET4_POST_BIND),
+	BPF_EAPROG_SEC("cgroup/post_bind6",	BPF_PROG_TYPE_CGROUP_SOCK,
+						BPF_CGROUP_INET6_POST_BIND),
+	BPF_APROG_SEC("cgroup/dev",		BPF_PROG_TYPE_CGROUP_DEVICE,
+						BPF_CGROUP_DEVICE),
+	BPF_APROG_SEC("sockops",		BPF_PROG_TYPE_SOCK_OPS,
+						BPF_CGROUP_SOCK_OPS),
+	BPF_APROG_COMPAT("sk_skb",		BPF_PROG_TYPE_SK_SKB),
+	BPF_APROG_SEC("sk_msg",			BPF_PROG_TYPE_SK_MSG,
+						BPF_SK_MSG_VERDICT),
+	BPF_APROG_SEC("lirc_mode2",		BPF_PROG_TYPE_LIRC_MODE2,
+						BPF_LIRC_MODE2),
+	BPF_APROG_SEC("flow_dissector",		BPF_PROG_TYPE_FLOW_DISSECTOR,
+						BPF_FLOW_DISSECTOR),
+	BPF_EAPROG_SEC("cgroup/bind4",		BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+						BPF_CGROUP_INET4_BIND),
+	BPF_EAPROG_SEC("cgroup/bind6",		BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+						BPF_CGROUP_INET6_BIND),
+	BPF_EAPROG_SEC("cgroup/connect4",	BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+						BPF_CGROUP_INET4_CONNECT),
+	BPF_EAPROG_SEC("cgroup/connect6",	BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+						BPF_CGROUP_INET6_CONNECT),
+	BPF_EAPROG_SEC("cgroup/sendmsg4",	BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+						BPF_CGROUP_UDP4_SENDMSG),
+	BPF_EAPROG_SEC("cgroup/sendmsg6",	BPF_PROG_TYPE_CGROUP_SOCK_ADDR,
+						BPF_CGROUP_UDP6_SENDMSG),
 };
 
+#undef BPF_PROG_SEC_IMPL
 #undef BPF_PROG_SEC
-#undef BPF_PROG_SEC_FULL
-#undef BPF_S_PROG_SEC
-#undef BPF_SA_PROG_SEC
+#undef BPF_APROG_SEC
+#undef BPF_EAPROG_SEC
+#undef BPF_APROG_COMPAT
 
 int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
 			     enum bpf_attach_type *expected_attach_type)
@@ -2156,6 +2180,25 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
 	return -EINVAL;
 }
 
+int libbpf_attach_type_by_name(const char *name,
+			       enum bpf_attach_type *attach_type)
+{
+	int i;
+
+	if (!name)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(section_names); i++) {
+		if (strncmp(name, section_names[i].sec, section_names[i].len))
+			continue;
+		if (section_names[i].attach_type == -EINVAL)
+			return -EINVAL;
+		*attach_type = section_names[i].attach_type;
+		return 0;
+	}
+	return -EINVAL;
+}
+
 static int
 bpf_program__identify_section(struct bpf_program *prog,
 			      enum bpf_prog_type *prog_type,
tools/lib/bpf/libbpf.h +2 -0
index e3b00e23e181..511c1294dcbf 100644
@@ -104,6 +104,8 @@ void *bpf_object__priv(struct bpf_object *prog);
 
 int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
 			     enum bpf_attach_type *expected_attach_type);
+int libbpf_attach_type_by_name(const char *name,
+			       enum bpf_attach_type *attach_type);
 
 /* Accessors of bpf_program */
 struct bpf_program;
Signature · 1 line
2.17.1
#2 lore raw

PATCH 2/5 libbpf: Support cgroup_skb/{e,in}gress section names

In reply to Andrey Ignatov

Add section names for BPF_CGROUP_INET_INGRESS and BPF_CGROUP_INET_EGRESS attach types to be able to identify them in libbpf_attach_type_by_name.

"cgroup_skb" is used instead of "cgroup/skb" mostly to easy possible unifying of how libbpf and bpftool works with section names:
* bpftool uses "cgroup_skb" to in "prog list" sub-command;
* bpftool uses "ingress" and "egress" in "cgroup list" sub-command;
* having two parts instead of three in a string like "cgroup_skb/ingress" can be leveraged to split it to prog_type part and attach_type part, or vise versa: use two parts to make a section name.

---
 tools/lib/bpf/libbpf.c | 4 ++++
 1 file changed, 4 insertions(+)
tools/lib/bpf/libbpf.c +4 -0
index 59e589a64d5c..51edf6cd390e 100644
@@ -2124,6 +2124,10 @@ static const struct {
 	BPF_PROG_SEC("lwt_out",			BPF_PROG_TYPE_LWT_OUT),
 	BPF_PROG_SEC("lwt_xmit",		BPF_PROG_TYPE_LWT_XMIT),
 	BPF_PROG_SEC("lwt_seg6local",		BPF_PROG_TYPE_LWT_SEG6LOCAL),
+	BPF_APROG_SEC("cgroup_skb/ingress",	BPF_PROG_TYPE_CGROUP_SKB,
+						BPF_CGROUP_INET_INGRESS),
+	BPF_APROG_SEC("cgroup_skb/egress",	BPF_PROG_TYPE_CGROUP_SKB,
+						BPF_CGROUP_INET_EGRESS),
 	BPF_APROG_COMPAT("cgroup/skb",		BPF_PROG_TYPE_CGROUP_SKB),
 	BPF_APROG_SEC("cgroup/sock",		BPF_PROG_TYPE_CGROUP_SOCK,
 						BPF_CGROUP_INET_SOCK_CREATE),
Signature · 1 line
2.17.1
#3 lore raw

PATCH 3/5 libbpf: Support sk_skb/stream_{parser,verdict} section names

In reply to Andrey Ignatov

Add section names for BPF_SK_SKB_STREAM_PARSER and BPF_SK_SKB_STREAM_VERDICT attach types to be able to identify them in libbpf_attach_type_by_name.

"stream_parser" and "stream_verdict" are used instead of simple "parser" and "verdict" just to avoid possible confusion in a place where attach type is used alone (e.g. in bpftool's show sub-commands) since there is another attach point that can be named as "verdict": BPF_SK_MSG_VERDICT.

---
 tools/lib/bpf/libbpf.c | 4 ++++
 1 file changed, 4 insertions(+)
tools/lib/bpf/libbpf.c +4 -0
index 51edf6cd390e..425d5ca45c97 100644
@@ -2139,6 +2139,10 @@ static const struct {
 						BPF_CGROUP_DEVICE),
 	BPF_APROG_SEC("sockops",		BPF_PROG_TYPE_SOCK_OPS,
 						BPF_CGROUP_SOCK_OPS),
+	BPF_APROG_SEC("sk_skb/stream_parser",	BPF_PROG_TYPE_SK_SKB,
+						BPF_SK_SKB_STREAM_PARSER),
+	BPF_APROG_SEC("sk_skb/stream_verdict",	BPF_PROG_TYPE_SK_SKB,
+						BPF_SK_SKB_STREAM_VERDICT),
 	BPF_APROG_COMPAT("sk_skb",		BPF_PROG_TYPE_SK_SKB),
 	BPF_APROG_SEC("sk_msg",			BPF_PROG_TYPE_SK_MSG,
 						BPF_SK_MSG_VERDICT),
Signature · 1 line
2.17.1
#4 lore raw

PATCH 4/5 selftests/bpf: Use libbpf_attach_type_by_name in test_socket_cookie

In reply to Andrey Ignatov

Use newly introduced libbpf_attach_type_by_name in test_socket_cookie selftest.

---
 tools/testing/selftests/bpf/test_socket_cookie.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
tools/testing/selftests/bpf/test_socket_cookie.c +1 -5
index 68e108e4687a..b6c2c605d8c0 100644
@@ -158,11 +158,7 @@ static int run_test(int cgfd)
 	bpf_object__for_each_program(prog, pobj) {
 		prog_name = bpf_program__title(prog, /*needs_copy*/ false);
 
-		if (strcmp(prog_name, "cgroup/connect6") == 0) {
-			attach_type = BPF_CGROUP_INET6_CONNECT;
-		} else if (strcmp(prog_name, "sockops") == 0) {
-			attach_type = BPF_CGROUP_SOCK_OPS;
-		} else {
+		if (libbpf_attach_type_by_name(prog_name, &attach_type)) {
 			log_err("Unexpected prog: %s", prog_name);
 			goto err;
 		}
Signature · 1 line
2.17.1
#5 lore raw

PATCH 5/5 selftests/bpf: Test libbpf_{prog,attach}_type_by_name

In reply to Andrey Ignatov

Add selftest for libbpf functions libbpf_prog_type_by_name and libbpf_attach_type_by_name.

Example of output:
% ./tools/testing/selftests/bpf/test_section_names
Summary: 35 PASSED, 0 FAILED

---
 tools/testing/selftests/bpf/Makefile          |   2 +-
 .../selftests/bpf/test_section_names.c        | 208 ++++++++++++++++++
 2 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/bpf/test_section_names.c
tools/testing/selftests/bpf/Makefile +1 -1
index fd3851d5c079..059d64a0f897 100644
@@ -23,7 +23,7 @@ $(TEST_CUSTOM_PROGS): $(OUTPUT)/%: %.c
 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
 	test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \
 	test_sock test_btf test_sockmap test_lirc_mode2_user get_cgroup_id_user \
-	test_socket_cookie test_cgroup_storage test_select_reuseport
+	test_socket_cookie test_cgroup_storage test_select_reuseport test_section_names
 
 TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \
 	test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o     \
tools/testing/selftests/bpf/test_section_names.c new file +208 -0

208 lines not on this page · raw message

Signature · 1 line
2.17.1
#6 lore raw
In reply to Andrey Ignatov
Quoted 11 lines · Andrey Ignatov

This patch set introduces libbpf_attach_type_by_name function in libbpf to identify attach type by section name.

This is useful to avoid writing same logic over and over again in user space applications that leverage libbpf.

Patch 1 has more details on the new function and problem being solved. Patches 2 and 3 add support for new section names.
Patch 4 uses new function in a selftest.
Patch 5 adds selftest for libbpf_{prog,attach}_type_by_name.

Quoted 4 lines

As a side note there are a lot of inconsistencies now between names used by libbpf and bpftool (e.g. cgroup/skb vs cgroup_skb, cgroup_device and device vs cgroup/dev, sockops vs sock_ops, etc). This patch set does not address it but it tries not to make it harder to address it in the future.

I was wondering a few times whether I should point it out to people during review, but thought it would be nit picking. Maybe we should be more strict.

Your series LGTM!

#7 lore raw

Jakub Kicinski <[email protected]> [Wed, 2018-09-26 16:20 -0700]:

Quoted 17 lines · Andrey Ignatov
Quoted 11 lines

This patch set introduces libbpf_attach_type_by_name function in libbpf to identify attach type by section name.

This is useful to avoid writing same logic over and over again in user space applications that leverage libbpf.

Patch 1 has more details on the new function and problem being solved. Patches 2 and 3 add support for new section names.
Patch 4 uses new function in a selftest.
Patch 5 adds selftest for libbpf_{prog,attach}_type_by_name.

Quoted 4 lines

As a side note there are a lot of inconsistencies now between names used by libbpf and bpftool (e.g. cgroup/skb vs cgroup_skb, cgroup_device and device vs cgroup/dev, sockops vs sock_ops, etc). This patch set does not address it but it tries not to make it harder to address it in the future.

Quoted 5 lines

I was wondering a few times whether I should point it out to people during review, but thought it would be nit picking. Maybe we should be more strict.

Your series LGTM!

Thanks for review!

IMO having it consistent would be great, e.g. one writes a program with section name X and bpftool shows/accepts it in exactly same way in all its sub-commands (w/o maybe custom suffix added by program writer).

But I doubt that keeping a few places in sync manually will work long term since it's easy to miss such a thing.

What do you think of having one source of truth in libbpf so that a string for prog_type or attach_type is defined once and all other places (e.g. bpftool prog show, bpftool cgroup show) use only corresponding enum-s to get those strings, but don't introduce any new strings?

Keeping already existing names in a backward compatible way is a pain though.

Another thing, I was wondering, is if there is a way to bypass strings completely (at least in libbpf, since bpftool still has to print human-readable names) and keep actual bpf_prog_type and bpf_attach_type as metadata for a program in ELF file. Maybe some compiler magic ..

Signature · 1 line
Andrey Ignatov
#8 lore raw
Quoted 33 lines · Andrey Ignatov

Jakub Kicinski <[email protected]> [Wed, 2018-09-26 16:20 -0700]:

Quoted 17 lines · Andrey Ignatov
Quoted 11 lines

This patch set introduces libbpf_attach_type_by_name function in libbpf to identify attach type by section name.

This is useful to avoid writing same logic over and over again in user space applications that leverage libbpf.

Patch 1 has more details on the new function and problem being solved. Patches 2 and 3 add support for new section names.
Patch 4 uses new function in a selftest.
Patch 5 adds selftest for libbpf_{prog,attach}_type_by_name.

Quoted 4 lines

As a side note there are a lot of inconsistencies now between names used by libbpf and bpftool (e.g. cgroup/skb vs cgroup_skb, cgroup_device and device vs cgroup/dev, sockops vs sock_ops, etc). This patch set does not address it but it tries not to make it harder to address it in the future.

Quoted 5 lines

I was wondering a few times whether I should point it out to people during review, but thought it would be nit picking. Maybe we should be more strict.

Your series LGTM!

Thanks for review!

IMO having it consistent would be great, e.g. one writes a program with section name X and bpftool shows/accepts it in exactly same way in all its sub-commands (w/o maybe custom suffix added by program writer).

But I doubt that keeping a few places in sync manually will work long term since it's easy to miss such a thing.

Quoted 7 lines

What do you think of having one source of truth in libbpf so that a string for prog_type or attach_type is defined once and all other places (e.g. bpftool prog show, bpftool cgroup show) use only corresponding enum-s to get those strings, but don't introduce any new strings?

Keeping already existing names in a backward compatible way is a pain though.

One source of truth would be nice IMO. The backward compat ties our hands a tiny bit, but we could do a fallback strategy, where bpftool checks if it has a name defined for a type, and if it doesn't (for new types) it will ask libbpf.

There is another place actually where names are hard coded - for program load command we use the types as they appear in libbpf already. And that requires putting them in help, man page and bash completions, too.

Quoted 4 lines

Another thing, I was wondering, is if there is a way to bypass strings completely (at least in libbpf, since bpftool still has to print human-readable names) and keep actual bpf_prog_type and bpf_attach_type as metadata for a program in ELF file. Maybe some compiler magic ..

Possibly. I'm far from an ELF expert, but I think attaching arbitrary metadata to sections may be harder, name is already there and is free form.

maintainer Applied
#9 lore raw
In reply to Andrey Ignatov
Quoted 17 lines · Andrey Ignatov

This patch set introduces libbpf_attach_type_by_name function in libbpf to identify attach type by section name.

This is useful to avoid writing same logic over and over again in user space applications that leverage libbpf.

Patch 1 has more details on the new function and problem being solved. Patches 2 and 3 add support for new section names.
Patch 4 uses new function in a selftest.
Patch 5 adds selftest for libbpf_{prog,attach}_type_by_name.

As a side note there are a lot of inconsistencies now between names used by libbpf and bpftool (e.g. cgroup/skb vs cgroup_skb, cgroup_device and device vs cgroup/dev, sockops vs sock_ops, etc). This patch set does not address it but it tries not to make it harder to address it in the future.

Quoted 6 lines

Andrey Ignatov (5):
libbpf: Introduce libbpf_attach_type_by_name
libbpf: Support cgroup_skb/{e,in}gress section names
libbpf: Support sk_skb/stream_{parser,verdict} section names selftests/bpf: Use libbpf_attach_type_by_name in test_socket_cookie selftests/bpf: Test libbpf_{prog,attach}_type_by_name

Applied to bpf-next, thanks Andrey!