From cd3fde7d2af961b296ad61901cf00bace61944ff Mon Sep 17 00:00:00 2001 From: Vchanger Date: Thu, 6 Feb 2025 01:40:35 +0800 Subject: [PATCH] [PFM_OPT] tcpprobe: merge win/sockbuf/rtt/rate subprobes to reduce ebpf event --- .../ebpf.probe/src/tcpprobe/tcp_abn.bpf.c | 4 +- .../ebpf.probe/src/tcpprobe/tcp_delay.bpf.c | 4 +- .../ebpf.probe/src/tcpprobe/tcp_link.bpf.c | 9 +- .../ebpf.probe/src/tcpprobe/tcp_link.h | 21 ++- .../ebpf.probe/src/tcpprobe/tcp_probe.c | 149 ++---------------- .../ebpf.probe/src/tcpprobe/tcp_rate.bpf.c | 103 ------------ .../ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c | 102 ------------ .../ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c | 114 -------------- .../{tcp_windows.bpf.c => tcp_stats.bpf.c} | 121 ++++++++++---- .../ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c | 4 +- .../ebpf.probe/src/tcpprobe/tcpprobe.c | 7 +- .../ebpf.probe/src/tcpprobe/tcpprobe.h | 17 +- 12 files changed, 150 insertions(+), 505 deletions(-) delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c delete mode 100644 src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c rename src/probes/extends/ebpf.probe/src/tcpprobe/{tcp_windows.bpf.c => tcp_stats.bpf.c} (49%) diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c index 3fe0f563..54b7be48 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_abn.bpf.c @@ -38,8 +38,8 @@ static __always_inline char is_tmout_abn(struct sock *sk) u64 ts = bpf_ktime_get_ns(); u64 period = get_period(); - if ((ts > sock_stats->ts_stats.abn_ts) && ((ts - sock_stats->ts_stats.abn_ts) >= period)) { - sock_stats->ts_stats.abn_ts = ts; + if ((ts > sock_stats->ts.abn_ts) && ((ts - sock_stats->ts.abn_ts) >= period)) { + sock_stats->ts.abn_ts = ts; return 1; } return 0; diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c index 692d7499..452ea04e 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_delay.bpf.c @@ -31,8 +31,8 @@ static __always_inline char is_tmout_delay(struct sock_stats_s *sock_stats) u64 curr_ts; curr_ts = bpf_ktime_get_ns(); - if (curr_ts > sock_stats->ts_stats.delay_ts + HIST_SAMPLE_PERIOD) { - sock_stats->ts_stats.delay_ts = curr_ts; + if (curr_ts > sock_stats->ts.delay_ts + HIST_SAMPLE_PERIOD) { + sock_stats->ts.delay_ts = curr_ts; return 1; } return 0; diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c index d171068e..2a1a8c88 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.bpf.c @@ -31,9 +31,12 @@ char g_linsence[] SEC("license") = "GPL"; static __always_inline void report_srtt(void *ctx, struct tcp_metrics_s *metrics) { - metrics->report_flags |= TCP_PROBE_SRTT; - (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); - metrics->report_flags &= ~TCP_PROBE_SRTT; + u32 probe_flags = get_probe_flags(); + if (probe_flags & PROBE_RANGE_TCP_SRTT) { + metrics->report_flags |= TCP_PROBE_SRTT; + (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); + metrics->report_flags &= ~TCP_PROBE_SRTT; + } } static __always_inline struct sock_info_s* is_exist_tcp_link(struct sock *sk, char *is_exist) diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h index 71533b00..65d477c4 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_link.h @@ -94,6 +94,19 @@ static __always_inline __maybe_unused u64 get_period(void) return period; // units from second to nanosecond } +static __always_inline __maybe_unused u32 get_probe_flags(void) +{ + u32 key = 0; + struct tcp_args_s *args; + + args = (struct tcp_args_s *)bpf_map_lookup_elem(&args_map, &key); + if (args) { + return args->probe_flags; + } + + return 0; +} + static __always_inline __maybe_unused char is_valid_tgid(u32 tgid) { struct proc_s obj = {.proc_id = tgid}; @@ -108,12 +121,8 @@ static __always_inline __maybe_unused int create_tcp_link(struct sock *sk, struc sock_stats.metrics.srtt_stats.syn_srtt = syn_srtt; __builtin_memcpy(&(sock_stats.metrics.link), link, sizeof(struct tcp_link_s)); u64 ts = bpf_ktime_get_ns(); - sock_stats.ts_stats.abn_ts = ts; - sock_stats.ts_stats.win_ts = ts; - sock_stats.ts_stats.rtt_ts = ts; - sock_stats.ts_stats.txrx_ts = ts; - sock_stats.ts_stats.sockbuf_ts = ts; - sock_stats.ts_stats.rate_ts = ts; + sock_stats.ts.abn_ts = ts; + sock_stats.ts.txrx_ts = ts; return bpf_map_update_elem(&tcp_link_map, &sk, &sock_stats, BPF_ANY); } diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c index acbb231b..ff5e5e15 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_probe.c @@ -35,10 +35,7 @@ #include "tcp_tracker.h" #include "tcp_event.h" #include "tcp_tx_rx.skel.h" -#include "tcp_windows.skel.h" -#include "tcp_sockbuf.skel.h" -#include "tcp_rtt.skel.h" -#include "tcp_rate.skel.h" +#include "tcp_stats.skel.h" #include "tcp_abn.skel.h" #include "tcp_link.skel.h" #include "tcp_delay.skel.h" @@ -775,28 +772,28 @@ static int proc_tcp_metrics_evt(void *ctx, void *data, u32 size) #endif -static int tcp_load_probe_sockbuf(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) +static int tcp_load_probe_stats(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) { int err; struct bpf_buffer *buffer = NULL; - __OPEN_PROBE_WITH_OUTPUT(tcp_sockbuf, err, is_load, buffer); + __OPEN_PROBE_WITH_OUTPUT(tcp_stats, err, is_load, buffer); if (is_load) { - __SELECT_RCV_ESTABLISHED_HOOKPOINT(tcp_sockbuf); + __SELECT_RCV_ESTABLISHED_HOOKPOINT(tcp_stats); } - __LOAD_PROBE(tcp_sockbuf, err, is_load); + __LOAD_PROBE(tcp_stats, err, is_load); if (is_load) { - prog->skels[prog->num].skel = tcp_sockbuf_skel; - prog->skels[prog->num].fn = (skel_destroy_fn)tcp_sockbuf_bpf__destroy; - prog->custom_btf_paths[prog->num] = tcp_sockbuf_open_opts.btf_custom_path; + prog->skels[prog->num].skel = tcp_stats_skel; + prog->skels[prog->num].fn = (skel_destroy_fn)tcp_stats_bpf__destroy; + prog->custom_btf_paths[prog->num] = tcp_stats_open_opts.btf_custom_path; if (prog->num == 0) { // All sub-probes share a output buffer err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); if (err) { - ERROR("[TCPPROBE] Open 'tcp_sockbuf' bpf_buffer failed.\n"); + ERROR("[TCPPROBE] Open 'tcp_stats' bpf_buffer failed.\n"); goto err; } } @@ -807,115 +804,7 @@ static int tcp_load_probe_sockbuf(struct tcp_mng_s *tcp_mng, struct bpf_prog_s * return 0; err: bpf_buffer__free(buffer); - __UNLOAD_PROBE(tcp_sockbuf); - return -1; -} - -static int tcp_load_probe_rtt(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) -{ - int err; - struct bpf_buffer *buffer = NULL; - - __OPEN_PROBE_WITH_OUTPUT(tcp_rtt, err, is_load, buffer); - - if (is_load) { - __SELECT_RCV_ESTABLISHED_HOOKPOINT(tcp_rtt); - } - - __LOAD_PROBE(tcp_rtt, err, is_load); - - if (is_load) { - prog->skels[prog->num].skel = tcp_rtt_skel; - prog->skels[prog->num].fn = (skel_destroy_fn)tcp_rtt_bpf__destroy; - prog->custom_btf_paths[prog->num] = tcp_rtt_open_opts.btf_custom_path; - - if (prog->num == 0) { // All sub-probes share a output buffer - err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); - if (err) { - ERROR("[TCPPROBE] Open 'tcp_rtt' bpf_buffer failed.\n"); - goto err; - } - } - prog->buffers[prog->num] = buffer; - prog->num++; - } - - return 0; -err: - bpf_buffer__free(buffer); - __UNLOAD_PROBE(tcp_rtt); - return -1; -} - -static int tcp_load_probe_win(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) -{ - int err; - struct bpf_buffer *buffer = NULL; - - __OPEN_PROBE_WITH_OUTPUT(tcp_windows, err, is_load, buffer); - - if (is_load) { - __SELECT_SPACE_ADJUST_HOOKPOINT(tcp_windows); - } - - __LOAD_PROBE(tcp_windows, err, is_load); - - if (is_load) { - prog->skels[prog->num].skel = tcp_windows_skel; - prog->skels[prog->num].fn = (skel_destroy_fn)tcp_windows_bpf__destroy; - prog->custom_btf_paths[prog->num] = tcp_windows_open_opts.btf_custom_path; - - if (prog->num == 0) { // All sub-probes share a output buffer - err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); - if (err) { - ERROR("[TCPPROBE] Open 'tcp_windows' bpf_buffer failed.\n"); - goto err; - } - } - prog->buffers[prog->num] = buffer; - prog->num++; - } - - return 0; -err: - bpf_buffer__free(buffer); - __UNLOAD_PROBE(tcp_windows); - return -1; -} - -static int tcp_load_probe_rate(struct tcp_mng_s *tcp_mng, struct bpf_prog_s *prog, char is_load) -{ - int err; - struct bpf_buffer *buffer = NULL; - - __OPEN_PROBE_WITH_OUTPUT(tcp_rate, err, is_load, buffer); - - if (is_load) { - __SELECT_SPACE_ADJUST_HOOKPOINT(tcp_rate); - } - - __LOAD_PROBE(tcp_rate, err, is_load); - - if (is_load) { - prog->skels[prog->num].skel = tcp_rate_skel; - prog->skels[prog->num].fn = (skel_destroy_fn)tcp_rate_bpf__destroy; - prog->custom_btf_paths[prog->num] = tcp_rate_open_opts.btf_custom_path; - - if (prog->num == 0) { // All sub-probes share a output buffer - err = bpf_buffer__open(buffer, proc_tcp_metrics_evt, NULL, tcp_mng); - if (err) { - ERROR("[TCPPROBE] Open 'tcp_rate' bpf_buffer failed.\n"); - goto err; - } - } - prog->buffers[prog->num] = buffer; - prog->num++; - } - - return 0; -err: - bpf_buffer__free(buffer); - __UNLOAD_PROBE(tcp_rate); + __UNLOAD_PROBE(tcp_stats); return -1; } @@ -1057,7 +946,7 @@ err: int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struct bpf_prog_s **new_prog) { - char is_load = 0; + char is_load = 0, is_load_stats = 0; struct bpf_prog_s *prog; char is_load_txrx, is_load_abn, is_load_win, is_load_rate, is_load_rtt, is_load_sockbuf, is_load_delay, is_load_srtt; @@ -1071,6 +960,8 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc is_load_srtt = ipc_body->probe_range_flags & PROBE_RANGE_TCP_SRTT; is_load = is_load_txrx | is_load_abn | is_load_rate | is_load_win | is_load_rtt | is_load_sockbuf | is_load_delay | is_load_srtt; + is_load_stats = is_load_rate | is_load_win | is_load_rtt | is_load_sockbuf; + if (!is_load) { return 0; } @@ -1094,19 +985,7 @@ int tcp_load_probe(struct tcp_mng_s *tcp_mng, struct ipc_body_s *ipc_body, struc goto err; } - if (tcp_load_probe_rate(tcp_mng, prog, is_load_rate)) { - goto err; - } - - if (tcp_load_probe_win(tcp_mng, prog, is_load_win)) { - goto err; - } - - if (tcp_load_probe_rtt(tcp_mng, prog, is_load_rtt)) { - goto err; - } - - if (tcp_load_probe_sockbuf(tcp_mng, prog, is_load_sockbuf)) { + if (tcp_load_probe_stats(tcp_mng, prog, is_load_stats)) { goto err; } diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c deleted file mode 100644 index 5416f530..00000000 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rate.bpf.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * bpf code runs in the Linux kernel - * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifdef BPF_PROG_USER -#undef BPF_PROG_USER -#endif -#define BPF_PROG_KERN -#include -#include "bpf.h" -#include "tcp_link.h" - -char g_linsence[] SEC("license") = "GPL"; - -static __always_inline char is_tmout_rate(struct sock *sk) -{ - struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); - if (!sock_stats) { - return 0; - } - - u64 ts = bpf_ktime_get_ns(); - u64 period = get_period(); - if ((ts > sock_stats->ts_stats.rate_ts) && ((ts - sock_stats->ts_stats.rate_ts) >= period)) { - sock_stats->ts_stats.rate_ts = ts; - return 1; - } - return 0; -} - -static __always_inline void report_rate(void *ctx, struct tcp_metrics_s *metrics) -{ - metrics->report_flags |= TCP_PROBE_RATE; - (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); - metrics->report_flags &= ~TCP_PROBE_RATE; - //__builtin_memset(&(metrics->rate_stats), 0x0, sizeof(metrics->rate_stats)); -} - -// when CONFIG_HZ is 1000 -static void get_tcp_rate(struct sock *sk, struct tcp_rate* stats) -{ - struct inet_connection_sock *icsk = (struct inet_connection_sock *)sk; - // For the conversion method of jiffies to ms, please refer to: - // jiffies_to_clock_t(in kernel) and get_user_hz(in iproute2) - stats->tcpi_rto = _(icsk->icsk_rto); // ms - stats->tcpi_ato = _(icsk->icsk_ack.ato); // ms -} - -static void tcp_rate_probe_func(void *ctx, struct sock *sk) -{ - struct tcp_metrics_s *metrics; - - // Avoid high performance costs - if (!is_tmout_rate(sk)) { - return; - } - - metrics = get_tcp_metrics(sk); - if (metrics) { - get_tcp_rate(sk, &(metrics->rate_stats)); - report_rate(ctx, metrics); - } -} - -KRAWTRACE(tcp_rcv_space_adjust, bpf_raw_tracepoint_args) -{ - struct sock *sk = (struct sock*)ctx->args[0]; - tcp_rate_probe_func(ctx, sk); - return 0; -} - -KPROBE(tcp_rcv_space_adjust, pt_regs) -{ - struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); - tcp_rate_probe_func(ctx, sk); - return 0; -} - -SEC("tracepoint/tcp/tcp_rcv_space_adjust") -int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk *ctx) -{ - struct sock *sk = (struct sock*)ctx->skaddr; - tcp_rate_probe_func(ctx, sk); - return 0; -} - diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c deleted file mode 100644 index 36a8cb23..00000000 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_rtt.bpf.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * bpf code runs in the Linux kernel - * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifdef BPF_PROG_USER -#undef BPF_PROG_USER -#endif -#define BPF_PROG_KERN -#include -#include "bpf.h" -#include "tcp_link.h" - -char g_linsence[] SEC("license") = "GPL"; - -static __always_inline char is_tmout_rtt(struct sock *sk) -{ - struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); - if (!sock_stats) { - return 0; - } - - u64 ts = bpf_ktime_get_ns(); - u64 period = get_period(); - if ((ts > sock_stats->ts_stats.rtt_ts) && ((ts - sock_stats->ts_stats.rtt_ts) >= period)) { - sock_stats->ts_stats.rtt_ts = ts; - return 1; - } - return 0; -} - -static __always_inline void report_rtt(void *ctx, struct tcp_metrics_s *metrics) -{ - metrics->report_flags |= TCP_PROBE_RTT; - - (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); - - metrics->report_flags &= ~TCP_PROBE_RTT; - //__builtin_memset(&(metrics->rtt_stats), 0x0, sizeof(metrics->rtt_stats)); -} - -static void get_tcp_rtt(struct sock *sk, struct tcp_rtt* stats) -{ - u32 tmp; - struct tcp_sock *tcp_sk = (struct tcp_sock *)sk; - - tmp = _(tcp_sk->srtt_us) >> 3; // srtt_us is averaged rtt << 3 in usecs - stats->tcpi_srtt = tmp; - - tmp = _(tcp_sk->rcv_rtt_est.rtt_us); - tmp = tmp >> 3; // likewise - stats->tcpi_rcv_rtt = tmp; - return; -} - -static void tcp_rtt_probe_func(void *ctx, struct sock *sk) -{ - struct tcp_metrics_s *metrics; - - metrics = get_tcp_metrics(sk); - if (metrics) { - get_tcp_rtt(sk, &(metrics->rtt_stats)); - - // Avoid high performance costs - if (!is_tmout_rtt(sk)) { - return; - } - - report_rtt(ctx, metrics); - } -} - -KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) -{ - struct sock *sk = (struct sock*)ctx->args[0]; - tcp_rtt_probe_func(ctx, sk); - return 0; -} - -KPROBE(tcp_rcv_established, pt_regs) -{ - struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); - tcp_rtt_probe_func(ctx, sk); - return 0; -} - diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c deleted file mode 100644 index d03976e8..00000000 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_sockbuf.bpf.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * bpf code runs in the Linux kernel - * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifdef BPF_PROG_USER -#undef BPF_PROG_USER -#endif -#define BPF_PROG_KERN -#include -#include "bpf.h" -#include "tcp_link.h" - -char g_linsence[] SEC("license") = "GPL"; - -static __always_inline char is_tmout_sockbuf(struct sock *sk) -{ - struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); - if (!sock_stats) { - return 0; - } - - u64 ts = bpf_ktime_get_ns(); - u64 period = get_period(); - if ((ts > sock_stats->ts_stats.sockbuf_ts) && ((ts - sock_stats->ts_stats.sockbuf_ts) >= period)) { - sock_stats->ts_stats.sockbuf_ts = ts; - return 1; - } - return 0; -} - -static __always_inline void report_sockbuf(void *ctx, struct tcp_metrics_s *metrics) -{ - metrics->report_flags |= TCP_PROBE_SOCKBUF; - - (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); - - metrics->report_flags &= ~TCP_PROBE_SOCKBUF; - //__builtin_memset(&(metrics->sockbuf_stats), 0x0, sizeof(metrics->sockbuf_stats)); -} - -static void get_tcp_sock_buf(struct sock *sk, struct tcp_sockbuf* stats) -{ - stats->sk_rcvbuf = (int)_(sk->sk_rcvbuf); - stats->sk_sndbuf = (int)_(sk->sk_sndbuf); - -} - -static void set_last_sockbuf_stats(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) -{ - __builtin_memcpy(last_stats, stats, sizeof(struct tcp_sockbuf)); -} - -static int is_sockbuf_stats_changed(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) -{ - if (last_stats->sk_rcvbuf != stats->sk_rcvbuf) { - return 1; - } - - if (last_stats->sk_sndbuf != stats->sk_sndbuf) { - return 1; - } - return 0; -} - -static void tcp_sockbuf_probe_func(void *ctx, struct sock *sk) -{ - struct tcp_metrics_s *metrics; - struct tcp_sockbuf last_sockbuf_stats = {0}; - - // Avoid high performance costs - if (!is_tmout_sockbuf(sk)) { - return; - } - - metrics = get_tcp_metrics(sk); - if (metrics) { - set_last_sockbuf_stats(&(metrics->sockbuf_stats), &last_sockbuf_stats); - get_tcp_sock_buf(sk, &(metrics->sockbuf_stats)); - if (is_sockbuf_stats_changed(&(metrics->sockbuf_stats), &last_sockbuf_stats)) { - report_sockbuf(ctx, metrics); - } - } -} - -KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) -{ - struct sock *sk = (struct sock*)ctx->args[0]; - tcp_sockbuf_probe_func(ctx, sk); - return 0; -} - -KPROBE(tcp_rcv_established, pt_regs) -{ - struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); - tcp_sockbuf_probe_func(ctx, sk); - return 0; -} diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c similarity index 49% rename from src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c rename to src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c index 5cced8a5..d89641b1 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_windows.bpf.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_stats.bpf.c @@ -18,7 +18,6 @@ * * SPDX-License-Identifier: GPL-2.0 */ - #ifdef BPF_PROG_USER #undef BPF_PROG_USER #endif @@ -29,7 +28,7 @@ char g_linsence[] SEC("license") = "GPL"; -static __always_inline char is_tmout_win(struct sock *sk) +static __always_inline char is_tmout_stats(struct sock *sk) { struct sock_stats_s *sock_stats = bpf_map_lookup_elem(&tcp_link_map, &sk); if (!sock_stats) { @@ -38,20 +37,36 @@ static __always_inline char is_tmout_win(struct sock *sk) u64 ts = bpf_ktime_get_ns(); u64 period = get_period(); - if ((ts > sock_stats->ts_stats.win_ts) && ((ts - sock_stats->ts_stats.win_ts) >= period)) { - sock_stats->ts_stats.win_ts = ts; + if ((ts > sock_stats->ts.stats_ts) && ((ts - sock_stats->ts.stats_ts) >= period)) { + sock_stats->ts.stats_ts = ts; return 1; } return 0; } -static __always_inline void report_windows(void *ctx, struct tcp_metrics_s *metrics) +static __always_inline void report_tcp_stats(void *ctx, struct tcp_metrics_s *metrics, u32 report_flags) { - metrics->report_flags |= TCP_PROBE_WINDOWS; + if (report_flags == 0) { + return; + } + + metrics->report_flags |= report_flags; (void)bpfbuf_output(ctx, &tcp_output, metrics, sizeof(struct tcp_metrics_s)); + metrics->report_flags &= ~report_flags; +} - metrics->report_flags &= ~TCP_PROBE_WINDOWS; - //__builtin_memset(&(metrics->win_stats), 0x0, sizeof(metrics->win_stats)); +static void get_tcp_rtt(struct sock *sk, struct tcp_rtt* stats) +{ + u32 tmp; + struct tcp_sock *tcp_sk = (struct tcp_sock *)sk; + + tmp = _(tcp_sk->srtt_us) >> 3; // srtt_us is averaged rtt << 3 in usecs + stats->tcpi_srtt = tmp; + + tmp = _(tcp_sk->rcv_rtt_est.rtt_us); + tmp = tmp >> 3; // likewise + stats->tcpi_rcv_rtt = tmp; + return; } static void get_tcp_wnd(struct sock *sk, struct tcp_windows* stats) @@ -113,44 +128,94 @@ static int is_win_stats_changed(struct tcp_windows* stats, struct tcp_windows* l return 0; } -static void tcp_wnd_probe_func(void *ctx, struct sock *sk) +static void get_tcp_sock_buf(struct sock *sk, struct tcp_sockbuf* stats) +{ + stats->sk_rcvbuf = (int)_(sk->sk_rcvbuf); + stats->sk_sndbuf = (int)_(sk->sk_sndbuf); + +} + +static void set_last_sockbuf_stats(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) +{ + __builtin_memcpy(last_stats, stats, sizeof(struct tcp_sockbuf)); +} + +static int is_sockbuf_stats_changed(struct tcp_sockbuf* stats, struct tcp_sockbuf* last_stats) +{ + if (last_stats->sk_rcvbuf != stats->sk_rcvbuf) { + return 1; + } + + if (last_stats->sk_sndbuf != stats->sk_sndbuf) { + return 1; + } + return 0; +} + +// when CONFIG_HZ is 1000 +static void get_tcp_rate(struct sock *sk, struct tcp_rate* stats) +{ + struct inet_connection_sock *icsk = (struct inet_connection_sock *)sk; + // For the conversion method of jiffies to ms, please refer to: + // jiffies_to_clock_t(in kernel) and get_user_hz(in iproute2) + stats->tcpi_rto = _(icsk->icsk_rto); // ms + stats->tcpi_ato = _(icsk->icsk_ack.ato); // ms +} + +static void tcp_stats_probe_func(void *ctx, struct sock *sk) { struct tcp_metrics_s *metrics; - struct tcp_windows last_win_stats = {0}; + u32 report_flags = 0; // Avoid high performance costs - if (!is_tmout_win(sk)) { + if (!is_tmout_stats(sk)) { return; } metrics = get_tcp_metrics(sk); if (metrics) { - set_last_win_stats(&(metrics->win_stats), &last_win_stats); - get_tcp_wnd(sk, &(metrics->win_stats)); - if (is_win_stats_changed(&(metrics->win_stats), &last_win_stats)) { - report_windows(ctx, metrics); + u32 probe_flags = get_probe_flags(); + if (probe_flags & PROBE_RANGE_TCP_RTT) { + get_tcp_rtt(sk, &(metrics->rtt_stats)); + report_flags |= TCP_PROBE_RTT; } + + if (probe_flags & PROBE_RANGE_TCP_WINDOWS) { + struct tcp_windows last_win_stats = {0}; + set_last_win_stats(&(metrics->win_stats), &last_win_stats); + get_tcp_wnd(sk, &(metrics->win_stats)); + if (is_win_stats_changed(&(metrics->win_stats), &last_win_stats)) { + report_flags |= TCP_PROBE_WINDOWS; + } + } + + if (probe_flags & PROBE_RANGE_TCP_SOCKBUF) { + struct tcp_sockbuf last_sockbuf_stats = {0}; + set_last_sockbuf_stats(&(metrics->sockbuf_stats), &last_sockbuf_stats); + get_tcp_sock_buf(sk, &(metrics->sockbuf_stats)); + if (is_sockbuf_stats_changed(&(metrics->sockbuf_stats), &last_sockbuf_stats)) { + report_flags |= TCP_PROBE_SOCKBUF; + } + } + + if (probe_flags & PROBE_RANGE_TCP_RATE) { + get_tcp_rate(sk, &(metrics->rate_stats)); + report_flags |= TCP_PROBE_RATE; + } + report_tcp_stats(ctx, metrics, report_flags); } } -KRAWTRACE(tcp_rcv_space_adjust, bpf_raw_tracepoint_args) +KRAWTRACE(tcp_probe, bpf_raw_tracepoint_args) { struct sock *sk = (struct sock*)ctx->args[0]; - tcp_wnd_probe_func(ctx, sk); - return 0; -} - -KPROBE(tcp_rcv_space_adjust, pt_regs) -{ - struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx); - tcp_wnd_probe_func(ctx, sk); + tcp_stats_probe_func(ctx, sk); return 0; } -SEC("tracepoint/tcp/tcp_rcv_space_adjust") -int bpf_trace_tcp_rcv_space_adjust_func(struct trace_event_raw_tcp_event_sk *ctx) +KPROBE(tcp_rcv_established, pt_regs) { - struct sock *sk = (struct sock*)ctx->skaddr; - tcp_wnd_probe_func(ctx, sk); + struct sock *sk = (struct sock*)PT_REGS_PARM1(ctx); + tcp_stats_probe_func(ctx, sk); return 0; } diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c index bbd28359..878ece70 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcp_tx_rx.bpf.c @@ -38,8 +38,8 @@ static __always_inline char is_tmout_txrx(struct sock *sk) u64 ts = bpf_ktime_get_ns(); u64 period = get_period(); - if ((ts > sock_stats->ts_stats.txrx_ts) && ((ts - sock_stats->ts_stats.txrx_ts) >= period)) { - sock_stats->ts_stats.txrx_ts = ts; + if ((ts > sock_stats->ts.txrx_ts) && ((ts - sock_stats->ts.txrx_ts) >= period)) { + sock_stats->ts.txrx_ts = ts; return 1; } return 0; diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c index 49dd2e43..7784ac8d 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.c @@ -261,12 +261,13 @@ static void clean_tcp_pin_map() } } -static void tcp_load_args(int args_fd, struct probe_params* params) +static void tcp_load_args(int args_fd, struct ipc_body_s *ipc_body) { u32 key = 0; struct tcp_args_s args = {0}; - args.sample_period = MS2NS(params->sample_period); + args.probe_flags = ipc_body->probe_range_flags; + args.sample_period = MS2NS(ipc_body->probe_param.sample_period); (void)bpf_map_update_elem(args_fd, &key, &args, BPF_ANY); } @@ -344,7 +345,7 @@ int main(int argc, char **argv) } if (ipc_body.probe_flags & IPC_FLAGS_PARAMS_CHG || ipc_body.probe_flags == 0) { - tcp_load_args(args_map_fd, &ipc_body.probe_param); + tcp_load_args(args_map_fd, &ipc_body); } if (ipc_body.probe_flags & IPC_FLAGS_SNOOPER_CHG || ipc_body.probe_flags == 0) { diff --git a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h index 7478abf9..db517911 100644 --- a/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h +++ b/src/probes/extends/ebpf.probe/src/tcpprobe/tcpprobe.h @@ -27,6 +27,15 @@ #define TCP_LINK_TCP_PATH "/sys/fs/bpf/gala-gopher/__tcplink_tcp" #define TCP_LINK_FD_PATH "/sys/fs/bpf/gala-gopher/__tcplink_tcp_fd" +#define PROBE_RANGE_TCP_ABNORMAL 0x00000001 +#define PROBE_RANGE_TCP_WINDOWS 0x00000002 +#define PROBE_RANGE_TCP_RTT 0x00000004 +#define PROBE_RANGE_TCP_STATS 0x00000008 +#define PROBE_RANGE_TCP_SOCKBUF 0x00000010 +#define PROBE_RANGE_TCP_RATE 0x00000020 +#define PROBE_RANGE_TCP_SRTT 0x00000040 +#define PROBE_RANGE_TCP_DELAY 0x00000080 + #define TCP_PROBE_ABN (u32)(1) #define TCP_PROBE_WINDOWS (u32)(1 << 1) #define TCP_PROBE_RTT (u32)(1 << 2) @@ -188,20 +197,18 @@ struct sock_info_s { struct tcp_ts { u64 abn_ts; - u64 win_ts; - u64 rtt_ts; u64 txrx_ts; - u64 sockbuf_ts; - u64 rate_ts; + u64 stats_ts; u64 delay_ts; }; struct sock_stats_s { - struct tcp_ts ts_stats; + struct tcp_ts ts; struct tcp_metrics_s metrics; }; struct tcp_args_s { + __u32 probe_flags; __u64 sample_period; // Sampling period, unit ns }; -- Gitee