diff mbox series

[RFC,15/16] selftests/crib: Add test for getting all socket information of the process

Message ID AM6PR03MB5848307206A0D9B4D78CA12799A42@AM6PR03MB5848.eurprd03.prod.outlook.com (mailing list archive)
State Superseded
Headers show
Series bpf: Checkpoint/Restore In eBPF (CRIB) | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-7 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-8 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-6 pending Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 pending Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-11 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-12 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-13 fail Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / veristat
bpf/vmtest-bpf-next-VM_Test-18 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-19 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-20 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / veristat
bpf/vmtest-bpf-next-VM_Test-14 fail Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-15 fail Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / veristat
bpf/vmtest-bpf-next-VM_Test-21 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-22 fail Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-23 fail Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-31 fail Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-32 fail Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-38 fail Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 fail Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-40 fail Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
netdev/series_format fail Series longer than 15 patches
netdev/tree_selection success Guessed tree name to be net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 18 this patch: 18
netdev/build_tools success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 2 maintainers not CCed: linux-kselftest@vger.kernel.org shuah@kernel.org
netdev/build_clang success Errors and warnings before: 821 this patch: 821
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 826 this patch: 826
netdev/checkpatch warning CHECK: Alignment should match open parenthesis CHECK: Blank lines aren't necessary before a close brace '}' WARNING: Improper SPDX comment style for 'tools/testing/selftests/crib/test_dump_all_socket.h', please use '/*' instead WARNING: Missing a blank line after declarations WARNING: Missing or malformed SPDX-License-Identifier tag in line 1 WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: braces {} are not necessary for single statement blocks WARNING: externs should be avoided in .c files WARNING: line length of 100 exceeds 80 columns WARNING: line length of 101 exceeds 80 columns WARNING: line length of 103 exceeds 80 columns WARNING: line length of 104 exceeds 80 columns WARNING: line length of 105 exceeds 80 columns WARNING: line length of 106 exceeds 80 columns WARNING: line length of 107 exceeds 80 columns WARNING: line length of 108 exceeds 80 columns WARNING: line length of 115 exceeds 80 columns WARNING: line length of 81 exceeds 80 columns WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns WARNING: line length of 88 exceeds 80 columns WARNING: line length of 89 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: line length of 91 exceeds 80 columns WARNING: line length of 92 exceeds 80 columns WARNING: line length of 94 exceeds 80 columns WARNING: line length of 95 exceeds 80 columns WARNING: line length of 96 exceeds 80 columns WARNING: line length of 97 exceeds 80 columns WARNING: line length of 98 exceeds 80 columns WARNING: line length of 99 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Juntong Deng July 10, 2024, 6:40 p.m. UTC
In this test, all socket information of the process is obtained through
CRIB, including socket type, socket protocol, destination/source address,
TCP underlying protocol information, etc.

The socket information obtained through CRIB will be compared with known
information and with information obtained through getsockopt to verify
the correctness of the information.

Signed-off-by: Juntong Deng <juntong.deng@outlook.com>
---
 .../selftests/crib/test_dump_all_socket.bpf.c | 252 ++++++++++++
 .../selftests/crib/test_dump_all_socket.c     | 375 ++++++++++++++++++
 .../selftests/crib/test_dump_all_socket.h     |  69 ++++
 3 files changed, 696 insertions(+)
 create mode 100644 tools/testing/selftests/crib/test_dump_all_socket.bpf.c
 create mode 100644 tools/testing/selftests/crib/test_dump_all_socket.c
 create mode 100644 tools/testing/selftests/crib/test_dump_all_socket.h
diff mbox series

Patch

diff --git a/tools/testing/selftests/crib/test_dump_all_socket.bpf.c b/tools/testing/selftests/crib/test_dump_all_socket.bpf.c
new file mode 100644
index 000000000000..c124a0491ca3
--- /dev/null
+++ b/tools/testing/selftests/crib/test_dump_all_socket.bpf.c
@@ -0,0 +1,252 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ *	Juntong Deng <juntong.deng@outlook.com>
+ */
+
+#include "vmlinux.h"
+
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+
+#include "test_dump_all_socket.h"
+
+char LICENSE[] SEC("license") = "Dual BSD/GPL";
+
+struct {
+	__uint(type, BPF_MAP_TYPE_RINGBUF);
+	__uint(max_entries, 100000);
+} rb SEC(".maps");
+
+extern struct task_struct *bpf_task_from_vpid(pid_t vpid) __ksym;
+extern void bpf_task_release(struct task_struct *p) __ksym;
+
+extern struct sock *bpf_sock_from_task_fd(struct task_struct *task, int fd) __ksym;
+extern struct sock *bpf_sock_from_socket(struct socket *sock) __ksym;
+extern void bpf_sock_release(struct sock *sk) __ksym;
+
+extern struct socket *bpf_socket_from_file(struct file *file) __ksym;
+extern struct sock_common *bpf_sock_common_from_sock(struct sock *sk) __ksym;
+extern struct tcp_sock *bpf_tcp_sock_from_sock(struct sock *sk) __ksym;
+extern struct udp_sock *bpf_udp_sock_from_sock(struct sock *sk) __ksym;
+
+extern int bpf_inet_src_addr_from_socket(struct socket *sock, struct sockaddr_in *addr) __ksym;
+extern int bpf_inet_dst_addr_from_socket(struct socket *sock, struct sockaddr_in *addr) __ksym;
+extern int bpf_inet6_src_addr_from_socket(struct socket *sock, struct sockaddr_in6 *addr) __ksym;
+extern int bpf_inet6_dst_addr_from_socket(struct socket *sock, struct sockaddr_in6 *addr) __ksym;
+
+extern int bpf_iter_task_file_new(struct bpf_iter_task_file *it, struct task_struct *task) __ksym;
+extern struct file *bpf_iter_task_file_next(struct bpf_iter_task_file *it) __ksym;
+extern int bpf_iter_task_file_get_fd(struct bpf_iter_task_file *it) __ksym;
+extern void bpf_iter_task_file_destroy(struct bpf_iter_task_file *it) __ksym;
+
+SEC("crib")
+int dump_udp_socket(struct prog_args *arg)
+{
+	int err = 0;
+
+	struct task_struct *task = bpf_task_from_vpid(arg->pid);
+	if (!task) {
+		err = -1;
+		goto error;
+	}
+
+	struct sock *sk = bpf_sock_from_task_fd(task, arg->sockfd);
+	if (!sk) {
+		err = -1;
+		goto error_sock;
+	}
+
+	struct event_udp *e_udp = bpf_ringbuf_reserve(&rb, sizeof(struct event_udp), 0);
+	if (!e_udp) {
+		err = -2;
+		goto error_buf;
+	}
+
+	struct udp_sock *up = bpf_udp_sock_from_sock(sk);
+
+	e_udp->hdr.type = EVENT_TYPE_UDP;
+	e_udp->hdr.sockfd = arg->sockfd;
+	e_udp->udp_flags = BPF_CORE_READ(up, udp_flags);
+	e_udp->len = BPF_CORE_READ(up, len);
+	e_udp->pending = BPF_CORE_READ(up, pending);
+
+	bpf_ringbuf_submit(e_udp, 0);
+
+error_buf:
+	bpf_sock_release(sk);
+error_sock:
+	bpf_task_release(task);
+error:
+	return err;
+}
+
+SEC("crib")
+int dump_tcp_socket(struct prog_args *arg)
+{
+	int err = 0;
+
+	struct task_struct *task = bpf_task_from_vpid(arg->pid);
+	if (!task) {
+		err = -1;
+		goto error;
+	}
+
+	struct sock *sk = bpf_sock_from_task_fd(task, arg->sockfd);
+	if (!sk) {
+		err = -1;
+		goto error_sock;
+	}
+
+	struct event_tcp *e_tcp = bpf_ringbuf_reserve(&rb, sizeof(struct event_tcp), 0);
+	if (!e_tcp) {
+		err = -2;
+		goto error_buf;
+	}
+
+	struct tcp_sock *tp = bpf_tcp_sock_from_sock(sk);
+
+	e_tcp->hdr.type = EVENT_TYPE_TCP;
+	e_tcp->hdr.sockfd = arg->sockfd;
+	e_tcp->snd_wl1 = BPF_CORE_READ(tp, snd_wl1);
+	e_tcp->snd_wnd = BPF_CORE_READ(tp, snd_wnd);
+	e_tcp->max_window = BPF_CORE_READ(tp, max_window);
+	e_tcp->rcv_wnd = BPF_CORE_READ(tp, rcv_wnd);
+	e_tcp->rcv_wup = BPF_CORE_READ(tp, rcv_wup);
+	e_tcp->write_seq = BPF_CORE_READ(tp, write_seq);
+	e_tcp->rcv_nxt = BPF_CORE_READ(tp, rcv_nxt);
+
+	bpf_ringbuf_submit(e_tcp, 0);
+
+error_buf:
+	bpf_sock_release(sk);
+error_sock:
+	bpf_task_release(task);
+error:
+	return err;
+}
+
+static int dump_inet_addr(struct socket *sock, int sockfd)
+{
+	struct event_inet_addr *e_src_addr = bpf_ringbuf_reserve(&rb, sizeof(struct event_inet_addr), 0);
+	if (!e_src_addr) {
+		return -2;
+	}
+
+	struct event_inet_addr *e_dst_addr = bpf_ringbuf_reserve(&rb, sizeof(struct event_inet_addr), 0);
+	if (!e_dst_addr) {
+		bpf_ringbuf_discard(e_src_addr, 0);
+		return -2;
+	}
+
+	e_src_addr->hdr.type = EVENT_TYPE_INET_ADDR;
+	e_src_addr->hdr.subtype = EVENT_SUBTYPE_ADDR_SRC;
+	e_src_addr->hdr.sockfd = sockfd;
+
+	e_dst_addr->hdr.type = EVENT_TYPE_INET_ADDR;
+	e_dst_addr->hdr.subtype = EVENT_SUBTYPE_ADDR_DST;
+	e_dst_addr->hdr.sockfd = sockfd;
+
+	bpf_inet_src_addr_from_socket(sock, &e_src_addr->addr);
+	bpf_inet_dst_addr_from_socket(sock, &e_dst_addr->addr);
+
+	bpf_ringbuf_submit(e_src_addr, 0);
+	bpf_ringbuf_submit(e_dst_addr, 0);
+
+	return 0;
+}
+
+static int dump_inet6_addr(struct socket *sock, int sockfd)
+{
+	struct event_inet6_addr *e_src_addr = bpf_ringbuf_reserve(&rb, sizeof(struct event_inet6_addr), 0);
+	if (!e_src_addr) {
+		return -2;
+	}
+
+	struct event_inet6_addr *e_dst_addr = bpf_ringbuf_reserve(&rb, sizeof(struct event_inet6_addr), 0);
+	if (!e_dst_addr) {
+		bpf_ringbuf_discard(e_src_addr, 0);
+		return -2;
+	}
+
+	e_src_addr->hdr.type = EVENT_TYPE_INET6_ADDR;
+	e_src_addr->hdr.subtype = EVENT_SUBTYPE_ADDR_SRC;
+	e_src_addr->hdr.sockfd = sockfd;
+
+	e_dst_addr->hdr.type = EVENT_TYPE_INET6_ADDR;
+	e_dst_addr->hdr.subtype = EVENT_SUBTYPE_ADDR_DST;
+	e_dst_addr->hdr.sockfd = sockfd;
+
+	bpf_inet6_src_addr_from_socket(sock, &e_src_addr->addr);
+	bpf_inet6_dst_addr_from_socket(sock, &e_dst_addr->addr);
+
+	bpf_ringbuf_submit(e_src_addr, 0);
+	bpf_ringbuf_submit(e_dst_addr, 0);
+
+	return 0;
+}
+
+SEC("crib")
+int dump_all_socket(struct prog_args *arg)
+{
+	int err = 0;
+
+	struct task_struct *task = bpf_task_from_vpid(arg->pid);
+	if (!task) {
+		err = -1;
+		goto error;
+	}
+
+	struct bpf_iter_task_file file_it;
+	struct file *cur_file;
+
+	bpf_iter_task_file_new(&file_it, task);
+	while ((cur_file = bpf_iter_task_file_next(&file_it))) {
+		struct socket *sock = bpf_socket_from_file(cur_file);
+		if (!sock) {
+			continue;
+		}
+
+		struct event_socket *e_socket = bpf_ringbuf_reserve(&rb, sizeof(struct event_socket), 0);
+		if (!e_socket) {
+			err = -2;
+			goto error_buf;
+		}
+
+		struct sock *sk = bpf_sock_from_socket(sock);
+		struct sock_common *sk_cm = bpf_sock_common_from_sock(sk);
+
+		int sock_family = BPF_CORE_READ(sk_cm, skc_family);
+		int sock_state = BPF_CORE_READ(sk_cm, skc_state);
+		int sock_type = BPF_CORE_READ(sk, sk_type);
+		int sock_protocol = BPF_CORE_READ(sk, sk_protocol);
+		int fd = bpf_iter_task_file_get_fd(&file_it);
+
+		bpf_sock_release(sk);
+
+		e_socket->hdr.type = EVENT_TYPE_SOCKET;
+		e_socket->hdr.sockfd = fd;
+		e_socket->family = sock_family;
+		e_socket->state = sock_state;
+		e_socket->type = sock_type;
+		e_socket->protocol = sock_protocol;
+
+		bpf_ringbuf_submit(e_socket, 0);
+
+		if (sock_family == PF_INET)
+			err = dump_inet_addr(sock, fd);
+		else if (sock_family == PF_INET6)
+			err = dump_inet6_addr(sock, fd);
+
+		if (err) {
+			goto error_buf;
+		}
+	}
+
+error_buf:
+	bpf_iter_task_file_destroy(&file_it);
+	bpf_task_release(task);
+error:
+	return err;
+}
diff --git a/tools/testing/selftests/crib/test_dump_all_socket.c b/tools/testing/selftests/crib/test_dump_all_socket.c
new file mode 100644
index 000000000000..15add7fbf4f4
--- /dev/null
+++ b/tools/testing/selftests/crib/test_dump_all_socket.c
@@ -0,0 +1,375 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ *	Juntong Deng <juntong.deng@outlook.com>
+ */
+
+#include <argp.h>
+#include <stdio.h>
+#include <bpf/libbpf.h>
+#include <bpf/bpf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <linux/if_packet.h>
+#include <net/ethernet.h>
+#include <linux/netlink.h>
+#include <asm/types.h>
+#include <asm-generic/socket.h>
+#include <linux/tcp.h>
+
+#include "../kselftest_harness.h"
+
+#include "test_dump_all_socket.h"
+#include "test_dump_all_socket.bpf.skel.h"
+
+struct tcp_dump_info {
+	unsigned int snd_wl1;
+	unsigned int snd_wnd;
+	unsigned int max_window;
+	unsigned int rcv_wnd;
+	unsigned int rcv_wup;
+	unsigned int write_seq;
+	unsigned int rcv_nxt;
+};
+
+struct udp_dump_info {
+	int udp_flags;
+	int len;
+	int pending;
+};
+
+struct socket_dump_info {
+	int sockfd;
+	int family;
+	int type;
+	int protocol;
+	union {
+		struct sockaddr_in src_addr4;
+		struct sockaddr_in6 src_addr6;
+	};
+	union {
+		struct sockaddr_in dst_addr4;
+		struct sockaddr_in6 dst_addr6;
+	};
+	union {
+		struct tcp_dump_info tcp;
+		struct udp_dump_info udp;
+	};
+};
+
+static int dump_all_socket_fd;
+static int dump_tcp_socket_fd;
+static int dump_udp_socket_fd;
+
+static int tcp_client_fd;
+static int tcp_server_fd;
+static int tcp_accept_fd;
+static int udp_client_fd;
+
+static int socket_count;
+
+static struct socket_dump_info *find_dump_info_by_sockfd(struct socket_dump_info *all_info, int sockfd)
+{
+	struct socket_dump_info *info;
+	for (int i = 0; i < 4; i++) {
+		info = &all_info[i];
+		if (info->sockfd == sockfd)
+			return info;
+	}
+	return NULL;
+}
+
+static int handle_tcp_event(struct socket_dump_info *all_info, struct event_tcp *e_tcp)
+{
+	struct socket_dump_info *info = find_dump_info_by_sockfd(all_info, e_tcp->hdr.sockfd);
+	info->tcp.snd_wl1 = e_tcp->snd_wl1;
+	info->tcp.snd_wnd = e_tcp->snd_wnd;
+	info->tcp.max_window = e_tcp->max_window;
+	info->tcp.rcv_wnd = e_tcp->rcv_wnd;
+	info->tcp.rcv_wup = e_tcp->rcv_wup;
+	info->tcp.write_seq = e_tcp->write_seq;
+	info->tcp.rcv_nxt = e_tcp->rcv_nxt;
+	return 0;
+}
+
+static int handle_udp_event(struct socket_dump_info *all_info, struct event_udp *e_udp)
+{
+	struct socket_dump_info *info = find_dump_info_by_sockfd(all_info, e_udp->hdr.sockfd);
+	info->udp.udp_flags = e_udp->udp_flags;
+	info->udp.len = e_udp->len;
+	info->udp.pending = e_udp->pending;
+	return 0;
+}
+
+static int handle_inet_addr_event(struct socket_dump_info *all_info, struct event_inet_addr *e_inet_addr)
+{
+	struct socket_dump_info *info = &all_info[socket_count - 1];
+	if (e_inet_addr->hdr.subtype == EVENT_SUBTYPE_ADDR_SRC)
+		memcpy(&info->src_addr4, &e_inet_addr->addr, sizeof(struct sockaddr_in));
+	else if (e_inet_addr->hdr.subtype == EVENT_SUBTYPE_ADDR_DST)
+		memcpy(&info->dst_addr4, &e_inet_addr->addr, sizeof(struct sockaddr_in));
+	return 0;
+}
+
+static int handle_inet6_addr_event(struct socket_dump_info *all_info, struct event_inet6_addr *e_inet6_addr)
+{
+	struct socket_dump_info *info = &all_info[socket_count - 1];
+	if (e_inet6_addr->hdr.subtype == EVENT_SUBTYPE_ADDR_SRC)
+		memcpy(&info->src_addr6, &e_inet6_addr->addr, sizeof(struct sockaddr_in6));
+	else if (e_inet6_addr->hdr.subtype == EVENT_SUBTYPE_ADDR_DST)
+		memcpy(&info->dst_addr6, &e_inet6_addr->addr, sizeof(struct sockaddr_in6));
+	return 0;
+}
+
+static int handle_socket_event(struct socket_dump_info *all_info, struct event_socket *e_socket)
+{
+	struct prog_args arg = {
+		.pid = getpid(),
+		.sockfd = e_socket->hdr.sockfd
+	};
+
+	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, tattrs,
+		.ctx_in = &arg,
+		.ctx_size_in = sizeof(arg),
+	);
+
+	struct socket_dump_info *info = &all_info[socket_count];
+	info->sockfd = e_socket->hdr.sockfd;
+	info->family = e_socket->family;
+	info->type = e_socket->type;
+	info->protocol = e_socket->protocol;
+
+	int err = 0;
+	if (e_socket->protocol == IPPROTO_TCP)
+		err = bpf_prog_test_run_opts(dump_tcp_socket_fd, &tattrs);
+	else if (e_socket->protocol == IPPROTO_UDP)
+		err = bpf_prog_test_run_opts(dump_udp_socket_fd, &tattrs);
+
+	socket_count++;
+
+	return err;
+}
+
+static int handle_event(void *ctx, void *data, size_t data_sz)
+{
+	struct socket_dump_info *all_info = (struct socket_dump_info *)ctx;
+	const struct event_hdr *e_hdr = data;
+	int err = 0;
+
+	switch (e_hdr->type) {
+	case EVENT_TYPE_TCP:
+		handle_tcp_event(all_info, (struct event_tcp *)data);
+		break;
+	case EVENT_TYPE_UDP:
+		handle_udp_event(all_info, (struct event_udp *)data);
+		break;
+	case EVENT_TYPE_SOCKET:
+		handle_socket_event(all_info, (struct event_socket *)data);
+		break;
+	case EVENT_TYPE_INET_ADDR:
+		handle_inet_addr_event(all_info, (struct event_inet_addr *)data);
+		break;
+	case EVENT_TYPE_INET6_ADDR:
+		handle_inet6_addr_event(all_info, (struct event_inet6_addr *)data);
+		break;
+	default:
+		err = -1;
+		printf("Unknown event type!\n");
+		break;
+	}
+	return err;
+}
+
+static int check_tcp_dump_info_correctness(struct socket_dump_info *info)
+{
+	const int enable = 1;
+	if (info->family != AF_INET || info->type != SOCK_STREAM ||
+		info->protocol != IPPROTO_TCP)
+		return -1;
+
+	if (info->dst_addr4.sin_family != AF_INET || info->src_addr4.sin_family != AF_INET)
+		return -1;
+
+	if (info->sockfd == tcp_client_fd && (info->dst_addr4.sin_addr.s_addr != htonl(INADDR_LOOPBACK) ||
+		info->dst_addr4.sin_port != htons(5555)))
+		return -1;
+
+	if (info->sockfd == tcp_server_fd && (info->src_addr4.sin_addr.s_addr != htonl(INADDR_ANY) ||
+		info->src_addr4.sin_port != htons(5555)))
+		return -1;
+
+	if (info->sockfd == tcp_accept_fd && (info->src_addr4.sin_addr.s_addr != htonl(INADDR_LOOPBACK) ||
+		info->dst_addr4.sin_addr.s_addr != htonl(INADDR_LOOPBACK) ||
+		info->src_addr4.sin_port != htons(5555)))
+		return -1;
+
+	if (info->sockfd != tcp_server_fd) {
+		if (setsockopt(info->sockfd, IPPROTO_TCP, TCP_REPAIR, &enable, sizeof(enable)))
+			return -1;
+
+		struct tcp_repair_window opt;
+		socklen_t optlen = sizeof(opt);
+		if (getsockopt(info->sockfd, IPPROTO_TCP, TCP_REPAIR_WINDOW, &opt, &optlen))
+			return -1;
+
+		if (opt.snd_wl1 != info->tcp.snd_wl1 || opt.snd_wnd != info->tcp.snd_wnd ||
+			opt.max_window != info->tcp.max_window || opt.rcv_wnd != info->tcp.rcv_wnd ||
+			opt.rcv_wup != info->tcp.rcv_wup)
+			return -1;
+
+		int queue = TCP_SEND_QUEUE;
+		if (setsockopt(info->sockfd, IPPROTO_TCP, TCP_REPAIR_QUEUE, &queue, sizeof(queue)))
+			return -1;
+
+		unsigned int write_seq;
+		optlen = sizeof(write_seq);
+		if (getsockopt(info->sockfd, IPPROTO_TCP, TCP_QUEUE_SEQ, &write_seq, &optlen))
+			return -1;
+
+		if (write_seq != info->tcp.write_seq)
+			return -1;
+
+		queue = TCP_RECV_QUEUE;
+		if (setsockopt(info->sockfd, IPPROTO_TCP, TCP_REPAIR_QUEUE, &queue, sizeof(queue)))
+			return -1;
+
+		unsigned int rcv_nxt;
+		if (getsockopt(info->sockfd, IPPROTO_TCP, TCP_QUEUE_SEQ, &rcv_nxt, &optlen))
+			return -1;
+
+		if (rcv_nxt != info->tcp.rcv_nxt)
+			return -1;
+	}
+	return 0;
+}
+
+static int check_udp_dump_info_correctness(struct socket_dump_info *info)
+{
+	if (info->family != AF_INET6 || info->type != SOCK_DGRAM ||
+		info->protocol != IPPROTO_UDP)
+		return -1;
+
+	if (info->dst_addr6.sin6_family != AF_INET6 || info->dst_addr6.sin6_port != htons(7777) ||
+		memcmp(&info->dst_addr6.sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) != 0)
+		return -1;
+
+	return 0;
+}
+
+static int check_dump_info_correctness(struct socket_dump_info *all_info)
+{
+	struct socket_dump_info *info;
+	for (int i = 0; i < 4; i++) {
+		info = &all_info[i];
+
+		if (info->sockfd <= 0)
+			return -1;
+
+		if (info->sockfd == udp_client_fd) {
+			if (check_udp_dump_info_correctness(info) != 0)
+				return -1;
+		} else {
+			if (check_tcp_dump_info_correctness(info) != 0)
+				return -1;
+		}
+
+	}
+	return 0;
+}
+
+TEST(dump_all_socket)
+{
+	struct prog_args args = {
+		.pid = getpid(),
+	};
+	ASSERT_GT(args.pid, 0);
+
+	DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
+		.ctx_in = &args,
+		.ctx_size_in = sizeof(args),
+	);
+
+	tcp_client_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	ASSERT_GT(tcp_client_fd, 0);
+
+	tcp_server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	ASSERT_GT(tcp_server_fd, 0);
+
+	udp_client_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+	ASSERT_GT(udp_client_fd, 0);
+
+	const int enable = 1;
+	ASSERT_EQ(setsockopt(tcp_server_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)), 0);
+
+	struct sockaddr_in tcp_src_addr, tcp_dst_addr;
+	struct sockaddr_in6 udp_dst_addr;
+	memset(&tcp_src_addr, 0, sizeof(struct sockaddr_in));
+	memset(&tcp_dst_addr, 0, sizeof(struct sockaddr_in));
+	memset(&udp_dst_addr, 0, sizeof(struct sockaddr_in6));
+
+	tcp_src_addr.sin_family = AF_INET;
+	tcp_src_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+	tcp_src_addr.sin_port = htons(5555);
+
+	tcp_dst_addr.sin_family = AF_INET;
+	tcp_dst_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	tcp_dst_addr.sin_port = htons(5555);
+
+	udp_dst_addr.sin6_family = AF_INET6;
+	udp_dst_addr.sin6_addr = in6addr_loopback;
+	udp_dst_addr.sin6_port = htons(7777);
+
+	ASSERT_EQ(bind(tcp_server_fd, (struct sockaddr *)&tcp_src_addr, sizeof(struct sockaddr_in)), 0);
+	ASSERT_EQ(listen(tcp_server_fd, 100), 0);
+
+	ASSERT_EQ(connect(tcp_client_fd, (struct sockaddr *)&tcp_dst_addr, sizeof(struct sockaddr_in)), 0);
+
+	tcp_accept_fd = accept(tcp_server_fd, NULL, NULL);
+	ASSERT_GT(tcp_accept_fd, 0);
+
+	char buf[20];
+	memset(buf, 'a', 20);
+	ASSERT_EQ(send(tcp_client_fd, buf, 20, 0), 20);
+
+	ASSERT_EQ(connect(udp_client_fd, (struct sockaddr *)&udp_dst_addr, sizeof(struct sockaddr_in6)), 0);
+
+	struct test_dump_all_socket_bpf *skel = test_dump_all_socket_bpf__open_and_load();
+	ASSERT_NE(skel, NULL);
+
+	dump_all_socket_fd = bpf_program__fd(skel->progs.dump_all_socket);
+	ASSERT_GT(dump_all_socket_fd, 0);
+
+	dump_tcp_socket_fd = bpf_program__fd(skel->progs.dump_tcp_socket);
+	ASSERT_GT(dump_tcp_socket_fd, 0);
+
+	dump_udp_socket_fd = bpf_program__fd(skel->progs.dump_udp_socket);
+	ASSERT_GT(dump_udp_socket_fd, 0);
+
+	struct socket_dump_info *all_info = (struct socket_dump_info *)malloc(sizeof(struct socket_dump_info) * 4);
+
+	struct ring_buffer *rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, all_info, NULL);
+	ASSERT_NE(rb, NULL);
+
+	ASSERT_EQ(bpf_prog_test_run_opts(dump_all_socket_fd, &opts), 0);
+
+	ASSERT_GT(ring_buffer__poll(rb, 100), 0);
+
+	ASSERT_EQ(check_dump_info_correctness(all_info), 0);
+
+	ASSERT_EQ(close(tcp_client_fd), 0);
+	ASSERT_EQ(close(tcp_accept_fd), 0);
+	ASSERT_EQ(close(tcp_server_fd), 0);
+	ASSERT_EQ(close(udp_client_fd), 0);
+	ring_buffer__free(rb);
+	test_dump_all_socket_bpf__destroy(skel);
+}
+
+TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/crib/test_dump_all_socket.h b/tools/testing/selftests/crib/test_dump_all_socket.h
new file mode 100644
index 000000000000..04453e650469
--- /dev/null
+++ b/tools/testing/selftests/crib/test_dump_all_socket.h
@@ -0,0 +1,69 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ *	Juntong Deng <juntong.deng@outlook.com>
+ */
+
+#ifndef __TEST_DUMP_ALL_SOCKET_H
+#define __TEST_DUMP_ALL_SOCKET_H
+
+#define PF_INET		2
+#define PF_INET6	10
+
+#define EVENT_TYPE_TCP		0
+#define EVENT_TYPE_UDP		1
+#define EVENT_TYPE_SOCKET	2
+#define EVENT_TYPE_INET_ADDR	3
+#define EVENT_TYPE_INET6_ADDR	4
+
+#define EVENT_SUBTYPE_ADDR_SRC	0
+#define EVENT_SUBTYPE_ADDR_DST	1
+
+struct prog_args {
+	int pid;
+	int sockfd;
+};
+
+struct event_hdr {
+	int type;
+	int subtype;
+	int sockfd;
+};
+
+struct event_socket {
+	struct event_hdr hdr;
+	int family;
+	int state;
+	int type;
+	int protocol;
+};
+
+struct event_inet6_addr {
+	struct event_hdr hdr;
+	struct sockaddr_in6 addr;
+};
+
+struct event_inet_addr {
+	struct event_hdr hdr;
+	struct sockaddr_in addr;
+};
+
+struct event_tcp {
+	struct event_hdr hdr;
+	unsigned int snd_wl1;
+	unsigned int snd_wnd;
+	unsigned int max_window;
+	unsigned int rcv_wnd;
+	unsigned int rcv_wup;
+	unsigned int write_seq;
+	unsigned int rcv_nxt;
+};
+
+struct event_udp {
+	struct event_hdr hdr;
+	int udp_flags;
+	int len;
+	int pending;
+};
+
+#endif /* __TEST_DUMP_ALL_SOCKET_H */