On Fri, Feb 10, 2017 at 9:08 AM, William Tu <[email protected]> wrote:
> my program is too huge so I start with simple example using xdp1_kern.c
> I tried adding an ethernet header as local variable:
>
> --- a/samples/bpf/xdp1_kern.c
> +++ b/samples/bpf/xdp1_kern.c
> @@ -51,10 +51,19 @@ int xdp_prog1(struct xdp_md *ctx)
>         u64 nh_off;
>         u32 ipproto;
>
> +       struct ethhdr myeth;
> +
>         nh_off = sizeof(*eth);
>         if (data + nh_off > data_end)
>                 return rc;
>
> +       myeth.h_dest[0] = eth->h_source[0];
> +       myeth.h_dest[1] = eth->h_source[1];
> +       myeth.h_dest[2] = eth->h_source[2];
> +       myeth.h_dest[3] = eth->h_source[3];
> +       myeth.h_dest[4] = eth->h_source[4];
> +       myeth.h_dest[5] = eth->h_source[5];
> +
>         h_proto = eth->h_proto;
>
>         if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
> @@ -87,6 +96,7 @@ int xdp_prog1(struct xdp_md *ctx)
>         if (value)
>                 *value += 1;
>
> +       memcpy(eth, &myeth, sizeof(myeth));
>         return rc;
>  }
> ---------
> Then using llvm-objdump, it shows:
>
> ; myeth.h_dest[5] = eth->h_source[5];
>       24: r4 = *(u8 *)(r1 + 11)
> ; myeth.h_dest[4] = eth->h_source[4];
>       25: r5 = *(u8 *)(r1 + 10)
> ; myeth.h_dest[3] = eth->h_source[3];
>       26: r0 = *(u8 *)(r1 + 9)
> ; myeth.h_dest[2] = eth->h_source[2];
>       27: r6 = *(u8 *)(r1 + 8)
> ; myeth.h_dest[1] = eth->h_source[1];
>       28: r7 = *(u8 *)(r1 + 7)
> ; myeth.h_dest[0] = eth->h_source[0];
>       29: r8 = *(u8 *)(r1 + 6)
>       30: r1 += 6
> ; if (h_proto == htons(ETH_P_8021Q) || h_proto == htons(ETH_P_8021AD)) {
>       31: *(u64 *)(r10 - 72) = r1
>       32: *(u64 *)(r10 - 80) = r2
>       33: *(u64 *)(r10 - 88) = r3
>       34: *(u64 *)(r10 - 96) = r4
>       35: *(u64 *)(r10 - 104) = r5
>       36: *(u64 *)(r10 - 112) = r0
>       37: *(u64 *)(r10 - 120) = r6
>       38: *(u64 *)(r10 - 128) = r7
>       39: *(u64 *)(r10 - 136) = r8
> ----
> by observing that it's always 8 byte offset, r10 - 136, 128, 120, 112....
> the local variable myeth.h_dest[6] seems to take 6 * 8 = 48 Byte on stack.
> and my ethernet header will take 8 * (6+6) + 2 = 50 Byte

interesting.
in this case 'struct ethhdr myeth' doesn't actually exist on stack.
Compiler kept it in regsiters, but due to function call it had to spill
those registers to stack. Every register is 8-byte, hence you see so much
stack usage. With llvm trunk I see better code, but it still spills.
I don't have a workaround yet.
_______________________________________________
iovisor-dev mailing list
[email protected]
https://lists.iovisor.org/mailman/listinfo/iovisor-dev

Reply via email to