首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有什么方法可以在ebpf程序和具有值结构的userspace程序之间共享一些ebpf映射吗?

有什么方法可以在ebpf程序和具有值结构的userspace程序之间共享一些ebpf映射吗?
EN

Stack Overflow用户
提问于 2022-01-15 12:59:24
回答 1查看 357关注 0票数 0

所以我创建了一个BPF_MAP_TYPE_ARRAY类型的地图。

代码语言:javascript
复制
struct share_me
{

    struct iphdr dest_ip;
};

struct bpf_map_def SEC("maps") ip_map = {
    .type = BPF_MAP_TYPE_ARRAY,
    .key_size = sizeof(int),
    .value_size = sizeof(struct share_me),
    .max_entries = 64,  /* Assume netdev has no more than 64 queues */
};

因此,ip_map是我的地图,它的定义部分和SEC精灵部分用于在上述定义中创建地图。

在我的ebpf程序功能中,我正在做

代码语言:javascript
复制
SEC("xdp_sock")
int xdp_sock_prog(struct xdp_md *ctx)
{
    int index = ctx->rx_queue_index;
    __u32 *pkt_count;

    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;  
    struct share_me me; 

    if ((void *)eth + sizeof(*eth) <= data_end)
    {

        struct iphdr *ip = data + sizeof(*eth);
        //me.dest_ip=ip;    
        memcpy(&me.dest_ip,ip,sizeof(struct iphdr));    
        bpf_map_lookup_elem(&ip_map, &index);
        bpf_map_update_elem(&ip_map,&index,&me,0);  

因此,我使用struct对象更新ip_map键的当前值。

这就是我在使用空间程序中所做的。

代码语言:javascript
复制
        bpf_obj = load_bpf_and_xdp_attach(&cfg);
        if (!bpf_obj) {
            /* Error handling done in load_bpf_and_xdp_attach() */
            exit(EXIT_FAILURE);
        }

        /* We also need to load the xsks_map */
        
        map1 = bpf_object__find_map_by_name(bpf_obj, "ip_map");
        xsks_map_fd = bpf_map__fd(map);
        map_fd = bpf_map__fd(map1);
        if(map_fd<0)
        {
            printf("map_fd <0\n");
            exit(0);
        }
        
        if (xsks_map_fd < 0) {
            fprintf(stderr, "ERROR: no xsks map found: %s\n",
                strerror(xsks_map_fd));
            exit(EXIT_FAILURE);
        }

这是load_bpf_and_xdp_attach函数,只是bpf/libbpf的包装器,所以调用load_bpf_object_file等等,

代码语言:javascript
复制
struct bpf_object *load_bpf_and_xdp_attach(struct config *cfg)
{
    struct bpf_program *bpf_prog;
    struct bpf_object *bpf_obj;
    int offload_ifindex = 0;
    int prog_fd = -1;
    int err;

    /* If flags indicate hardware offload, supply ifindex */
    if (cfg->xdp_flags & XDP_FLAGS_HW_MODE)
        offload_ifindex = cfg->ifindex;

    /* Load the BPF-ELF object file and get back libbpf bpf_object */
    if (cfg->reuse_maps)
        bpf_obj = load_bpf_object_file_reuse_maps(cfg->filename,
                              offload_ifindex,
                              cfg->pin_dir);
    else
        bpf_obj = load_bpf_object_file(cfg->filename, offload_ifindex);
    if (!bpf_obj) {
        fprintf(stderr, "ERR: loading file: %s\n", cfg->filename);
        exit(EXIT_FAIL_BPF);
    }
    /* At this point: All XDP/BPF programs from the cfg->filename have been
     * loaded into the kernel, and evaluated by the verifier. Only one of
     * these gets attached to XDP hook, the others will get freed once this
     * process exit.
     */

    if (cfg->progsec[0])
        /* Find a matching BPF prog section name */
        bpf_prog = bpf_object__find_program_by_title(bpf_obj, cfg->progsec);
    else
        /* Find the first program */
        bpf_prog = bpf_program__next(NULL, bpf_obj);

    if (!bpf_prog) {
        fprintf(stderr, "ERR: couldn't find a program in ELF section '%s'\n", cfg->progsec);
        exit(EXIT_FAIL_BPF);
    }

    strncpy(cfg->progsec, bpf_program__title(bpf_prog, false), sizeof(cfg->progsec));

    prog_fd = bpf_program__fd(bpf_prog);
    if (prog_fd <= 0) {
        fprintf(stderr, "ERR: bpf_program__fd failed\n");
        exit(EXIT_FAIL_BPF);
    }

    /* At this point: BPF-progs are (only) loaded by the kernel, and prog_fd
     * is our select file-descriptor handle. Next step is attaching this FD
     * to a kernel hook point, in this case XDP net_device link-level hook.
     */
    err = xdp_link_attach(cfg->ifindex, cfg->xdp_flags, prog_fd);
    if (err)
        exit(err);

    return bpf_obj;
}

但我错了

代码语言:javascript
复制
libbpf: load bpf program failed: Permission denied
libbpf: -- BEGIN DUMP LOG ---
libbpf: 
; int index = ctx->rx_queue_index;
0: (61) r2 = *(u32 *)(r1 +16)
; int index = ctx->rx_queue_index;
1: (63) *(u32 *)(r10 -4) = r2
; void *data_end = (void *)(long)ctx->data_end;
2: (61) r2 = *(u32 *)(r1 +4)
; void *data = (void *)(long)ctx->data;
3: (61) r1 = *(u32 *)(r1 +0)
; if ((void *)eth + sizeof(*eth) <= data_end)
4: (07) r1 += 14
; if ((void *)eth + sizeof(*eth) <= data_end)
5: (2d) if r1 > r2 goto pc+25
 R1_w=pkt(id=0,off=14,r=14,imm=0) R2_w=pkt_end(id=0,off=0,imm=0) R10=fp0 fp-8=mmmm????
; memcpy(&me.dest_ip,ip,sizeof(struct iphdr));  
6: (61) r2 = *(u32 *)(r1 +16)
invalid access to packet, off=30 size=4, R1(id=0,off=30,r=14)
R1 offset is outside of the packet
processed 7 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

libbpf: -- END LOG --
libbpf: failed to load program 'xdp_sock'
libbpf: failed to load object 'af_xdp_kern.o'
ERR: loading BPF-OBJ file(af_xdp_kern.o) (-22): Invalid argument
ERR: loading file: af_xdp_kern.o

因此,在加载ebpf程序时,我得到了invalid access to packet, off=30 size=4, R1(id=0,off=30,r=14) R1 offset is outside of the packet,我有点确定由于我使用struct值作为BPF_MAP_TYPE_ARRY值类型的映射而引起的错误。

所以我想知道如果我使用libbpf允许struct作为MAP键的值,那里还有其他的映射类型吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-16 11:11:00

TL;DR..问题在于,从验证者的角度来看,您正在使不受约束地访问数据包。您需要检查数据包是否足够长,以便首先实际包含IP报头。

读取验证器错误消息.

代码语言:javascript
复制
; memcpy(&me.dest_ip,ip,sizeof(struct iphdr));  
6: (61) r2 = *(u32 *)(r1 +16)
invalid access to packet, off=30 size=4, R1(id=0,off=30,r=14)
R1 offset is outside of the packet

指令6上的验证器错误,它对应于memcpy语句。它指出,您正在对数据包进行无效访问,而R1中的偏移量保持在该数据包已知界限之外。

您检查了数据包是否至少足够长以容纳以太网报头,但从未检查它是否足够长以容纳IP报头。因此,验证器会看到您试图访问以太网标头以外的字节(最多可以偏移30)和错误。

更新数据包边界检查.

如果您从一开始就知道需要同时读取以太网和IP报头,则可以从以下位置更新检查:

代码语言:javascript
复制
if ((void *)eth + sizeof(*eth) <= data_end)

至:

代码语言:javascript
复制
if ((void *)eth + sizeof(*eth) + sizeof(struct iphdr) <= data_end)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70721661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档