Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions agent/src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1033,13 +1033,15 @@ pub struct EbpfFileIoEvent {
pub collect_mode: usize,
#[serde(with = "humantime_serde")]
pub minimal_duration: Duration,
pub enable_virtual_file_collect: bool,
}

impl Default for EbpfFileIoEvent {
fn default() -> Self {
Self {
collect_mode: 1,
minimal_duration: Duration::from_millis(1),
enable_virtual_file_collect: false,
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions agent/src/config/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3313,6 +3313,14 @@ impl ConfigHandler {
io_event.minimal_duration = new_io_event.minimal_duration;
restart_agent = !first_run;
}
if io_event.enable_virtual_file_collect != new_io_event.enable_virtual_file_collect {
info!(
"Update inputs.ebpf.file.io_event.enable_virtual_file_collect from {:?} to {:?}.",
io_event.enable_virtual_file_collect, new_io_event.enable_virtual_file_collect
);
io_event.enable_virtual_file_collect = new_io_event.enable_virtual_file_collect;
restart_agent = !first_run;
}
if ebpf.java_symbol_file_refresh_defer_interval
!= new_ebpf.java_symbol_file_refresh_defer_interval
{
Expand Down
60 changes: 57 additions & 3 deletions agent/src/ebpf/kernel/files_rw.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,68 @@

// Default value set when file read/write latency timestamp rollback occurs.
#define TIME_ROLLBACK_DEFAULT_LATENCY_NS 50000
#define FILE_CHECK_ERROR (-1) /* Error or exceptional condition */
#define FILE_TYPE_REGULAR 0 /* Regular (non-virtual) file */
#define FILE_TYPE_VIRTUAL 1 /* Virtual file */

static __inline bool is_regular_file(int fd,
struct member_fields_offset *off_ptr)
static __inline int check_virtual_file(void *file, struct member_fields_offset *offset)
{
if (!file || !offset)
return FILE_CHECK_ERROR;

/*
* Determine whether a file belongs to a regular VFS filesystem
* based on the existence of file->f_op->read_iter.
*
* file->f_op->read_iter != NULL:
* Regular VFS-backed files, including:
* - ext4 / xfs / btrfs
* - NFS / CIFS / CephFS
* - tmpfs / ramfs
* - overlayfs
* - fuse
*
* file->f_op->read_iter == NULL:
* Non-VFS or special kernel objects, including:
* - IPC objects (pipe / fifo)
* - socket-related objects
* - anon_inode derived objects
* - some procfs / sysfs entries
* - certain character devices or special driver files
* - kernel objects without regular VFS file semantics
*/
void *f_op, *read_iter;
bpf_probe_read_kernel(&f_op, sizeof(f_op),
file + offset->struct_file_f_op_offset);
if (f_op == NULL)
return FILE_CHECK_ERROR;

bpf_probe_read_kernel(&read_iter, sizeof(read_iter),
f_op +
offset->struct_file_operations_read_iter_offset);
if (read_iter == NULL)
return FILE_TYPE_VIRTUAL;

return FILE_TYPE_REGULAR;
}

static __inline bool is_readable_file(int fd,
bool disable_vfile_collect,
struct member_fields_offset *off_ptr)
{
struct member_fields_offset *offset = off_ptr;
if (offset == NULL) {
__u32 k0 = 0;
offset = members_offset__lookup(&k0);
}
void *file = fd_to_file(fd, offset);
if (file == NULL)
return false;

if (disable_vfile_collect &&
check_virtual_file(file, offset) != FILE_TYPE_REGULAR)
return false;

__u32 i_mode = file_to_i_mode(file, offset);
return S_ISREG(i_mode);
}
Expand Down Expand Up @@ -295,7 +347,9 @@ static __inline int trace_io_event_common(void *ctx,

int data_max_sz = tracer_ctx->data_limit_max;

if (!is_regular_file(data_args->fd, offset)) {
if (!is_readable_file(data_args->fd,
!tracer_ctx->virtual_file_collect_enabled,
offset)) {
return -1;
}

Expand Down
5 changes: 4 additions & 1 deletion agent/src/ebpf/kernel/include/socket_trace_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ struct tracer_ctx_s {
__u32 go_tracing_timeout; /**< Go tracing timeout */
__u32 io_event_collect_mode; /**< IO event collection mode */
__u64 io_event_minimal_duration; /**< Minimum duration for IO events */
bool virtual_file_collect_enabled; /**< Enable virtual file collection */
int push_buffer_refcnt; /**< Reference count of the data push buffer */
__u64 last_period_timestamp; /**< Record the timestamp of the last periodic check of the push buffer. */
__u64 period_timestamp; /**< Record the timestamp of the periodic check of the push buffer. */
Expand Down Expand Up @@ -372,7 +373,9 @@ struct member_fields_offset {

__u16 struct_files_struct_fdt_offset; // offsetof(struct files_struct, fdt)
__u16 struct_file_f_pos_offset; // offsetof(struct file, f_pos)
__u32 struct_files_private_data_offset; // offsetof(struct file, private_data)
__u32 struct_file_private_data_offset; // offsetof(struct file, private_data)
__u32 struct_file_f_op_offset; // offsetof(struct file, f_op)
__u32 struct_file_operations_read_iter_offset; // offsetof(struct file_operations, read_iter)
__u32 struct_file_f_inode_offset; // offsetof(struct file, f_inode)
__u32 struct_inode_i_mode_offset; // offsetof(struct inode, i_mode)
__u32 struct_inode_i_sb_offset; // offsetof(struct inode, i_sb)
Expand Down
6 changes: 3 additions & 3 deletions agent/src/ebpf/kernel/include/task_struct_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ static __inline void *infer_and_get_socket_from_fd(int fd_num, struct member_fie
sizeof(private_data),
file +
offset->
struct_files_private_data_offset);
struct_file_private_data_offset);
if (private_data != NULL) {
socket = private_data;
bpf_probe_read_kernel(&__socket,
Expand Down Expand Up @@ -165,7 +165,7 @@ static __inline void *infer_and_get_socket_from_fd(int fd_num, struct member_fie
}

bpf_probe_read_kernel(&private_data, sizeof(private_data),
file + offset->struct_files_private_data_offset);
file + offset->struct_file_private_data_offset);

if (private_data == NULL) {
return NULL;
Expand Down Expand Up @@ -225,7 +225,7 @@ static __inline void *get_socket_from_fd(int fd_num,
file + data_off);
#else
bpf_probe_read_kernel(&private_data, sizeof(private_data),
file + offset->struct_files_private_data_offset);
file + offset->struct_file_private_data_offset);
#endif
if (private_data == NULL) {
return NULL;
Expand Down
1 change: 1 addition & 0 deletions agent/src/ebpf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ extern "C" {
pub fn enable_unix_socket_feature();
pub fn disable_fentry();
pub fn enable_fentry();
pub fn set_virtual_file_collect(enabled: bool) -> c_int;
cfg_if::cfg_if! {
if #[cfg(feature = "extended_observability")] {
pub fn enable_offcpu_profiler() -> c_int;
Expand Down
1 change: 1 addition & 0 deletions agent/src/ebpf/samples/rust/socket-tracer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ fn main() {
// dpdk enable
// set_dpdk_trace_enabled(true);
// disable_kprobe_feature();
// set_virtual_file_collect(true);
if running_socket_tracer(
socket_trace_callback, /* Callback interface rust -> C */
1, /* Number of worker threads, indicating how many user-space threads participate in data processing */
Expand Down
105 changes: 88 additions & 17 deletions agent/src/ebpf/user/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ static enum linux_kernel_type g_k_type;
static bool use_kfunc_bin; // Whether to use fentry/fexit binary eBPF bytecode
static struct list_head events_list; // Use for extra register events
static pthread_t proc_events_pthread; // Process exec/exit thread
static bool kprobe_feature_disable; // Whether to disable the kprobe feature.
static bool unix_socket_feature_enable; // Whether to enable the kprobe feature.
static bool kprobe_feature_disable; // Whether to disable the kprobe feature?
static bool unix_socket_feature_enable; // Whether to enable the kprobe feature?
static bool virtual_file_collect_enable; // Whether to enable virtual file collect?
/*
* Control whether to disable the tracing feature.
* 'true' disables the tracing feature, and 'false' enables it.
Expand Down Expand Up @@ -1711,37 +1712,45 @@ static int update_offset_map_default(struct bpf_tracer *t,
switch (kern_type) {
case K_TYPE_VER_3_10:
offset.struct_files_struct_fdt_offset = 0x8;
offset.struct_files_private_data_offset = 0xa8;
offset.struct_file_private_data_offset = 0xa8;
offset.struct_file_f_pos_offset = 0x68;
offset.struct_ns_common_inum_offset = 0x4;
break;
case K_TYPE_KYLIN:
offset.struct_files_struct_fdt_offset = 0x20;
offset.struct_files_private_data_offset = 0xc0;
offset.struct_file_private_data_offset = 0xc0;
offset.struct_file_f_pos_offset = 0x60;
offset.struct_ns_common_inum_offset = 0x10;
break;
default:
offset.struct_files_struct_fdt_offset = 0x20;
offset.struct_files_private_data_offset = 0xc8;
offset.struct_file_private_data_offset = 0xc8;
offset.struct_file_f_pos_offset = 0x68;
offset.struct_ns_common_inum_offset = 0x10;
};

/*
* In Tencent Linux (4.14.105-1-tlinux3-0023.1), there is a difference in
* `struct_files_private_data_offset`. If the offset value of the generic
* `struct_file_private_data_offset`. If the offset value of the generic
* eBPF program is used, it will result in the kernel being unable to adapt.
* A separate correction is made here.
*/
if (strstr(linux_release, "tlinux3"))
offset.struct_files_private_data_offset = 0xc0;
offset.struct_file_private_data_offset = 0xc0;

// For 4.19.90-2211.5.0.0178.22.uel20.x86_64
if (strstr(linux_release, "uel20"))
offset.struct_files_private_data_offset = 0xc0;
offset.struct_file_private_data_offset = 0xc0;

offset.struct_file_f_inode_offset = 0x20;
/*
* The corresponding offset is used to access `file->f_op->read_iter`, which
* is then used to determine whether the file belongs to a standard VFS
* filesystem or is a virtual file.
*/
offset.struct_file_f_op_offset = 0x28;
offset.struct_file_operations_read_iter_offset = 0x20;

offset.struct_file_f_inode_offset = 0x20;
offset.struct_inode_i_mode_offset = 0x0;
offset.struct_inode_i_sb_offset = 0x28;
offset.struct_super_block_s_dev_offset = 0x10;
Expand Down Expand Up @@ -1817,8 +1826,12 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t)

int struct_files_struct_fdt_offset =
kernel_struct_field_offset(obj, "files_struct", "fdt");
int struct_files_private_data_offset =
int struct_file_private_data_offset =
kernel_struct_field_offset(obj, "file", "private_data");
int struct_file_f_op_offset =
kernel_struct_field_offset(obj, "file", "f_op");
int struct_file_operations_read_iter_offset =
kernel_struct_field_offset(obj, "file_operations", "read_iter");
int struct_file_f_inode_offset =
kernel_struct_field_offset(obj, "file", "f_inode");
int struct_file_f_pos_offset =
Expand Down Expand Up @@ -1885,7 +1898,9 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t)
kernel_struct_field_offset(obj, "mount", "mnt_id");
if (copied_seq_offs < 0 || write_seq_offs < 0 || files_offs < 0 ||
sk_flags_offs < 0 || struct_files_struct_fdt_offset < 0 ||
struct_files_private_data_offset < 0 ||
struct_file_private_data_offset < 0 ||
struct_file_f_op_offset < 0 ||
struct_file_operations_read_iter_offset < 0 ||
struct_file_f_inode_offset < 0 || struct_inode_i_mode_offset < 0 ||
struct_inode_i_sb_offset < 0 ||
struct_super_block_s_dev_offset < 0 || struct_file_dentry_offset < 0 ||
Expand All @@ -1910,8 +1925,12 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t)
ebpf_info(" sk_flags_offs: 0x%x\n", sk_flags_offs);
ebpf_info(" struct_files_struct_fdt_offset: 0x%x\n",
struct_files_struct_fdt_offset);
ebpf_info(" struct_files_private_data_offset: 0x%x\n",
struct_files_private_data_offset);
ebpf_info(" struct_file_private_data_offset: 0x%x\n",
struct_file_private_data_offset);
ebpf_info(" struct_file_f_op_offset: 0x%x\n",
struct_file_f_op_offset);
ebpf_info(" struct_file_operations_read_iter_offset: 0x%x\n",
struct_file_operations_read_iter_offset);
ebpf_info(" struct_file_f_inode_offset: 0x%x\n",
struct_file_f_inode_offset);
ebpf_info(" struct_file_f_pos_offset: 0x%x\n",
Expand Down Expand Up @@ -1978,8 +1997,11 @@ static int update_offset_map_from_btf_vmlinux(struct bpf_tracer *t)
offset.tcp_sock__copied_seq_offset = copied_seq_offs;
offset.tcp_sock__write_seq_offset = write_seq_offs;
offset.struct_files_struct_fdt_offset = struct_files_struct_fdt_offset;
offset.struct_files_private_data_offset =
struct_files_private_data_offset;
offset.struct_file_private_data_offset =
struct_file_private_data_offset;
offset.struct_file_f_op_offset = struct_file_f_op_offset;
offset.struct_file_operations_read_iter_offset =
struct_file_operations_read_iter_offset;
offset.struct_file_f_inode_offset = struct_file_f_inode_offset;
offset.struct_file_f_pos_offset = struct_file_f_pos_offset;
offset.struct_inode_i_mode_offset = struct_inode_i_mode_offset;
Expand Down Expand Up @@ -2040,8 +2062,12 @@ static void display_kern_offsets(bpf_offset_param_t * offset)
offset->struct_files_struct_fdt_offset);
ebpf_info("\tstruct_file_f_pos_offset: 0x%x\n",
offset->struct_file_f_pos_offset);
ebpf_info("\tstruct_files_private_data_offset: 0x%x\n",
offset->struct_files_private_data_offset);
ebpf_info("\tstruct_file_private_data_offset: 0x%x\n",
offset->struct_file_private_data_offset);
ebpf_info("\tstruct_file_f_op_offset: 0x%x\n",
offset->struct_file_f_op_offset);
ebpf_info("\tstruct_file_operations_read_iter_offset: 0x%x\n",
offset->struct_file_operations_read_iter_offset);
ebpf_info("\tstruct_file_f_inode_offset: 0x%x\n",
offset->struct_file_f_inode_offset);
ebpf_info("\tstruct_inode_i_mode_offset: 0x%x\n",
Expand Down Expand Up @@ -2354,6 +2380,7 @@ int set_io_event_collect_mode(uint32_t mode)
return ETR_UPDATE_MAP_FAILD;
}

ebpf_info("Set io_event_collect_mode %d\n", io_event_collect_mode);
return 0;
}

Expand Down Expand Up @@ -2387,6 +2414,42 @@ int set_io_event_minimal_duration(uint64_t duration)
return ETR_UPDATE_MAP_FAILD;
}

ebpf_info("Set io_event_minimal_duration %llu ns\n", io_event_minimal_duration);
return 0;
}

int set_virtual_file_collect(bool enabled)
{
virtual_file_collect_enable = enabled;

struct bpf_tracer *tracer = find_bpf_tracer(SK_TRACER_NAME);
if (tracer == NULL) {
return 0;
}

int cpu;
int nr_cpus = get_num_possible_cpus();
struct tracer_ctx_s values[nr_cpus];
memset(values, 0, sizeof(values));

if (!bpf_table_get_value(tracer, MAP_TRACER_CTX_NAME, 0, values)) {
ebpf_warning("Get map '%s' failed.\n", MAP_TRACER_CTX_NAME);
return ETR_NOTEXIST;
}

for (cpu = 0; cpu < nr_cpus; cpu++) {
values[cpu].virtual_file_collect_enabled =
virtual_file_collect_enable;
}

if (!bpf_table_set_value
(tracer, MAP_TRACER_CTX_NAME, 0, (void *)&values)) {
ebpf_warning("Set '%s' failed\n", MAP_TRACER_CTX_NAME);
return ETR_UPDATE_MAP_FAILD;
}

ebpf_info("IO event virtual_file_collect_enable set to %s\n",
virtual_file_collect_enable ? "true" : "false");
return 0;
}

Expand Down Expand Up @@ -2921,6 +2984,7 @@ int running_socket_tracer(tracer_callback_t handle,
t_conf[cpu].io_event_collect_mode = io_event_collect_mode;
t_conf[cpu].io_event_minimal_duration =
io_event_minimal_duration;
t_conf[cpu].virtual_file_collect_enabled = virtual_file_collect_enable;
t_conf[cpu].disable_tracing = g_disable_syscall_tracing;
if (!g_disable_syscall_tracing)
t_conf[cpu].go_tracing_timeout = go_tracing_timeout;
Expand All @@ -2930,6 +2994,13 @@ int running_socket_tracer(tracer_callback_t handle,
(tracer, MAP_TRACER_CTX_NAME, 0, (void *)&t_conf))
return -EINVAL;

ebpf_info("Config socket_data_limit_max: %d\n", socket_data_limit_max);
ebpf_info("Config io_event_collect_mode: %d\n", io_event_collect_mode);
ebpf_info("Config io_event_minimal_duration: %llu ns\n", io_event_minimal_duration);
ebpf_info("Config virtual_file_collect_enable: %d\n", virtual_file_collect_enable);
ebpf_info("Config g_disable_syscall_tracing: %d\n", g_disable_syscall_tracing);
ebpf_info("Config go_tracing_timeout: %d\n", go_tracing_timeout);

tracer->data_limit_max = socket_data_limit_max;

// Insert prog of output data into map for using BPF Tail Calls.
Expand Down
Loading
Loading