On Mon, Mar 18, 2019 at 4:18 AM Simon <[email protected]> wrote:
>
> Thx a lot again for your time and your detailed explanation.
>
> About the workaround you proposed, I didn't get where I should repeat __u16 
> udp_len = bpf_ntohs(udp->len);.. I tried several spot but didn't succeed to 
> make it works.

This is a tough issue. I spent a couple of hours trying various source
workaround and did not succeed.
To illustrate my experiment, the following is what I tried to do to
move the code udp_len calculation and its usage closer to each other
to avoid register spill/refills.

```
-bash-4.4$ diff ulb.c ulb.c.org
61,62c61,62
< static inline int ipv4_l4_csum(struct udphdr *data_start, __u32 data_size,
<                                 __u64 *csum, struct iphdr *iph, void
*data_end) {
---
> static inline void ipv4_l4_csum(void *data_start, __u32 data_size,
>                                 __u64 *csum, struct iphdr *iph) {
70,87c70,71
<
<   data_start = iph + 1;
<   if (data_start + 1 > data_end)
<       return XDP_DROP;
<   data_size = bpf_ntohs(data_start->len);
<   if (data_size < 8)
<       return -1;
<   if (data_size > 512)
<       return -1;
<   data_size = data_size & 0x1ff;
<   data_start = (void *)data_start + data_size;
<   if ((void *) data_start <= data_end) {
<     *csum = bpf_csum_diff(0, 0, (void *)data_start - data_size,
data_size, *csum);
<     *csum = csum_fold_helper(*csum);
<     return 0;
<   }
<
<   return -1;
---
>   *csum = bpf_csum_diff(0, 0, data_start, data_size, *csum);
>   *csum = csum_fold_helper(*csum);
140a125,132
>     __u16 udp_len = bpf_ntohs(udp->len);
>     if (udp_len < 8)
>         return XDP_DROP;
>     if (udp_len > 512) // TODO use a more approriate max value
>         return XDP_DROP;
>     udp_len = udp_len & 0x1ff;
>     if ((void *) udp + udp_len > data_end)
>         return XDP_DROP;
200,203c192
<     __u16 udp_len = 0;
<     int ret = ipv4_l4_csum(udp, udp_len, &cs, iph, data_end) ;
<     if (ret == -1)
<       return XDP_DROP;
---
>     ipv4_l4_csum(udp, udp_len, &cs, iph) ;
-bash-4.4$
```

But my attempt above not working. The main reason is the compiler is
always trying to
use the original assignment register
   data_start = iph + 1;           /* data_start is in r8 */
   /* r1 = r8, and below r1 is used for data_start */
   if (data_start   + 1 > data_end)
      return XDP_DROP;
   ...
   *csum = bpf_csum_diff(0, 0, (void *)data_start - data_size,
data_size, *csum);  /* data_start in r8 */

The data_start is refined in r1 while r8 is used in the final argument passing.

I think I need to look at kernel verifier side and compiler side.

> By the way repeat it, means probably shifting byte again ... so I pretty sure 
> I didn't  get well what you mean :/ ... Did you succeed to make it works with 
> this workaround ?
>
> This is maybe a stupid question, but it seems to me that I'm not doing so 
> exotic code here. I mean calculate a checksum with XDP and I fall in not so 
> easy "issues". Is there something I do which is totally wrong or uncommon ?

You are not. The compiler is doing optimization which make verifier
fail. It is possible an early compiler with less optimizations may
work.

>
> I will take a look at SCALAR_VALUE issue later on.But if you or anybody has 
> cycles and want to look into this issue,feel free to do so.
>
> I didn't have enough skill to do that, I'm not even sure to understand what 
> "spill/reload" means ?

Something like:
    udp_len = ...
    ...
    ... = udp_len

The generated code:
     store_to_stack for udp_len;
     ...
     get udp_len value from stack
     use udp_len

> 

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.

View/Reply Online (#1613): https://lists.iovisor.org/g/iovisor-dev/message/1613
Mute This Topic: https://lists.iovisor.org/mt/30315706/21656
Mute #verifier: https://lists.iovisor.org/mk?hashtag=verifier&subid=2590197
Group Owner: [email protected]
Unsubscribe: https://lists.iovisor.org/g/iovisor-dev/unsub  
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to