Is it mandatory to have unique names for every program section in bpf
program? For instance, this program compiles fine with llvm-5.0
:
...
SEC("sockops")
int bpf1(struct bpf_sock_ops *sk_ops)
{
return 1;
}
SEC("sockops")
int bpf2(struct bpf_sock_ops *sk_ops)
{
return 1;
}
SEC("sockops")
int bpf3(struct bpf_sock_ops *sk_ops)
{
return 1;
}
SEC("sockops")
int bpf_main(struct bpf_sock_ops *sk_ops)
{
__u32 port = bpf_ntohl(sk_ops->remote_port);
switch (port) {
case 5000:
bpf_tail_call(sk_ops, &jmp_table, 1);
break;
case 6000:
bpf_tail_call(sk_ops, &jmp_table, 2);
break;
case 7000:
bpf_tail_call(sk_ops, &jmp_table, 3);
break;
}
sk_ops->reply = 0;
return 1;
}
char _license[] SEC("license") = "GPL";
u32 _version SEC("version") = LINUX_VERSION_CODE;
However, llvm-objdump
reports only one program section:
$ llvm-objdump-5.0 -section-headers bpf_main.o
bpf_main.o: file format ELF64-BPF
Sections:
Idx Name Size Address Type
0 00000000 0000000000000000
1 .strtab 000000a5 0000000000000000
2 .text 00000000 0000000000000000 TEXT DATA
3 sockops 000001f8 0000000000000000 TEXT DATA
4 .relsockops 00000030 0000000000000000
5 maps 0000001c 0000000000000000 DATA
6 .rodata.str1.16 00000021 0000000000000000 DATA
7 .rodata.str1.1 0000000e 0000000000000000 DATA
8 license 00000004 0000000000000000 DATA
9 version 00000004 0000000000000000 DATA
10 .eh_frame 00000090 0000000000000000 DATA
11 .rel.eh_frame 00000040 0000000000000000
12 .symtab 00000138 0000000000000000
Is there a compiler option to give at least a warning?
UPDATE - so I understand that sections provided in the same bpf file must have unique names. Is it true in cases when bpf programs reside in different files and compiled independently, so that they could be loaded and call one another, e.g. tail calls
?
Apparently the compiler concatenates everything in the same section (I simplified bpf_main
to have it compile and to test).
$ readelf -x sockops bpf_prog.o
Hex dump of section 'sockops':
0x00000000 b7000000 01000000 95000000 00000000 ................
0x00000010 b7000000 01000000 95000000 00000000 ................
0x00000020 b7000000 01000000 95000000 00000000 ................
0x00000030 b7000000 00000000 95000000 00000000 ...............
From here, I cannot see how you intend to later retrieve the individual programs to load them properly. Usually, user space tools get one program from a section, and attempt to load them by passing the instructions to the kernel through the bpf()
syscall; here, whatever program you use will probably try to load the concatenated four programs at once.
Is there a particular reason why you would like to have all programs in sections with the same name?
I have no idea for the warning in LLVM on such a thing. I guess not: people may have reason to put different stuff in a section. The case here is specific to BPF, and I do not think people usually try to put several programs in a same section. But this is just a guess, I may be wrong.
Regarding your update:
I do not believe using similar sections names in different object files is an issue. As long as your user space tool is able to retrieve the programs from object files and to perform relocation, it should work fine. The kernel does not see any section name anyway. What it takes from the attr
argument is an array of instructions:
struct { /* anonymous struct used by BPF_PROG_LOAD command */
__u32 prog_type; /* one of enum bpf_prog_type */
__u32 insn_cnt;
__aligned_u64 insns;
__aligned_u64 license;
__u32 log_level; /* verbosity level of verifier */
__u32 log_size; /* size of user buffer */
__aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */
__u32 prog_flags;
char prog_name[BPF_OBJ_NAME_LEN];
__u32 prog_ifindex; /* ifindex of netdev to prep for */
};
(from include/uapi/linux/bpf.h
, note the insns
attribute). For tail calls your user space code also needs to create the specific maps holding referenced to the programs you want to jump to (more bpf()
calls). But there again, it's all the responsibility of user space to extract the information from the ELF files. Libbpf should be able to handle it correctly I think, but I have not tried it.
A side note to finish: I don't know what your use case is exactly, but since you are trying to compile your code in different object files and to use calls, you might be interested to learn that eBPF now supports “function calls”, i.e. you can define several (non-inline) functions, possibly in several ELF files, and call them in your program. More information in the cover letter. Again, I didn't have the time to experiment with it so far.