From 256008a6d97247e3dc5df10c7755a1fc6e0ebee7 Mon Sep 17 00:00:00 2001 From: Afek Berger Date: Wed, 18 Sep 2024 14:15:04 +0300 Subject: [PATCH 1/2] Enlarge map size --- .../gadgets/http/tracer/bpf/http-sniffer.c | 13 +++++++------ .../gadgets/http/tracer/http_sniffer_bpfel.o | Bin 125352 -> 125352 bytes 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c b/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c index 36d6a6ff..be19a8ef 100644 --- a/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c +++ b/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c @@ -11,7 +11,7 @@ struct { // Used to manage pre accept connections from client struct { __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 4096); + __uint(max_entries, 8192); __type(key, __u64); __type(value, struct pre_accept_args); } pre_accept_args_map SEC(".maps"); @@ -19,7 +19,7 @@ struct { // Used to manage active http connections to monitor struct { __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 4096); + __uint(max_entries, 8192); __type(key, __u64); __type(value, struct pre_connect_args); } active_connections_args_map SEC(".maps"); @@ -27,7 +27,7 @@ struct { // Used to manage active http connections to monitor as server struct { __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 4096); + __uint(max_entries, 8192); __type(key, __u64); __type(value, struct active_connection_info); } accepted_sockets_map SEC(".maps"); @@ -35,7 +35,7 @@ struct { // Used to store the buffer of packets struct { __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 4096); + __uint(max_entries, 8192); __type(key, __u64); __type(value, struct packet_buffer); } buffer_packets SEC(".maps"); @@ -43,7 +43,7 @@ struct { // Used to store the buffer of messages of messages type struct { __uint(type, BPF_MAP_TYPE_HASH); - __uint(max_entries, 4096); + __uint(max_entries, 8192); __type(key, __u64); __type(value, struct packet_msg); } msg_packets SEC(".maps"); @@ -128,7 +128,7 @@ static __always_inline int populate_httpevent(struct httpevent *event) return 0; } -static __always_inline void enrich_ip_port(struct trace_event_raw_sys_enter *ctx, __u32 sockfd, struct httpevent *event) +static __always_inline void enrich_ip_port(struct trace_event_raw_sys_exit *ctx, __u32 sockfd, struct httpevent *event) { __u64 id = bpf_get_current_pid_tgid(); __u64 unique_connection_id = generate_unique_connection_id(id, sockfd); @@ -373,6 +373,7 @@ static __always_inline int process_msg(struct trace_event_raw_sys_exit *ctx, cha } } bpf_map_delete_elem(&msg_packets, &id); + return 0; } SEC("tracepoint/syscalls/sys_enter_accept") diff --git a/pkg/ebpf/gadgets/http/tracer/http_sniffer_bpfel.o b/pkg/ebpf/gadgets/http/tracer/http_sniffer_bpfel.o index 92f2e6d09193ec14d19123568c0b0c07fb825560..5934b035e09a6570028c0de0dae7d4adee156e6b 100644 GIT binary patch delta 960 zcmZ{iOK1~O6o&tU&Al@a8zZfDCe#GQ5V2@%gD7GeCD2l>4^#vjBoqaag1XCEA}DSm zDC0&@2$)K+0l{0eiy$f}_<(MtNb$9j;&UUeJa;mMI}7h>zH@%Qb7t-|=4E4Eww_H= z>cR8L-*x(-9!ZLk6BVd#0g~vPi4{PD8GYX0l{BNS*_0(WCvbNgu-XW{Vn#uz$CA3q zDG4M7!fXI>O2!)kqXg(h`i6i=(_7&3SX1D9Q2xaG zt*HxC0zRu_ErD9V$GA_k0&TAM8^b;`8JL16QCplqbZnX#nYIDL<} zmc+^3K+5P}Vn&bDmg)2hhTe=sCK$cM9BmP@0qee_Hd33IQB@~$G%VcP7H0PW8;$-VGn&3-I-TCnd$z6rUW4x2ZFO-M zog?S1g;UJtuq(`X9}N3r;VZNGO0jY7ciEjkCtjo!xhWe%2f~))%owoMM2_;p9kub0 e3#Mj42abj`Q#N)U3~Nfvs013Ssh3A+@y0)et){U6 delta 960 zcmZ{iO-K}B7{~t)x$ipzy1 zGfxL7b^qDGuL)XGk0d3@u>?l916kBg?+PGbMuY!n6-}#aHhJWF0(W)-tBuerX6zN} zv7~x(dIU19aZ8CAgNDT!5xC052E#I~Lt|lx#{IkXlub_v93((5vaStC1pWe-I|G69 zQTY?^w`N@6V#H^4Y)YUK@d@tJ1A#fNHyOh|GhOJ7z(FFJG-N-X^(4)%&07DrX+50!PGp_f!Ubmt;D8MT+_jf z56har5&;()xu%c4kk=)Cu&nS4`nPvb#mQONb^zF*6MS^&7&AQ8>Cqc#}ld*~cFFD(o*o5QX!<6SiDw}r3F<|`$;^<=yD=cLQjOzwIcZHMEQlgwzbRd0cc k!Y$i)$OTigpaVx^njsszkHj^7%ovU|G^So0r^W0404(9AzyJUM From 3e9bceff6957a97ada081a8d55df4501308a7684 Mon Sep 17 00:00:00 2001 From: Afek Berger Date: Wed, 18 Sep 2024 17:46:29 +0300 Subject: [PATCH 2/2] Modified map type --- .../gadgets/http/tracer/bpf/http-sniffer.c | 10 +++++----- .../gadgets/http/tracer/http_sniffer_bpfel.o | Bin 125352 -> 125392 bytes 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c b/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c index be19a8ef..96ea3a11 100644 --- a/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c +++ b/pkg/ebpf/gadgets/http/tracer/bpf/http-sniffer.c @@ -10,7 +10,7 @@ struct { // Used to manage pre accept connections from client struct { - __uint(type, BPF_MAP_TYPE_HASH); + __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 8192); __type(key, __u64); __type(value, struct pre_accept_args); @@ -18,7 +18,7 @@ struct { // Used to manage active http connections to monitor struct { - __uint(type, BPF_MAP_TYPE_HASH); + __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 8192); __type(key, __u64); __type(value, struct pre_connect_args); @@ -26,7 +26,7 @@ struct { // Used to manage active http connections to monitor as server struct { - __uint(type, BPF_MAP_TYPE_HASH); + __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 8192); __type(key, __u64); __type(value, struct active_connection_info); @@ -34,7 +34,7 @@ struct { // Used to store the buffer of packets struct { - __uint(type, BPF_MAP_TYPE_HASH); + __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 8192); __type(key, __u64); __type(value, struct packet_buffer); @@ -42,7 +42,7 @@ struct { // Used to store the buffer of messages of messages type struct { - __uint(type, BPF_MAP_TYPE_HASH); + __uint(type, BPF_MAP_TYPE_LRU_HASH); __uint(max_entries, 8192); __type(key, __u64); __type(value, struct packet_msg); diff --git a/pkg/ebpf/gadgets/http/tracer/http_sniffer_bpfel.o b/pkg/ebpf/gadgets/http/tracer/http_sniffer_bpfel.o index 5934b035e09a6570028c0de0dae7d4adee156e6b..c1926bd6cc44cfc040775aebf9352e6ef37c89a9 100644 GIT binary patch delta 16720 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 Y z^Cz$CnFAl}qwnOz$((>zHQ5CC#Oq-+`jU#0a}%BRYyMN({!MH+kzuOG{oSH^+}}4; zkNYbdbD#c>aRr^pHM4yI`mf*L=>zt&zxz9%a<1&tzkR#+@0`#11OLtaEA;=P{aZF@ zKl|s76=on_pZ-4UQ_k^!>U@xbmsgaW_b;9g;Xdt=N8!!b;`3ELR*4>OTe+|7v%dbZ z{WF<@WOJrFyY=W^i$p)6Po&EeO6GZSCVJ+6T!_wjF?c`6KRz$w{lD*d5uXq7c_Dvp zoY{Z*89%fC+&0tu4uI>x|95`;D*b1?8n&&t<^06a`*mpUdx-2i>Dwt+ZW{3*$-RG{ zN#3`QfBz8qRXSO*Y{-62^8WTuo?ZTf{aZIQ(d&_)hbAWFr6=>$B_c<_2Et7l`t9h8 zGxSC1D>L-F(I3pv7o&$6`u*rzGxR&r-^kD(;Ex>4hZ%+yIDD0%FGtVTM{Id%xRsE4 zq+m*-*6_sn6|LV&Je?R=QTbLPotRZo{&phmy)nMxleZJo64@2y?_ecSA`;&v+EP&| z(ZGuG_lOo&R7%vUqI@UO=!!}r@5hN1V|J1MxQfbMShrM^zc1EF6`#D1wRc7N2UurS zR7#XxQT`!O?}|!^aQ(A0R!TIhqWmKqU?&+ Sl|)S{$|ZWVVpV0L=)VC*!r2f2