On Thu, Feb 9, 2017 at 5:11 AM, Daniel Borkmann <[email protected]> wrote:
> On 02/08/2017 09:22 PM, William Tu via iovisor-dev wrote:
>>
>> Hi,
>>
>> I have a program which I use around at most 300byte of local stack as
>> below. The largest struct is the "struct Headers" which is around 80
>> byte. However, when loading into the verifier, it says
>>
>> 393: (7b) *(u64 *)(r10 -56) = r1
>> 394: (05) goto pc+56
>> 451: (7b) *(u64 *)(r10 -528) = r0
>> invalid stack off=-528 size=8
>>
>> I don't think I'm using more than 512byte. It seems that the llvm
>> generates the code which use more stack memory than I thought. Any
>> idea how to debug it? Or how to dump the llvm IR to know how it
>> allocates stack? Thanks
>>
>> snippet of the code:
>> SEC("prog")
>> int ebpf_filter(struct xdp_md* skb){
>>      struct Headers hd;
>>      unsigned ebpf_packetOffsetInBits = 0;
>>      enum ebpf_errorCodes ebpf_errorCode = NoError;
>>      void* ebpf_packetStart = ((void*)(long)skb->data);
>>      void* ebpf_packetEnd = ((void*)(long)skb->data_end);
>>      u32 ebpf_zero = 0;
>>      u8 ebpf_byte = 0;
>>      u32 ebpf_outHeaderLength = 0;
>>      struct xdp_output xout;
>>      /* TODO: this should be initialized by the environment. HOW? */
>>      struct xdp_input xin;
>>
>>      goto start;
>>      start: {
>>          /* extract(hd.ethernet
>
>
> Looks like a code generation issue perhaps?

yes, I guess LLVM doesn't like the pattern we generate, I will try
different patterns to see if it makes any difference.

> It seems your prog parses and fills a huge struct on the stack, f.e. eth dest 
> is filled from
> direct packet acces byte by byte (inefficient, but fair enough). The

The performance of byte-by-byte load will be bad, but we decide to
work on correctness first.

> below annotation somehow seems to be off slightly (?), but it's always
> patterns like:

ya. it is off by 1 line.
I do try packing the structure, using
#pragma pack(1)
but makes no difference.

Thanks for your reply~
--William

>
>   r1 = *(u8 *)(r2 + 11)      ; load byte 1 from pkt into reg (u8)
>   *(u64 *)(r10 - 408) = r1   ; store byte 1 into stack (u64)
>
>   r1 = *(u8 *)(r2 + 10)      ; load byte 2 from pkt into reg (u8)
>   *(u64 *)(r10 - 416) = r1   ; store byte 2 into stack (u64)
>
> [...]
> ; void* ebpf_packetStart = ((void*)(long)skb->data);
>        2:       r2 = *(u32 *)(r6 + 0)
> [...]
> ; hd.ethernet.destination[5] = (u8)((load_byte(ebpf_packetStart,
> BYTES(ebpf_packetOffsetInBits) + 5) >> 0));
>        9:       r1 = *(u8 *)(r2 + 11)
> ; hd.ethernet.destination[4] = (u8)((load_byte(ebpf_packetStart,
> BYTES(ebpf_packetOffsetInBits) + 4) >> 0));
>       10:       *(u64 *)(r10 - 408) = r1
>       11:       r1 = *(u8 *)(r2 + 10)
> ; hd.ethernet.destination[3] = (u8)((load_byte(ebpf_packetStart,
> BYTES(ebpf_packetOffsetInBits) + 3) >> 0));
>       12:       *(u64 *)(r10 - 416) = r1
>       13:       r1 = *(u8 *)(r2 + 9)
> ; hd.ethernet.destination[2] = (u8)((load_byte(ebpf_packetStart,
> BYTES(ebpf_packetOffsetInBits) + 2) >> 0));
>       14:       *(u64 *)(r10 - 424) = r1
>       15:       r1 = *(u8 *)(r2 + 8)
> ; hd.ethernet.destination[1] = (u8)((load_byte(ebpf_packetStart,
> BYTES(ebpf_packetOffsetInBits) + 1) >> 0));
>       16:       *(u64 *)(r10 - 432) = r1
>       17:       r1 = *(u8 *)(r2 + 7)
> ; hd.ethernet.destination[0] = (u8)((load_byte(ebpf_packetStart,
> BYTES(ebpf_packetOffsetInBits) + 0) >> 0));
>       18:       *(u64 *)(r10 - 440) = r1
>       19:       r1 = *(u8 *)(r2 + 6)
> [...]
>
> Despite a struct of:
>
> struct Ethernet {
>     char source[6]; /* bit<48> */
>     char destination[6]; /* bit<48> */
>     u16 protocol; /* bit<16> */
>     u8 ebpf_valid;
> };
>
> Maybe packing structs helps a bit (but still shouldn't be such waste,
> hmm ...).
>
>> full C, objdump
>> https://gist.github.com/williamtu/5a09b60a951ee5fc062328766403ab4b
>> thanks
>> _______________________________________________
>> iovisor-dev mailing list
>> [email protected]
>> https://lists.iovisor.org/mailman/listinfo/iovisor-dev
>>
>
_______________________________________________
iovisor-dev mailing list
[email protected]
https://lists.iovisor.org/mailman/listinfo/iovisor-dev

Reply via email to