On 01/12/2017 07:50 PM, William Tu via iovisor-dev wrote:
Hi,I observed that for direct packet access, we have to use this data and data_end checking pattern: int xdp_prog1(struct xdp_md *ctx) { void *data_end = (void *)(long)ctx->data_end; void *data = (void *)(long)ctx->data; struct ethhdr *eth = data; ... nh_off = sizeof(*eth); if (nh_off + data > data_end) return rc; --- if writing in another way like --- if ((long)nh_off > data_end - data) return rc; --- then verifier isn't able to record the packet's range (r=0): 0: (61) r2 = *(u32 *)(r1 +0) 1: (61) r1 = *(u32 *)(r1 +4) 2: (bf) r4 = r1 3: (1f) r4 -= r2 4: (b7) r3 = 14 5: (6d) if r3 s> r4 goto pc+54 R1=pkt_end R2=pkt(id=0,off=0,r=0) R3=imm14,min_value=14,max_value=14 R4=inv,min_value=14 R10=fp 6: (71) r5 = *(u8 *)(r2 +12) invalid access to packet, off=12 size=1, R2(id=0,off=0,r=0) Is this the expected behavior?
Yes, effectively in 3) you're doing data_end -= data and that will result in marking the register as unknown value by the verifier, since it doesn't pattern match alu ops with data_end as dst reg. So that carried onwards in the conditional cannot type match the pkt test, and thus access range won't get updated, so verifier correctly complains here. Hm, not sure if that's worth the extra complexity ... I'd assume for getting it to work you would need to make that result a new internal reg type and then add pattern matches against that one. _______________________________________________ iovisor-dev mailing list [email protected] https://lists.iovisor.org/mailman/listinfo/iovisor-dev
