vincentmli / xdp-tools

Utilities and example programs for use with XDP
Other
1 stars 0 forks source link

xdp-sni xdp_sni.bpf.c program is too large #6

Open vincentmli opened 2 weeks ago

vincentmli commented 2 weeks ago

after add follow bpf ringbuff to xdp_sni.bpf.c, it compiles ok with clang 18.0.0 on ubuntu 22.04 , but failed to load

diff --git a/xdp-sni/xdp_sni.bpf.c b/xdp-sni/xdp_sni.bpf.c
index 51f7487..962da9d 100644
--- a/xdp-sni/xdp_sni.bpf.c
+++ b/xdp-sni/xdp_sni.bpf.c
@@ -28,7 +28,7 @@
 #include <linux/in.h>

 #define SERVER_NAME_EXTENSION 0
-#define MAX_DOMAIN_SIZE 127
+#define MAX_DOMAIN_SIZE 63 

 struct domain_name {
     struct bpf_lpm_trie_key lpm_key;
@@ -56,6 +56,31 @@ struct sni_extension {
     __u16 len;
 } __attribute__((packed));

+struct {
+        __uint(type, BPF_MAP_TYPE_RINGBUF);
+        __uint(max_entries, 1 << 12); // 4KB buffer
+        __uint(pinning, LIBBPF_PIN_BY_NAME);
+} sni_ringbuf SEC(".maps");
+
+struct sni_event {
+        __u8 len;
+        __u32 src_ip; // Store IPv4 address
+        char sni[MAX_DOMAIN_SIZE + 1];
+};
+
+static __always_inline void *custom_memcpy(void *dest, const void *src,
+                                           __u8 len)
+{
+        __u8 i;
+
+        // Perform the copy byte-by-byte to satisfy the BPF verifier
+        for (i = 0; i < len; i++) {
+                *((__u8 *)dest + i) = *((__u8 *)src + i);
+        }
+
+        return dest;
+}
+
 static __always_inline void reverse_string(char *str, __u8 len) {
     for (int i = 0; i < (len - 1) / 2; i++) {
         char temp = str[i];
@@ -199,6 +224,23 @@ int xdp_tls_sni(struct xdp_md *ctx) {

             bpf_printk("TLS SNI: %s", dn.server_name);

+           // Allocate a buffer from the ring buffer
+            struct sni_event *event = bpf_ringbuf_reserve(
+                    &sni_ringbuf, sizeof(*event), 0);
+
+            if (!event) {
+       //          bpf_printk("no space for event log\n");
+                    return XDP_PASS; // Drop if no space
+           }
+
+            // Set event fields
+            event->len = server_name_len;
+            event->src_ip = ip->saddr; // Extract source IP address
+            custom_memcpy(event->sni, dn.server_name, server_name_len);
+           event->sni[server_name_len] = '\0';
+           // Submit the event
+            bpf_ringbuf_submit(event, 0);
+
            reverse_string(dn.server_name, server_name_len);

             if (bpf_map_lookup_elem(&sni_denylist, &dn)) {

load error

; if (!event) {
164: (15) if r0 == 0x0 goto pc+54     ; R0=ringbuf_mem(ref_obj_id=3918,sz=72) refs=3918
; 
165: (bf) r1 = r0                     ; R0=ringbuf_mem(ref_obj_id=3918,sz=72) R1_w=ringbuf_mem(ref_obj_id=3918,sz=72) refs=3918
; event->len = server_name_len;
166: (73) *(u8 *)(r1 +0) = r8         ; R1_w=ringbuf_mem(ref_obj_id=3918,sz=72) R8=48 refs=3918
; event->src_ip = ip->saddr; // Extract source IP address
167: (61) r2 = *(u32 *)(r7 +26)       ; R2_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) R7=pkt(r=34) refs=3918
; event->src_ip = ip->saddr; // Extract source IP address
168: (63) *(u32 *)(r1 +4) = r2        ; R1_w=ringbuf_mem(ref_obj_id=3918,sz=72) R2_w=scalar(smin=0,smax=umax=0xffffffff,var_off=(0x0; 0xffffffff)) refs=3918
; event->len = server_name_len;
169: (bf) r7 = r8                     ; R7_w=48 R8=48 refs=3918
170: (57) r7 &= 255                   ; R7_w=48 refs=3918
; for (i = 0; i < len; i++) {
171: (15) if r7 == 0x0 goto pc+11     ; R7_w=48 refs=3918
172: (bf) r2 = r0                     ; R0=ringbuf_mem(ref_obj_id=3918,sz=72) R2_w=ringbuf_mem(ref_obj_id=3918,sz=72) refs=3918
173: (07) r2 += 8                     ; R2_w=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) refs=3918
174: (b7) r3 = 0                      ; R3=0 refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
175: (bf) r4 = r2                     ; R2=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) R4_w=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) refs=3918
176: (0f) r4 += r3                    ; R3=0 R4_w=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
177: (bf) r5 = r6                     ; R5_w=fp-68 R6=fp-68 refs=3918
178: (0f) r5 += r3                    ; R3=0 R5_w=fp-68 refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
179: (71) r5 = *(u8 *)(r5 +0)         ; R5_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff)) fp-72=mmmm384 refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
180: (73) *(u8 *)(r4 +0) = r5         ; R4_w=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) R5_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff)) refs=3918
; for (i = 0; i < len; i++) {
181: (07) r3 += 1                     ; R3_w=1 refs=3918
; for (i = 0; i < len; i++) {
182: (2d) if r7 > r3 goto pc-8        ; R3_w=1 R7=48 refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
175: (bf) r4 = r2                     ; R2=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) R4_w=ringbuf_mem(ref_obj_id=3918,off=8,sz=72) refs=3918
176: (0f) r4 += r3                    ; R3_w=1 R4_w=ringbuf_mem(ref_obj_id=3918,off=9,sz=72) refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
177: (bf) r5 = r6                     ; R5_w=fp-68 R6=fp-68 refs=3918
178: (0f) r5 += r3                    ; R3_w=1 R5_w=fp-67 refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
179: (71) r5 = *(u8 *)(r5 +0)         ; R5_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff)) fp-72=mmmm384 refs=3918
; *((__u8 *)dest + i) = *((__u8 *)src + i);
180: (73) *(u8 *)(r4 +0) = r5
BPF program is too large. Processed 1000001 insn
processed 1000001 insns (limit 1000000) max_states_per_insn 10 total_states 21646 peak_states 382 mark_read 14
-- END PROG LOAD LOG --
  libbpf: prog 'xdp_tls_sni': failed to load: -7
  libbpf: failed to load object 'xdp-sni/xdp_sni.bpf.o'
 libxdp: Got 'argument list too long' error while loading component program.
 libxdp: Falling back to loading single prog without dispatcher
 libxdp: Checking for kernel frags support
 libxdp: Loading XDP program 'xdp-dispatcher.o' from embedded object file
 ......
 libxdp: Loaded XDP program xdp_pass, got fd 6
 libxdp: Duplicated fd 6 to 7 for prog xdp_pass
 libxdp: Kernel supports XDP programs with frags
 libxdp: XDP program xdp_tls_sni is already loaded with fd -2
 libxdp: Error on fcntl: Bad file descriptorCouldn't attach XDP program on iface 'lo': Bad file descriptor(-9)
vincentmli commented 2 weeks ago

while trying to build new llvm-project from upstream on ubuntu 22.04,

     $ git clone https://github.com/llvm/llvm-project.git
     $ mkdir -p llvm-project/llvm/build
     $ cd llvm-project/llvm/build
     $ cmake .. -G "Ninja" -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
                -DLLVM_ENABLE_PROJECTS="clang"    \
                -DCMAKE_BUILD_TYPE=Release        \
                -DLLVM_BUILD_RUNTIME=OFF

got error similar to https://askubuntu.com/questions/1472032/cannot-build-darling fix the error with apt install libstdc++-12-dev

vincentmli commented 2 weeks ago

ninja -j8 to build llvm 19.1 version result in error below

cc: error: unrecognized command-line option ‘-Wcovered-switch-default’; did you mean ‘-Wno-switch-default’?
cc: error: unrecognized command-line option ‘-Wstring-conversion’; did you mean ‘-Wsign-conversion’?

llvm-project 18.1.8 has no build problem, but use clang 18.1.8 to compile xdp_sni.bpf.c did not resolve the program is too large issue.

vincentmli commented 1 week ago

by now remove the reverse_string function to avoid program is too large issue