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
