首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解决加载名为R2的ebpf文件时出现的“bpf_cubic.c无效mem 'inv'”错误

如何解决加载名为R2的ebpf文件时出现的“bpf_cubic.c无效mem 'inv'”错误
EN

Stack Overflow用户
提问于 2022-05-01 05:01:02
回答 1查看 149关注 0票数 0

linux内核源代码版本为5.11.0

尝试加载由eBPF实现的拥塞控制算法。

文件是linux-source-5.11.0\tools\testing\selftests\bpf\progs\bpf_cubic.c.

我使用了libbpf引导程序,所以我对代码做了一些修改,但我不认为这是问题所在,因为我没有更改出错的部分。我的更改主要集中在用户状态代码上。除了以前的编译错误外,内核状态代码几乎没有变化:

代码语言:javascript
复制
/* No prefix in SEC will also work.
 * The remaining tcp-cubic functions have an easier way.
 */
/*
* 
* changes:
*         comment out this sentence://SEC("no-sec-prefix-bictcp_cwnd_event")
*         add the code SEC("struct_ops/bictcp_cwnd_event")
*/
//SEC("no-sec-prefix-bictcp_cwnd_event")
SEC("struct_ops/bictcp_cwnd_event")
void BPF_PROG(bictcp_cwnd_event, struct sock *sk, enum tcp_ca_event event)
{
    if (event == CA_EVENT_TX_START) {
        struct bictcp *ca = inet_csk_ca(sk);
        __u32 now = tcp_jiffies32;
        __s32 delta;

        delta = now - tcp_sk(sk)->lsndtime;

        /* We were application limited (idle) for a while.
         * Shift epoch_start to keep cwnd growth to cubic curve.
         */
        if (ca->epoch_start && delta > 0) {
            ca->epoch_start += delta;
            if (after(ca->epoch_start, now))
                ca->epoch_start = now;
        }
        return;
    }
}

加载此文件时,编译成功,但加载时会报告错误。错误是:

代码语言:javascript
复制
R0=inv(id=26,umin_value=1152921504606846976,umax_value=11517967026549683715) 
R1_rw=invP(id=26,umin_value=1152921504606846976,umax_value=11517967026549683715) R2_r=inv0             
R3=invP(id=26,umin_value=1152921504606846976,umax_value=11517967026549683715) 
R4_w=inv1152921504606846976 R5_rw=invP63 R6_r=ptr_tcp_sock(id=0,off=0,imm=0) R7_r=inv(id=2) 
R8_r=ptr_tcp_sock(id=0,off=1296,imm=0) R9_r=inv(id=8,umax_value=4294967295,var_off=(0x0;0xffffffff)) R10=fp0 fp-8_r=inv
parent already had regs=2a stack=0 marks
; x = ((__u32)(((__u32)v[shift] + 10) << b)) >> 6;
232: (18) r2 = 0xffffa7ee80066000
234: (0f) r2 += r1
235: (71) r5 = *(u8 *)(r2 +0)
R2 invalid mem access 'inv'
processed 544 insns (limit 1000000) max_states_per_insn 2 total_states 30 peak_states 30 mark_read 10
-- END PROG LOAD LOG --
libbpf: failed to load program 'bictcp_cong_avoid'
libbpf: failed to load object 'bpf_cubic_bpf'
libbpf: failed to load BPF skeleton 'bpf_cubic_bpf': -13
Failed to load and verify BPF skeleton

我发现错误的代码是x = ((__u32)(((__u32)v[shift] + 10) << b)) >> 6;在函数static __always_inline __u32 cubic_root(__u64 a)

如果我注释掉这句话,或者用一个数字替换shift,我可以加载这个项目。

我试图添加一些范围验证,但仍然无法加载。

代码语言:javascript
复制
    if (shift >= 64){
        return 0;
    }else{
        x = ((__u32)(((__u32)v[shift] + 10) << b)) >> 6;

        /*
        * Newton-Raphson iteration
        *                         2
        * x    = ( 2 * x  +  a / x  ) / 3
        *  k+1          k         k
        */
        x = (2 * x + (__u32)div64_u64(a, (__u64)x * (__u64)(x - 1)));
        x = ((x * 341) >> 10);
    }

函数的全部代码是

代码语言:javascript
复制
/*
 * cbrt(x) MSB values for x MSB values in [0..63].
 * Precomputed then refined by hand - Willy Tarreau
 *
 * For x in [0..63],
 *   v = cbrt(x << 18) - 1
 *   cbrt(x) = (v[x] + 10) >> 6
 */
static const __u8 v[] = {
/* 0x00 */    0,   54,   54,   54,  118,  118,  118,  118,
/* 0x08 */  123,  129,  134,  138,  143,  147,  151,  156,
/* 0x10 */  157,  161,  164,  168,  170,  173,  176,  179,
/* 0x18 */  181,  185,  187,  190,  192,  194,  197,  199,
/* 0x20 */  200,  202,  204,  206,  209,  211,  213,  215,
/* 0x28 */  217,  219,  221,  222,  224,  225,  227,  229,
/* 0x30 */  231,  232,  234,  236,  237,  239,  240,  242,
/* 0x38 */  244,  245,  246,  248,  250,  251,  252,  254,
};

/* calculate the cubic root of x using a table lookup followed by one
 * Newton-Raphson iteration.
 * Avg err ~= 0.195%
 */
static __always_inline __u32 cubic_root(__u64 a)
{
    __u32 x=0, b, shift;

    if (a < 64) {
        /* a in [0..63] */
        return ((__u32)v[(__u32)a] + 35) >> 6;
    }

    b = fls64(a);
    b = ((b * 84) >> 8) - 1;
    shift = (a >> (b * 3));

    /* it is needed for verifier's bound check on v */
    if (shift >= 64){
        return 0;
    }else{
        x = ((__u32)(((__u32)v[shift] + 10) << b)) >> 6;

        /*
        * Newton-Raphson iteration
        *                         2
        * x    = ( 2 * x  +  a / x  ) / 3
        *  k+1          k         k
        */
        x = (2 * x + (__u32)div64_u64(a, (__u64)x * (__u64)(x - 1)));
        x = ((x * 341) >> 10);
    }
    return x;
}
EN

回答 1

Stack Overflow用户

发布于 2022-05-03 14:35:29

谢谢你的回答。

我的一个朋友告诉我,我应该通过:

代码语言:javascript
复制
if(v[shift]){
...
}

他告诉我,我应该判断数组的对应位置是否存在,而不是直接判断“移位”的大小。

我这样修改了它,程序确实通过了验证。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72074115

复制
相关文章

相似问题

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