Context |
Check |
Description |
bpf/vmtest-bpf-next-PR |
success
|
PR summary
|
bpf/vmtest-bpf-next-VM_Test-3 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-next-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-next-VM_Test-2 |
success
|
Logs for Unittests
|
bpf/vmtest-bpf-next-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-next-VM_Test-4 |
success
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-5 |
success
|
Logs for aarch64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-7 |
pending
|
Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-8 |
pending
|
Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 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-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-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-6 |
success
|
Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-9 |
success
|
Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-13 |
success
|
Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
|
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-16 |
success
|
Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
|
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
|
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
|
netdev/series_format |
fail
|
Series longer than 15 patches
|
netdev/tree_selection |
success
|
Clearly marked for bpf-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 |
success
|
Errors and warnings before: 816 this patch: 816
|
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
|
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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
new file mode 100644
@@ -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 */
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