代码之家  ›  专栏  ›  技术社区  ›  Mark

ebpf-节名称

  •  4
  • Mark  · 技术社区  · 6 年前

    中的每个程序节都必须有唯一的名称吗 bpf 程序例如,此程序可以使用 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;
    

    然而 llvm-objdump 仅报告一个程序节:

    $ 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
    

    是否有至少给出警告的编译器选项?

    更新 -因此,我理解同一bpf文件中提供的节必须具有唯一的名称。当bpf程序驻留在不同的文件中并独立编译时,这样它们就可以被加载并互相调用,例如:。 tail calls ?

    1 回复  |  直到 5 年前
        1
  •  3
  •   Qeole    6 年前

    显然,编译器将所有内容连接在同一节中(我简化了 bpf_main 进行编译和测试)。

    $ 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 ...............
    

    从这里,我看不出您以后打算如何检索各个程序以正确加载它们。通常,用户空间工具从一个节中获取一个程序,并尝试通过将指令通过 bpf() 系统调用;在这里,您使用的任何程序都可能试图同时加载连接的四个程序。

    您希望所有程序在节中使用相同的名称,有什么特别的原因吗?

    我不知道LLVM对这种事情的警告。我想不是:人们可能有理由在一个部分中放不同的东西。这里的例子是针对BPF的,我认为人们通常不会试图将几个程序放在同一个部分中。但这只是猜测,我可能错了。

    关于您的更新:

    我不认为在不同的对象文件中使用类似的节名称是一个问题。只要您的用户空间工具能够从对象文件中检索程序并执行重新定位,它就应该可以正常工作。内核无论如何看不到任何节名。从 attr 参数是一组指令:

    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 */
    };
    

    (来自 include/uapi/linux/bpf.h ,请注意 insns 属性)。对于tail调用,您的用户空间代码还需要创建特定的映射,这些映射包含要跳转到的程序(更多 bpf() 电话)。但是,从ELF文件中提取信息完全是用户空间的责任。我认为Libbpf应该能够正确处理它,但我还没有尝试过。

    需要补充说明的是:我不知道您的用例到底是什么,但由于您正试图在不同的对象文件中编译代码并使用调用,您可能有兴趣了解eBPF现在支持函数调用,即您可以定义几个(非内联)函数,可能在几个ELF文件中,并在程序中调用它们。更多信息 in the cover letter . 再一次,到目前为止,我还没有时间进行实验。