-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Checksum code does not work for LLVM-14, but it works for LLVM-13 #4612
Comments
Hi @luokaink, I guess LLVM-14 is applying some kind of optimization that makes the eBPF verifier loose track of the check on packet boundary in the for loop. __u16 * volatile buf = (void *)udph; This unfortunately will make the code slower, since every operation involving the variable will fetch it from memory, instead of keeping it into a register. Let me know if it works for you. |
Hi @FedeParola , thanks a lot for your response. I think this solution is just a workaround for this issue. Is there a plan to fix this issue completely? I just use LLVM-12 in my code to avoid this issue by now |
@luokaink Can you post a minimal script to repro the issue ? |
#include <linux/ethtool.h> #include <bcc/BPF.h> #define XDP_PROGRAM "xdp_prog" // ebpf kernel program code #define MAX_UDP_SIZE 1480 static __always_inline void set_udp_csum(struct iphdr *iph, struct udphdr *udph, void *data_end) udph->check = 0; // Compute pseudo-header checksum // Compute checksum on udp header + payload
} if ((void *)buf + 1 <= data_end) { __u16 csum = (__u16)csum_buffer + (__u16)(csum_buffer >> 16); udph->check = csum; int xdp_prog(struct xdp_md *ctx) { // Drop the malformed packet eth = (struct ethhdr *)data; iph = data + sizeof(struct ethhdr); struct udphdr *udp; set_udp_csum(iph, udp, data_end); return XDP_PASS; void init_port_map(const char *net_dev) { auto result = bpf.init(BPF_BATCH_PROGRAM); int fd = -1; auto attach_result = bpf_attach_xdp(net_dev, fd, 0); int main() { |
Ya, the following is problematic w.r.t. verifier,
I tried to use For this case, we won't be able to fix verifier as the complexity to enhance verifier for such cases |
The following is another workaround with asm code. Hopefully it won't impact performance a lot.
I understand using asm code as a workaround is not pleasant. The transformation like |
I did further investigation. The transformation like Currently in bcc infrastructure, after initial IR is generated, there is an optimization pass (see |
attribute((always_inline))
static inline __u16 caludpcsum(struct iphdr *iph, struct udphdr *udph, void *data_end)
{
__u32 csum_buffer = 0;
__u16 *buf = (void *)udph;
}
The above code does not work for LLVM-14 in ubutun 22.04, but it works for LLVM-13/LLVM-12. I think there is a bug in LLVM-14 with bcc. The error code:
; for (u16 i = 0; i < MAX_UDP_SIZE; i += 2) {
43: (2d) if r7 > r6 goto pc+158 ; R6=pkt_end(off=0,imm=0) R7=pkt(off=36,r=42,imm=0)
44: (bf) r9 = r6 ; R6=pkt_end(off=0,imm=0) R9_w=pkt_end(off=0,imm=0)
45: (1f) r9 -= r8 ; R8=pkt(off=0,r=42,imm=0) R9_w=scalar()
46: (07) r9 += -36 ; R9_w=scalar()
47: (77) r9 >>= 1 ; R9_w=scalar(umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff))
48: (b7) r1 = 739 ; R1_w=739
49: (2d) if r1 > r9 goto pc+1 ; R1_w=739 R9_w=scalar(umin=739,umax=9223372036854775807,var_off=(0x0; 0x7fffffffffffffff))
50: (b7) r9 = 739 ; R9=739
51: (b7) r5 = 0 ; R5_w=0
52: (b7) r2 = 7 ; R2_w=7
53: (bf) r1 = r7 ; R1_w=pkt(off=36,r=42,imm=0) R7=pkt(off=36,r=42,imm=0)
54: (2d) if r2 > r9 goto pc+134 ; R2_w=P7 R9=P739
55: (7b) *(u64 *)(r10 -128) = r8 ; R8=pkt(off=0,r=42,imm=0) R10=fp0 fp-128_w=pkt
56: (7b) *(u64 *)(r10 -136) = r3 ; R3=pkt(off=34,r=42,imm=0) R10=fp0 fp-136_w=pkt
57: (7b) *(u64 *)(r10 -152) = r6 ; R6=pkt_end(off=0,imm=0) R10=fp0 fp-152_w=pkt_end
58: (79) r1 = *(u64 *)(r10 -96) ; R1_w=scalar(id=1,umax=4294967295,var_off=(0x0; 0xffffffff)) R10=fp0
59: (7b) *(u64 *)(r10 -112) = r7 ; R7=pkt(off=36,r=42,imm=0) R10=fp0 fp-112_w=pkt
60: (07) r9 += 1 ; R9_w=P740
61: (bf) r1 = r9 ; R1_w=P740 R9_w=P740
62: (bf) r8 = r4 ; R4=scalar(id=4,umin=4352,umax=332027,var_off=(0x0; 0x7ffff)) R8_w=scalar(id=4,umin=4352,umax=332027,var_off=(0x0; 0x7ffff))
63: (b7) r9 = 0 ; R9_w=0
64: (7b) *(u64 *)(r10 -160) = r1 ; R1_w=P740 R10=fp0 fp-160_w=P740
65: (57) r1 &= 2040 ; R1_w=P736
66: (7b) *(u64 *)(r10 -104) = r1 ; R1_w=P736 R10=fp0 fp-104_w=P736
67: (07) r1 += -8 ; R1_w=P728
68: (bf) r5 = r1 ; R1_w=P728 R5_w=P728
69: (77) r5 >>= 3 ; R5_w=P91
70: (07) r5 += 1 ; R5_w=P92
71: (bf) r2 = r5 ; R2_w=P92 R5_w=P92
72: (57) r2 &= 1 ; R2_w=P0
73: (7b) *(u64 *)(r10 -168) = r2 ; R2_w=P0 R10=fp0 fp-168_w=00000000
74: (b7) r2 = 0 ; R2_w=0
75: (7b) *(u64 *)(r10 -144) = r2 ; R2_w=P0 R10=fp0 fp-144_w=00000000
76: (b7) r7 = 0 ; R7_w=0
77: (b7) r6 = 0 ; R6_w=0
78: (b7) r4 = 0 ; R4_w=0
79: (b7) r2 = 0 ; R2_w=0
80: (b7) r3 = 0 ; R3_w=0
81: (b7) r0 = 0 ; R0_w=0
82: (15) if r1 == 0x0 goto pc+51 ; R1_w=P728
83: (18) r1 = 0x3ffffffffffffffe ; R1_w=4611686018427387902
85: (5f) r5 &= r1 ; R1_w=P4611686018427387902 R5_w=P92
86: (b7) r4 = 0 ; R4_w=0
87: (79) r1 = *(u64 *)(r10 -128) ; R1_w=pkt(off=0,r=42,imm=0) R10=fp0
88: (07) r1 += 58 ; R1_w=pkt(off=58,r=42,imm=0)
89: (bf) r2 = r5 ; R2_w=P92 R5_w=P92
90: (67) r2 <<= 3 ; R2_w=P736
91: (7b) *(u64 *)(r10 -144) = r2 ; R2_w=P736 R10=fp0 fp-144_w=P736
92: (b7) r7 = 0 ; R7_w=0
93: (b7) r6 = 0 ; R6_w=0
94: (b7) r2 = 0 ; R2_w=0
95: (b7) r3 = 0 ; R3_w=0
96: (b7) r0 = 0 ; R0=0
97: (7b) *(u64 *)(r10 -88) = r5 ; R5=P92 R10=fp0 fp-88_w=P92
; sum += *ip_payload++;
98: (69) r5 = *(u16 *)(r1 -24) ; R1=pkt(off=58,r=42,imm=0) R5_w=scalar(umax=65535,var_off=(0x0; 0xffff))
; sum += *ip_payload++;
99: (0f) r8 += r5 ; R5_w=scalar(umax=65535,var_off=(0x0; 0xffff)) R8_w=scalar(umin=4352,umax=397562,var_off=(0x0; 0x7ffff))
; sum += *ip_payload++;
100: (69) r5 = *(u16 *)(r1 -16)
invalid access to packet, off=42 size=2, R1(id=0,off=42,r=42)
R1 offset is outside of the packet
processed 100 insns (limit 1000000) max_states_per_insn 0 total_states 4 peak_states 4 mark_read 2
The text was updated successfully, but these errors were encountered: