summaryrefslogtreecommitdiff
path: root/SOURCE
diff options
context:
space:
mode:
authorYang Wei <[email protected]>2022-01-09 23:41:39 +0800
committerYang Wei <[email protected]>2022-01-09 23:41:39 +0800
commit0ddb0cf9d563d9abfd3d13be2888d54d19ac9c54 (patch)
tree4d8c4f5d27cfe1a29275676185b3764e99e52f14 /SOURCE
parenta2108822a3ff0a0768b26a97686f03effb33ca19 (diff)
diagnose-tools:增加tcp-connect功能,用于记录tcp主动、被动打开、关闭等信息
Diffstat (limited to 'SOURCE')
-rw-r--r--SOURCE/diagnose-tools/internal.h1
-rw-r--r--SOURCE/diagnose-tools/main.cc1
-rw-r--r--SOURCE/diagnose-tools/tcp_connect.cc329
-rwxr-xr-xSOURCE/module/Makefile2
-rw-r--r--SOURCE/module/chr_dev.c3
-rw-r--r--SOURCE/module/entry.c8
-rwxr-xr-xSOURCE/module/internal.h2
-rwxr-xr-xSOURCE/module/kernel/throttle_delay.c8
-rwxr-xr-xSOURCE/module/net/net_entry.c7
-rw-r--r--SOURCE/module/net/net_internal.h2
-rw-r--r--SOURCE/module/net/tcp_connect.c365
-rw-r--r--SOURCE/uapi/ali_diagnose.h14
-rw-r--r--SOURCE/uapi/tcp_connect.h53
13 files changed, 788 insertions, 7 deletions
diff --git a/SOURCE/diagnose-tools/internal.h b/SOURCE/diagnose-tools/internal.h
index 924ec39..c786a39 100644
--- a/SOURCE/diagnose-tools/internal.h
+++ b/SOURCE/diagnose-tools/internal.h
@@ -31,6 +31,7 @@ int exit_monitor_main(int argc, char **argv);
int utilization_main(int argc, char **argv);
int perf_main(int argc, char **argv);
int tcp_retrans_main(int argc, char **argv);
+int tcp_connect_main(int argc, char **argv);
int rw_top_main(int argc, char **argv);
int irq_delay_main(int argc, char **argv);
int mutex_monitor_main(int argc, char **argv);
diff --git a/SOURCE/diagnose-tools/main.cc b/SOURCE/diagnose-tools/main.cc
index e6c3486..ffd48bd 100644
--- a/SOURCE/diagnose-tools/main.cc
+++ b/SOURCE/diagnose-tools/main.cc
@@ -228,6 +228,7 @@ static struct diagnose_func all_funcs[] {
{"ping-delay6", ping_delay6_main, 0},
{"uprobe", uprobe_main, 0},
{"memcg-stats", memcg_stats_main, 0},
+ {"tcp-connect", tcp_connect_main, 0},
{"--vmsize", no_vmsize, 1},
{"-V", report_version, 0},
{"-v", report_version, 0},
diff --git a/SOURCE/diagnose-tools/tcp_connect.cc b/SOURCE/diagnose-tools/tcp_connect.cc
new file mode 100644
index 0000000..01892fa
--- /dev/null
+++ b/SOURCE/diagnose-tools/tcp_connect.cc
@@ -0,0 +1,329 @@
+/*
+ * Linux内核诊断工具--用户态tcp-connect功能实现
+ *
+ * Copyright (C) 2022 Alibaba Ltd.
+ *
+ * 作者: Yang Wei <[email protected]>
+ *
+ * License terms: GNU General Public License (GPL) version 3
+ *
+ */
+
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <getopt.h>
+
+#include <sys/time.h>
+#include <string.h>
+#include <stdio.h> /* for printf */
+#include <stdlib.h> /* for exit */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <iostream>
+#include <fstream>
+
+#include "internal.h"
+#include "symbol.h"
+#include "uapi/tcp_connect.h"
+#include "params_parse.h"
+#include "params_parse.h"
+
+using namespace std;
+
+static int tcp_connect_ignore = 0;
+static char sls_file[256];
+static int syslog_enabled;
+
+void usage_tcp_connect(void)
+{
+ printf(" tcp-connect usage:\n");
+ printf(" --help tcp-connect help info\n");
+ printf(" --activate\n");
+ printf(" verbose VERBOSE\n");
+ printf(" --deactivate\n");
+ printf(" --report dump log with text.\n");
+ printf(" --log\n");
+ printf(" sls=/tmp/1.log store in file\n");
+ printf(" syslog=1 store in syslog\n");
+}
+
+static void do_activate(const char *arg)
+{
+ int ret = 0;
+ struct params_parser parse(arg);
+ struct diag_tcp_connect_settings settings;
+ string str;
+
+ memset(&settings, 0, sizeof(struct diag_tcp_connect_settings));
+
+ settings.verbose = parse.int_value("verbose");
+
+ if (run_in_host) {
+ ret = diag_call_ioctl(DIAG_IOCTL_TCP_CONNECT_SET, (long)&settings);
+ } else {
+ ret = -ENOSYS;
+ syscall(DIAG_TCP_CONNECT_SET, &ret, &settings, sizeof(struct diag_tcp_connect_settings));
+ }
+
+ printf("功能设置%s,返回值:%d\n", ret ? "失败" : "成功", ret);
+ printf(" 输出级别:%d\n", settings.verbose);
+
+ if (ret)
+ return;
+
+ ret = diag_activate("tcp-connect");
+ if (ret == 1) {
+ printf("tcp-connect activated\n");
+ } else {
+ printf("tcp-connect is not activated, ret %d\n", ret);
+ }
+}
+
+static void do_deactivate(void)
+{
+ int ret = 0;
+
+ ret = diag_deactivate("tcp-connect");
+ if (ret == 0) {
+ printf("tcp-connect is not activated\n");
+ } else {
+ printf("deactivate tcp-connect fail, ret is %d\n", ret);
+ }
+}
+
+static void print_settings_in_json(struct diag_tcp_connect_settings *settings, int ret)
+{
+ Json::Value root;
+ std::string str_log;
+
+ if (ret == 0) {
+ root["activated"] = Json::Value(settings->activated);
+ root["verbose"] = Json::Value(settings->verbose);
+ } else {
+ root["err"] = Json::Value("found tcp-connect settings failed, please check if diagnose-tools is installed correctly or not.");
+ }
+
+ str_log.append(root.toStyledString());
+ printf("%s", str_log.c_str());
+
+ return;
+}
+
+static void do_settings(const char *arg)
+{
+ struct diag_tcp_connect_settings settings;
+ int ret;
+ int enable_json = 0;
+ struct params_parser parse(arg);
+ enable_json = parse.int_value("json");
+
+ memset(&settings, 0, sizeof(struct diag_tcp_connect_settings));
+ if (run_in_host) {
+ ret = diag_call_ioctl(DIAG_IOCTL_TCP_CONNECT_SETTINGS, (long)&settings);
+ } else {
+ ret = -ENOSYS;
+ syscall(DIAG_TCP_CONNECT_SETTINGS, &ret, &settings, sizeof(struct diag_tcp_connect_settings));
+ }
+
+ if (1 == enable_json) {
+ return print_settings_in_json(&settings, ret);
+ }
+
+ if (ret == 0) {
+ printf("功能设置:\n");
+ printf(" 是否激活:%s\n", settings.activated ? "√" : "×");
+ printf(" 输出级别:%d\n", settings.verbose);
+ } else {
+ printf("获取tcp-connect设置失败,请确保正确安装了diagnose-tools工具\n");
+ }
+}
+
+static int tcp_connect_extract(void *buf, unsigned int len, void *)
+{
+ int *et_type;
+ struct tcp_connect_detail *detail;
+ struct in_addr addr;
+
+ if (len == 0)
+ return 0;
+
+ et_type = (int *)buf;
+ switch (*et_type) {
+ case et_tcp_connect_detail:
+ if (len < sizeof(struct tcp_connect_detail))
+ break;
+ detail = (struct tcp_connect_detail *)buf;
+ printf("CGROUP:[%s] comm:%s 时间:[%lu:%lu]\n", detail->cgroup, detail->comm,
+ detail->tv.tv_sec, detail->tv.tv_usec);
+ printf("type:%d\n", detail->con_type);
+ addr.s_addr = detail->laddr;
+ printf("laddr:%s lport:%d\n", inet_ntoa(addr), detail->lport);
+ addr.s_addr = detail->raddr;
+ printf("raddr:%s rport:%d\n", inet_ntoa(addr), detail->rport);
+ printf("\n");
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int sls_extract(void *buf, unsigned int len, void *)
+{
+ int *et_type;
+ struct tcp_connect_detail *detail;
+ struct in_addr addr;
+ struct diag_timespec tv;
+ Json::Value root;
+ stringstream ss;
+
+ if (len == 0)
+ return 0;
+
+ diag_gettimeofday(&tv, NULL);
+ et_type = (int *)buf;
+ switch (*et_type) {
+ case et_tcp_connect_detail:
+ if (len < sizeof(struct tcp_connect_detail))
+ break;
+ detail = (struct tcp_connect_detail *)buf;
+ root["type"] = Json::Value(detail->con_type);
+ root["time"] = Json::Value(detail->tv.tv_sec);
+ addr.s_addr = detail->laddr;
+ root["laddr"] = Json::Value(inet_ntoa(addr));
+ root["lport"] = Json::Value(detail->lport);
+ addr.s_addr = detail->raddr;
+ root["raddr"] = Json::Value(inet_ntoa(addr));
+ root["rport"] = Json::Value(detail->rport);
+ root["comm"] = Json::Value(detail->comm);
+ root["cgroup"] = Json::Value(detail->cgroup);
+
+ write_file(sls_file, "tcp-connect", &tv, 0, 0, root);
+ write_syslog(syslog_enabled, "tcp-connect", &tv, 0, 0, root);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+static void do_extract(char *buf, int len)
+{
+ extract_variant_buffer(buf, len, tcp_connect_extract, NULL);
+}
+
+static void do_dump(const char *arg)
+{
+ static char variant_buf[1024 * 1024];
+ int len;
+ int ret = 0;
+ struct params_parser parse(arg);
+ tcp_connect_ignore = parse.int_value("ignore");
+ struct diag_ioctl_dump_param dump_param = {
+ .user_ptr_len = &len,
+ .user_buf_len = 1024 * 1024,
+ .user_buf = variant_buf,
+ };
+
+ memset(variant_buf, 0, 1024 * 1024);
+ if (run_in_host) {
+ ret = diag_call_ioctl(DIAG_IOCTL_TCP_CONNECT_SET_DUMP, (long)&dump_param);
+ } else {
+ ret = -ENOSYS;
+ syscall(DIAG_TCP_CONNECT_DUMP, &ret, &len, variant_buf, 1024 * 1024);
+ }
+
+ if (ret == 0) {
+ do_extract(variant_buf, len);
+ }
+
+ tcp_connect_ignore = 0;
+}
+
+static void do_sls(char *arg)
+{
+ int ret;
+ int len;
+ static char variant_buf[1024 * 1024];
+ struct diag_ioctl_dump_param dump_param = {
+ .user_ptr_len = &len,
+ .user_buf_len = 1024 * 1024,
+ .user_buf = variant_buf,
+ };
+
+ ret = log_config(arg, sls_file, &syslog_enabled);
+ if (ret != 1)
+ return;
+
+ while (1) {
+ if (run_in_host) {
+ ret = diag_call_ioctl(DIAG_IOCTL_TCP_CONNECT_SET_DUMP, (long)&dump_param);
+ } else {
+ syscall(DIAG_TCP_CONNECT_DUMP, &ret, &len, variant_buf, 1024 * 1024);
+ }
+
+ if (ret == 0 && len > 0) {
+ extract_variant_buffer(variant_buf, len, sls_extract, NULL);
+ }
+
+ sleep(10);
+ }
+}
+
+int tcp_connect_main(int argc, char **argv)
+{
+ static struct option long_options[] = {
+ {"help", no_argument, 0, 0 },
+ {"activate", optional_argument, 0, 0 },
+ {"deactivate", no_argument, 0, 0 },
+ {"settings", optional_argument, 0, 0 },
+ {"report", optional_argument, 0, 0 },
+ {"log", required_argument, 0, 0 },
+ {0, 0, 0, 0 }
+ };
+ int c;
+
+ if (argc <= 1) {
+ usage_tcp_connect();
+ return 0;
+ }
+ while (1) {
+ int option_index = -1;
+
+ c = getopt_long_only(argc, argv, "", long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (option_index) {
+ case 0:
+ usage_tcp_connect();
+ break;
+ case 1:
+ do_activate(optarg ? optarg : "");
+ break;
+ case 2:
+ do_deactivate();
+ break;
+ case 3:
+ do_settings(optarg ? optarg : "");
+ break;
+ case 4:
+ do_dump(optarg ? optarg : "");
+ break;
+ case 5:
+ do_sls(optarg);
+ break;
+ default:
+ usage_tcp_connect();
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/SOURCE/module/Makefile b/SOURCE/module/Makefile
index 0838616..d6c312a 100755
--- a/SOURCE/module/Makefile
+++ b/SOURCE/module/Makefile
@@ -220,7 +220,7 @@ ifneq ($(KERNELRELEASE),)
$(TARGET)-objs += io/io_entry.o
$(TARGET)-objs += fs/fs_entry.o fs/orphan.o fs/shm.o fs/rw_top.o
$(TARGET)-objs += net/net_entry.o net/tcp_retrans.o net/drop_packet.o net/ping_delay.o net/ping_delay6.o \
- net/net_bandwidth.o
+ net/net_bandwidth.o net/tcp_connect.o
ifeq ($(EXPERIENTIAL),1)
$(TARGET)-objs += test/test.o
diff --git a/SOURCE/module/chr_dev.c b/SOURCE/module/chr_dev.c
index ef4c1f5..6920cc5 100644
--- a/SOURCE/module/chr_dev.c
+++ b/SOURCE/module/chr_dev.c
@@ -183,6 +183,9 @@ static long diag_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case DIAG_IOCTL_TYPE_MEMCG_STATS:
ret = diag_ioctl_memcg_stats(nr, arg);
break;
+ case DIAG_IOCTL_TYPE_TCP_CONNECT:
+ ret = diag_ioctl_tcp_connect(nr, arg);
+ break;
default:
break;
}
diff --git a/SOURCE/module/entry.c b/SOURCE/module/entry.c
index 1c1fa32..237efb2 100644
--- a/SOURCE/module/entry.c
+++ b/SOURCE/module/entry.c
@@ -58,6 +58,7 @@
#include "uapi/task_monitor.h"
#include "uapi/rw_sem.h"
#include "uapi/rss_monitor.h"
+#include "uapi/tcp_connect.h"
unsigned long diag_timer_period = 10;
@@ -179,6 +180,8 @@ static ssize_t controller_file_write(struct diag_trace_file *trace_file,
activate_memcg_stats();
} else if (strcmp(func, "throttle-delay") == 0) {
activate_throttle_delay();
+ } else if (strcmp(func, "tcp-connect") == 0) {
+ activate_tcp_connect();
}
up(&controller_sem);
@@ -258,6 +261,8 @@ static ssize_t controller_file_write(struct diag_trace_file *trace_file,
deactivate_memcg_stats();
} else if (strcmp(func, "throttle-delay") == 0) {
deactivate_throttle_delay();
+ } else if (strcmp(func, "tcp-connect") == 0) {
+ deactivate_tcp_connect();
}
up(&controller_sem);
@@ -427,6 +432,9 @@ static void diag_cb_sys_enter(void *data, struct pt_regs *regs, long id)
} else if (id >= DIAG_BASE_SYSCALL_THROTTLE_DELAY
&& id < DIAG_BASE_SYSCALL_THROTTLE_DELAY + DIAG_SYSCALL_INTERVAL) {
ret = throttle_delay_syscall(regs, id);
+ } else if (id >= DIAG_BASE_SYSCALL_TCP_CONNECT
+ && id < DIAG_BASE_SYSCALL_TCP_CONNECT + DIAG_SYSCALL_INTERVAL) {
+ ret = tcp_connect_syscall(regs, id);
}
up(&controller_sem);
diff --git a/SOURCE/module/internal.h b/SOURCE/module/internal.h
index 483605e..801bcd6 100755
--- a/SOURCE/module/internal.h
+++ b/SOURCE/module/internal.h
@@ -812,6 +812,8 @@ int activate_fs_orphan(void);
int deactivate_fs_orphan(void);
int activate_net_bandwidth(void);
int deactivate_net_bandwidth(void);
+int activate_tcp_connect(void);
+int deactivate_tcp_connect(void);
int perf_syscall(struct pt_regs *regs, long id);
diff --git a/SOURCE/module/kernel/throttle_delay.c b/SOURCE/module/kernel/throttle_delay.c
index 1b4dc3a..cebb7fa 100755
--- a/SOURCE/module/kernel/throttle_delay.c
+++ b/SOURCE/module/kernel/throttle_delay.c
@@ -663,11 +663,12 @@ static void jump_init(void)
}
+#if 0
static int kprobe_dequeue_entity_pre(struct kprobe *p, struct pt_regs *regs)
{
- struct sched_entity *se = (void *)ORIG_PARAM2(regs);
- int *flags = (void *)ORIG_PARAM3(regs);
- struct task_struct *task;
+ //struct sched_entity *se = (void *)ORIG_PARAM2(regs);
+ //int *flags = (void *)ORIG_PARAM3(regs);
+ //struct task_struct *task;
if (!throttle_delay_settings.activated)
return 0;
@@ -675,6 +676,7 @@ static int kprobe_dequeue_entity_pre(struct kprobe *p, struct pt_regs *regs)
return 0;
}
+#endif
#if KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE
static void trace_sched_switch_hit(void *__data, bool preempt,
diff --git a/SOURCE/module/net/net_entry.c b/SOURCE/module/net/net_entry.c
index 83cb821..1560a5c 100755
--- a/SOURCE/module/net/net_entry.c
+++ b/SOURCE/module/net/net_entry.c
@@ -76,8 +76,14 @@ int diag_net_init(void)
if (ret)
goto out_net_bandwidth;
+ ret = diag_net_tcp_connect_init();
+ if (ret)
+ goto out_tcp_connect;
+
return 0;
+out_tcp_connect:
+ diag_net_net_bandwidth_exit();
out_net_bandwidth:
diag_net_ping_delay6_exit();
out_ping_delay6:
@@ -106,5 +112,6 @@ void diag_net_exit(void)
diag_net_packet_corruption_exit();
diag_net_redis_ixgbe_exit();
diag_net_net_bandwidth_exit();
+ diag_net_tcp_connect_exit();
//remove_proc_entry("ali-linux/diagnose/net", NULL);
}
diff --git a/SOURCE/module/net/net_internal.h b/SOURCE/module/net/net_internal.h
index 7285ea9..b5f5305 100644
--- a/SOURCE/module/net/net_internal.h
+++ b/SOURCE/module/net/net_internal.h
@@ -11,6 +11,8 @@
extern int diag_tcp_retrans_init(void);
extern void diag_tcp_retrans_exit(void);
+extern int diag_net_tcp_connect_init(void);
+extern void diag_net_tcp_connect_exit(void);
extern int diag_net_drop_packet_init(void);
extern void diag_net_drop_packet_exit(void);
extern int diag_net_reqsk_init(void);
diff --git a/SOURCE/module/net/tcp_connect.c b/SOURCE/module/net/tcp_connect.c
new file mode 100644
index 0000000..13ddae1
--- /dev/null
+++ b/SOURCE/module/net/tcp_connect.c
@@ -0,0 +1,365 @@
+/*
+ * Linux内核诊断工具--内核态tcp-connect功能
+ *
+ * Copyright (C) 2022 Alibaba Ltd.
+ *
+ * 作者: Yang Wei <[email protected]>
+ *
+ * License terms: GNU General Public License (GPL) version 3
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sysctl.h>
+#include <linux/rtc.h>
+#include <linux/time.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <net/tcp.h>
+#include <net/protocol.h>
+
+#include "uapi/ali_diagnose.h"
+#include "uapi/tcp_connect.h"
+#include "pub/variant_buffer.h"
+#include "pub/kprobe.h"
+#include "internal.h"
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(4, 9, 0)
+
+static struct kprobe kprobe_tcp_connect;
+static struct kretprobe kretprobe_inet_csk_accept;
+static struct kprobe kprobe_tcp_close;
+
+static atomic64_t diag_nr_running = ATOMIC64_INIT(0);
+static struct diag_variant_buffer tcp_connect_variant_buffer;
+static struct diag_tcp_connect_settings tcp_connect_settings;
+static unsigned int tcp_connect_alloced;
+
+static int kprobe_tcp_connect_pre(struct kprobe *p, struct pt_regs *regs)
+{
+ struct tcp_connect_detail detail;
+ unsigned long flags;
+ struct sock *sk;
+
+ atomic64_inc(&diag_nr_running);
+
+ detail.et_type = et_tcp_connect_detail;
+ detail.con_type = TCPCONNECT;
+ do_diag_gettimeofday(&detail.tv);
+
+ sk = (struct sock *) ORIG_PARAM1(regs);
+ detail.raddr = sk->sk_daddr;
+ detail.laddr = sk->sk_rcv_saddr;
+ detail.rport = ntohs(sk->sk_dport);
+ detail.lport = sk->sk_num;
+ strncpy(detail.comm, current->comm, TASK_COMM_LEN);
+ detail.comm[TASK_COMM_LEN - 1] = 0;
+ diag_cgroup_name(current, detail.cgroup, CGROUP_NAME_LEN, 0);
+ detail.cgroup[CGROUP_NAME_LEN - 1] = 0;
+
+ diag_variant_buffer_spin_lock(&tcp_connect_variant_buffer, flags);
+ diag_variant_buffer_reserve(&tcp_connect_variant_buffer, sizeof(struct tcp_connect_detail));
+ diag_variant_buffer_write_nolock(&tcp_connect_variant_buffer, &detail, sizeof(struct tcp_connect_detail));
+ diag_variant_buffer_seal(&tcp_connect_variant_buffer);
+ diag_variant_buffer_spin_unlock(&tcp_connect_variant_buffer, flags);
+
+ atomic64_dec(&diag_nr_running);
+
+ return 0;
+}
+
+static int kretprobe_inet_csk_accept_return(struct kretprobe_instance *ri, struct pt_regs *regs)
+{
+ struct tcp_connect_detail detail;
+ unsigned long flags;
+ struct sock *sk;
+
+ sk = (struct sock *)regs_return_value(regs);
+ if (!sk)
+ return 0;
+
+ atomic64_inc(&diag_nr_running);
+
+ detail.et_type = et_tcp_connect_detail;
+ detail.con_type = TCPACCEPT;
+ do_diag_gettimeofday(&detail.tv);
+
+ detail.raddr = sk->sk_daddr;
+ detail.laddr = sk->sk_rcv_saddr;
+ detail.rport = ntohs(sk->sk_dport);
+ detail.lport = sk->sk_num;
+
+ strncpy(detail.comm, current->comm, TASK_COMM_LEN);
+ detail.comm[TASK_COMM_LEN - 1] = 0;
+ diag_cgroup_name(current, detail.cgroup, CGROUP_NAME_LEN, 0);
+ detail.cgroup[CGROUP_NAME_LEN - 1] = 0;
+
+ diag_variant_buffer_spin_lock(&tcp_connect_variant_buffer, flags);
+ diag_variant_buffer_reserve(&tcp_connect_variant_buffer, sizeof(struct tcp_connect_detail));
+ diag_variant_buffer_write_nolock(&tcp_connect_variant_buffer, &detail, sizeof(struct tcp_connect_detail));
+ diag_variant_buffer_seal(&tcp_connect_variant_buffer);
+ diag_variant_buffer_spin_unlock(&tcp_connect_variant_buffer, flags);
+
+ atomic64_dec(&diag_nr_running);
+
+ return 0;
+}
+
+static int kprobe_tcp_close_pre(struct kprobe *p, struct pt_regs *regs)
+{
+ struct tcp_connect_detail detail;
+ unsigned long flags;
+ struct sock *sk;
+
+ atomic64_inc(&diag_nr_running);
+
+ detail.et_type = et_tcp_connect_detail;
+ detail.con_type = TCPCLOSE;
+ do_diag_gettimeofday(&detail.tv);
+
+ sk = (struct sock *) ORIG_PARAM1(regs);
+ detail.raddr = sk->sk_daddr;
+ detail.laddr = sk->sk_rcv_saddr;
+ detail.rport = ntohs(sk->sk_dport);
+ detail.lport = sk->sk_num;
+ strncpy(detail.comm, current->comm, TASK_COMM_LEN);
+ detail.comm[TASK_COMM_LEN - 1] = 0;
+ diag_cgroup_name(current, detail.cgroup, CGROUP_NAME_LEN, 0);
+ detail.cgroup[CGROUP_NAME_LEN - 1] = 0;
+
+ diag_variant_buffer_spin_lock(&tcp_connect_variant_buffer, flags);
+ diag_variant_buffer_reserve(&tcp_connect_variant_buffer, sizeof(struct tcp_connect_detail));
+ diag_variant_buffer_write_nolock(&tcp_connect_variant_buffer, &detail, sizeof(struct tcp_connect_detail));
+ diag_variant_buffer_seal(&tcp_connect_variant_buffer);
+ diag_variant_buffer_spin_unlock(&tcp_connect_variant_buffer, flags);
+
+ atomic64_dec(&diag_nr_running);
+
+ return 0;
+}
+
+static int __activate_tcp_connect(void)
+{
+ int ret = 0;
+
+ ret = alloc_diag_variant_buffer(&tcp_connect_variant_buffer);
+ if (ret)
+ goto out_variant_buffer;
+
+ tcp_connect_alloced = 1;
+
+ ret = hook_kprobe(&kprobe_tcp_connect, "tcp_connect",
+ kprobe_tcp_connect_pre, NULL);
+ if (ret) {
+ printk("aprof: failed to hook tcp_connect, ret=%d\n", ret);
+ goto out_variant_buffer;;
+ }
+
+ ret = hook_kretprobe(&kretprobe_inet_csk_accept, "inet_csk_accept",
+ NULL, kretprobe_inet_csk_accept_return, 0);
+ if (ret) {
+ printk("aprof: failed to hoot inet_csk_accept, ret:%d\n", ret);
+ goto err_unhook_tcp_connect;
+ }
+
+ ret = hook_kprobe(&kprobe_tcp_close, "tcp_close",
+ kprobe_tcp_close_pre, NULL);
+ if (ret) {
+ printk("aprof: failed to hoot tcp_close, ret:%d\n", ret);
+ goto err_unhook_inet_csk_accept;
+ }
+
+ return 1;
+
+
+err_unhook_inet_csk_accept:
+ unhook_kretprobe(&kretprobe_inet_csk_accept);
+err_unhook_tcp_connect:
+ unhook_kprobe(&kprobe_tcp_connect);
+out_variant_buffer:
+ return 0;
+}
+
+static void __deactivate_tcp_connect(void)
+{
+ unhook_kprobe(&kprobe_tcp_connect);
+ unhook_kretprobe(&kretprobe_inet_csk_accept);
+ unhook_kprobe(&kprobe_tcp_close);
+
+ synchronize_sched();
+ msleep(20);
+ while (atomic64_read(&diag_nr_running) > 0)
+ msleep(20);
+}
+
+int activate_tcp_connect(void)
+{
+ if (!tcp_connect_settings.activated)
+ tcp_connect_settings.activated = __activate_tcp_connect();
+
+ return tcp_connect_settings.activated;
+}
+
+int deactivate_tcp_connect(void)
+{
+ if (tcp_connect_settings.activated)
+ __deactivate_tcp_connect();
+
+ tcp_connect_settings.activated = 0;
+ return 0;
+}
+
+int tcp_connect_syscall(struct pt_regs *regs, long id)
+{
+ int __user *user_ptr_len;
+ size_t __user user_buf_len;
+ void __user *user_buf;
+ int ret = 0;
+ struct diag_tcp_connect_settings settings;
+
+ switch (id) {
+ case DIAG_TCP_CONNECT_SET:
+ user_buf = (void __user *)SYSCALL_PARAM1(regs);
+ user_buf_len = (size_t)SYSCALL_PARAM2(regs);
+
+ if (user_buf_len != sizeof(struct diag_tcp_connect_settings)) {
+ ret = -EINVAL;
+ } else if (tcp_connect_settings.activated) {
+ ret = -EBUSY;
+ } else {
+ ret = copy_from_user(&settings, user_buf, user_buf_len);
+ if (!ret) {
+ tcp_connect_settings = settings;
+ }
+ }
+ break;
+ case DIAG_TCP_CONNECT_SETTINGS:
+ user_buf = (void __user *)SYSCALL_PARAM1(regs);
+ user_buf_len = (size_t)SYSCALL_PARAM2(regs);
+
+ if (user_buf_len != sizeof(struct diag_tcp_connect_settings)) {
+ ret = -EINVAL;
+ } else {
+ settings.activated = tcp_connect_settings.activated;
+ settings.verbose = tcp_connect_settings.verbose;
+ ret = copy_to_user(user_buf, &settings, user_buf_len);
+ }
+ break;
+ case DIAG_TCP_CONNECT_DUMP:
+ user_ptr_len = (void __user *)SYSCALL_PARAM1(regs);
+ user_buf = (void __user *)SYSCALL_PARAM2(regs);
+ user_buf_len = (size_t)SYSCALL_PARAM3(regs);
+
+ if (!tcp_connect_alloced) {
+ ret = -EINVAL;
+ } else {
+ ret = copy_to_user_variant_buffer(&tcp_connect_variant_buffer,
+ user_ptr_len, user_buf, user_buf_len);
+ record_dump_cmd("tcp-connect");
+ }
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ return ret;
+}
+
+long diag_ioctl_tcp_connect(unsigned int cmd, unsigned long arg)
+{
+ int ret = 0;
+ struct diag_tcp_connect_settings settings;
+ struct diag_ioctl_dump_param dump_param;
+
+ switch (cmd) {
+ case CMD_TCP_CONNECT_SET:
+ if (tcp_connect_settings.activated) {
+ ret = -EBUSY;
+ } else {
+ ret = copy_from_user(&settings, (void *)arg, sizeof(struct diag_tcp_connect_settings));
+ if (!ret) {
+ tcp_connect_settings = settings;
+ }
+ }
+ break;
+ case CMD_TCP_CONNECT_SETTINGS:
+ settings.activated = tcp_connect_settings.activated;
+ settings.verbose = tcp_connect_settings.verbose;
+ ret = copy_to_user((void *)arg, &settings, sizeof(struct diag_tcp_connect_settings));
+ break;
+ case CMD_TCP_CONNECT_DUMP:
+ ret = copy_from_user(&dump_param, (void *)arg, sizeof(struct diag_ioctl_dump_param));
+
+ if (!tcp_connect_alloced) {
+ ret = -EINVAL;
+ } else if (!ret){
+ ret = copy_to_user_variant_buffer(&tcp_connect_variant_buffer,
+ dump_param.user_ptr_len, dump_param.user_buf, dump_param.user_buf_len);
+ record_dump_cmd("tcp-connect");
+ }
+ break;
+ default:
+ ret = -ENOSYS;
+ break;
+ }
+
+ return ret;
+}
+
+int diag_net_tcp_connect_init(void)
+{
+ init_diag_variant_buffer(&tcp_connect_variant_buffer, 2 * 1024 * 1024);
+
+ if (tcp_connect_settings.activated)
+ activate_tcp_connect();
+
+ return 0;
+}
+
+
+void diag_net_tcp_connect_exit(void)
+{
+ if (tcp_connect_settings.activated)
+ deactivate_tcp_connect();
+ tcp_connect_settings.activated = 0;
+
+ destroy_diag_variant_buffer(&tcp_connect_variant_buffer);
+ return;
+}
+
+#else
+
+int diag_net_tcp_connect_init(void)
+{
+ return 0;
+}
+
+void diag_net_tcp_connect_exit(void)
+{
+}
+
+int activate_tcp_connect(void)
+{
+ return 0;
+}
+
+int deactivate_tcp_connect(void)
+{
+ return 0;
+}
+
+int tcp_connect_syscall(struct pt_regs *regs, long id)
+{
+ return 0;
+}
+
+long diag_ioctl_tcp_connect(unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+#endif
+
diff --git a/SOURCE/uapi/ali_diagnose.h b/SOURCE/uapi/ali_diagnose.h
index 3c7a4d6..d5c8cdb 100644
--- a/SOURCE/uapi/ali_diagnose.h
+++ b/SOURCE/uapi/ali_diagnose.h
@@ -100,6 +100,7 @@ extern unsigned long debug_mode;
#define DIAG_IOCTL_TYPE_RSS_MONITOR (DIAG_IOCTL_TYPE_RW_SEM + 1)
#define DIAG_IOCTL_TYPE_MEMCG_STATS (DIAG_IOCTL_TYPE_RSS_MONITOR + 1)
#define DIAG_IOCTL_TYPE_THROTTLE_DELAY (DIAG_IOCTL_TYPE_MEMCG_STATS + 1)
+#define DIAG_IOCTL_TYPE_TCP_CONNECT (DIAG_IOCTL_TYPE_THROTTLE_DELAY + 1)
#define DIAG_IOCTL_TYPE_END (DIAG_IOCTL_TYPE_THROTTLE_DELAY + 1)
@@ -138,6 +139,7 @@ long diag_ioctl_task_monitor(unsigned int cmd, unsigned long arg);
long diag_ioctl_rw_sem(unsigned int cmd, unsigned long arg);
long diag_ioctl_rss_monitor(unsigned int cmd, unsigned long arg);
long diag_ioctl_memcg_stats(unsigned int cmd, unsigned long arg);
+long diag_ioctl_tcp_connect(unsigned int cmd, unsigned long arg);
struct diag_ioctl_test {
int in;
@@ -345,10 +347,13 @@ struct diag_ioctl_dump_param_cycle {
#define DIAG_BASE_SYSCALL_MEMCG_STATS \
(DIAG_BASE_SYSCALL_PING_DELAY6 + DIAG_SYSCALL_INTERVAL)
-/// 1900
+/// 1950
#define DIAG_BASE_SYSCALL_THROTTLE_DELAY \
- (DIAG_BASE_SYSCALL_PING_DELAY6 + DIAG_SYSCALL_INTERVAL)
+ (DIAG_BASE_SYSCALL_MEMCG_STATS + DIAG_SYSCALL_INTERVAL)
+//2000
+#define DIAG_BASE_SYSCALL_TCP_CONNECT \
+ (DIAG_BASE_SYSCALL_THROTTLE_DELAY + DIAG_SYSCALL_INTERVAL)
#define DIAG_SYSCALL_END (DIAG_BASE_SYSCALL + DIAG_SYSCALL_INTERVAL * 1000)
@@ -518,10 +523,13 @@ enum diag_record_id {
et_memcg_stats_summary,
et_memcg_stats_detail,
- et_throttle_delay_base = et_rss_monitor_base + DIAG_EVENT_TYPE_INTERVAL,
+ et_throttle_delay_base = et_memcg_stats_base + DIAG_EVENT_TYPE_INTERVAL,
et_throttle_delay_dither,
et_throttle_delay_rq,
+ et_tcp_connect_base = et_throttle_delay_base + DIAG_EVENT_TYPE_INTERVAL,
+ et_tcp_connect_detail,
+
et_count
};
diff --git a/SOURCE/uapi/tcp_connect.h b/SOURCE/uapi/tcp_connect.h
new file mode 100644
index 0000000..f1bf1ae
--- /dev/null
+++ b/SOURCE/uapi/tcp_connect.h
@@ -0,0 +1,53 @@
+/*
+ * Linux内核诊断工具--用户接口API
+ *
+ * Copyright (C) 2022 Alibaba Ltd.
+ *
+ * 作者: Yang Wei <[email protected]>
+ *
+ * License terms: GNU General Public License (GPL) version 3
+ *
+ */
+
+#ifndef UAPI_TCP_CONNECT_H
+#define UAPI_TCP_CONNECT_H
+
+#include <linux/ioctl.h>
+int tcp_connect_syscall(struct pt_regs *regs, long id);
+
+#define DIAG_TCP_CONNECT_SET (DIAG_BASE_SYSCALL_TCP_CONNECT)
+#define DIAG_TCP_CONNECT_SETTINGS (DIAG_TCP_CONNECT_SET + 1)
+#define DIAG_TCP_CONNECT_DUMP (DIAG_TCP_CONNECT_SETTINGS + 1)
+
+struct diag_tcp_connect_settings {
+ unsigned int activated;
+ unsigned int verbose;
+};
+
+enum connect_type {
+ TCPCONNECT = 1,
+ TCPACCEPT = 2,
+ TCPCLOSE = 3,
+};
+
+struct tcp_connect_detail {
+ int et_type;
+ enum connect_type con_type;
+ struct diag_timespec tv;
+ unsigned int laddr;
+ unsigned int raddr;
+ unsigned short lport;
+ unsigned short rport;
+ char comm[TASK_COMM_LEN];
+ char cgroup[CGROUP_NAME_LEN];
+};
+
+#define CMD_TCP_CONNECT_SET (0)
+#define CMD_TCP_CONNECT_SETTINGS (CMD_TCP_CONNECT_SET + 1)
+#define CMD_TCP_CONNECT_DUMP (CMD_TCP_CONNECT_SETTINGS + 1)
+#define DIAG_IOCTL_TCP_CONNECT_SET _IOWR(DIAG_IOCTL_TYPE_TCP_CONNECT, CMD_TCP_CONNECT_SET, struct diag_tcp_connect_settings)
+#define DIAG_IOCTL_TCP_CONNECT_SETTINGS _IOWR(DIAG_IOCTL_TYPE_TCP_CONNECT, CMD_TCP_CONNECT_SETTINGS, struct diag_tcp_connect_settings)
+#define DIAG_IOCTL_TCP_CONNECT_SET_DUMP _IOWR(DIAG_IOCTL_TYPE_TCP_CONNECT, CMD_TCP_CONNECT_DUMP, struct diag_ioctl_dump_param)
+
+#endif
+