Skip to content

Commit

Permalink
Merge branch 'linuxkerneltravel:develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
albertxu216 authored May 19, 2024
2 parents f020126 + eea66dc commit ad6c1c3
Show file tree
Hide file tree
Showing 365 changed files with 371,034 additions and 66 deletions.
14 changes: 14 additions & 0 deletions eBPF_Supermarket/CPU_Subsystem/cpu_watcher/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,20 @@ $(TARGETS): %: $(OUTPUT)/%.o $(COMMON_OBJ) $(LIBBPF_OBJ) | $(OUTPUT)
$(call msg,BINARY,$@)
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lstdc++ -lelf -lz -o $@

SUCCESS_MESSAGE:
@echo "\e[38;2;255;0;0m __ __ \e[0m"
@echo "\e[38;2;255;128;0m _________ __ __ _ ______ _/ /______/ /_ ___ _____\e[0m"
@echo "\e[38;2;255;255;0m / ___/ __ \/ / / / | | /| / / __ / __/ ___/ __ \/ _ \/ ___/\e[0m"
@echo "\e[38;2;128;255;0m/ /__/ /_/ / /_/ / | |/ |/ / /_/ / /_/ /__/ / / / __/ / \e[0m"
@echo "\e[38;2;0;255;0m\___/ .___/\__,_/ |__/|__/\__,_/\__/\___/_/ /_/\___/_/ \e[0m"
@echo "\e[38;2;0;255;128m /_/ \e[0m"
@echo "\e[38;2;0;255;255mSuccessful to compile cpu_watcher tools: \e[0m"
@echo "\e[38;2;0;255;255mPlease start your use ~ \e[0m"


all: $(TARGETS) SUCCESS_MESSAGE


# delete failed targets
.DELETE_ON_ERROR:

Expand Down
88 changes: 81 additions & 7 deletions eBPF_Supermarket/CPU_Subsystem/cpu_watcher/cpu_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@
#include <time.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include <sys/sysinfo.h>
#include <sys/select.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>
#include "cpu_watcher.h"
Expand All @@ -35,6 +38,7 @@

typedef long long unsigned int u64;
typedef unsigned int u32;
#define MAX_BUF 512

struct list_head {
struct list_head *next;
Expand All @@ -50,6 +54,8 @@ struct msg_msg {

static struct env {
int time;
int period;
bool percent;
bool enable_proc;
bool SAR;
bool CS_DELAY;
Expand All @@ -60,6 +66,8 @@ static struct env {
int freq;
} env = {
.time = 0,
.period = 1,
.percent = false,
.enable_proc = false,
.SAR = false,
.CS_DELAY = false,
Expand Down Expand Up @@ -87,6 +95,7 @@ unsigned long ktTime = 0;
unsigned long utTime = 0;
u64 tick_user = 0;


int sc_sum_time = 0 ;
int sc_max_time = 0 ;
int sc_min_time = SYSCALL_MIN_TIME ;
Expand All @@ -102,6 +111,8 @@ int preempt_start_print = 0 ;
const char argp_program_doc[] ="cpu wacher is in use ....\n";
static const struct argp_option opts[] = {
{ "time", 't', "TIME-SEC", 0, "Max Running Time(0 for infinite)" },
{ "period", 'i', "INTERVAL", 0, "Period interval in seconds" },
{"percent",'P',0,0,"format data as percentages"},
{"libbpf_sar", 's', 0,0,"print sar_info (the data of cpu)"},
{"cs_delay", 'c', 0,0,"print cs_delay (the data of cpu)"},
{"syscall_delay", 'S', 0,0,"print syscall_delay (the data of syscall)"},
Expand All @@ -118,6 +129,12 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
env.time = strtol(arg, NULL, 10);
if(env.time) alarm(env.time);
break;
case 'i':
env.period = strtol(arg, NULL, 10);
break;
case 'P':
env.percent = true;
break;
case 's':
env.SAR = true;
break;
Expand Down Expand Up @@ -219,6 +236,7 @@ u64 find_ksym(const char* target_symbol) {

static int print_all()
{
int nprocs = get_nprocs();
/*proc:*/
int key_proc = 1;
int err_proc, fd_proc = bpf_map__fd(sar_skel->maps.countMap);
Expand Down Expand Up @@ -334,10 +352,30 @@ static int print_all()
if(env.enable_proc){
time_t now = time(NULL);
struct tm *localTime = localtime(&now);
printf("%02d:%02d:%02d %8llu %8llu %6d %8llu %10llu %8llu %10lu %8llu %8llu %8llu\n",
if (env.percent == true){
printf("%02d:%02d:%02d %8llu %8llu %6d ",localTime->tm_hour, localTime->tm_min, localTime->tm_sec,__proc, __sched, runqlen);
// 大于百分之60的标红输出
double values[7] = {
(double)dtairqtime / 10000000 / nprocs / env.period,
(double)dtasoftirq / 10000000 / nprocs / env.period,
(double)dtaidle / 10000000 / nprocs / env.period,
(double)dtaKT / 10000000 / nprocs / env.period,
(double)dtaSysc / 10000000 / nprocs / env.period,
(double)dtaUTRaw / 10000000 / nprocs / env.period,
(double)dtaSys / 10000000 / nprocs / env.period
};
for (int i = 0; i < 7; i++) {
if (values[i] > 60.0) {
printf("\033[1;31m"); // 设置为红色
}
printf("%10.2f ", values[i]);
printf("\033[0m"); // 重置为默认颜色
}
printf("\n");
}else{printf("%02d:%02d:%02d %8llu %8llu %6d %8llu %10llu %8llu %10lu %8llu %8llu %8llu\n",
localTime->tm_hour, localTime->tm_min, localTime->tm_sec,
__proc,__sched,runqlen,dtairqtime/1000,dtasoftirq/1000,dtaidle/1000000,
dtaKT/1000,dtaSysc / 1000000,dtaUTRaw/1000000,dtaSys / 1000000);
dtaKT/1000,dtaSysc / 1000000,dtaUTRaw/1000000,dtaSys / 1000000);}
}
else{
env.enable_proc = true;
Expand Down Expand Up @@ -440,6 +478,32 @@ static int preempt_print(void *ctx, void *data, unsigned long data_sz)
return 0;
}

char* get_process_name_by_pid(int pid) {
static char buf[MAX_BUF];
char command[MAX_BUF];
snprintf(command, sizeof(command), "cat /proc/%d/status | grep Name", pid);
FILE* fp = popen(command, "r");
if (fp == NULL) {
perror("popen");
return NULL;
}
char* name = NULL;
while (fgets(buf, sizeof(buf), fp)) {
if (strncmp(buf, "Name:", 5) == 0) {
name = strdup(buf + 6);
break;
}
}
pclose(fp);
if (name != NULL) {
size_t len = strlen(name);
if (len > 0 && name[len - 1] == '\n') {
name[len - 1] = '\0';
}
}
return name;
}

static int schedule_print(struct bpf_map *sys_fd)
{
int key = 0;
Expand All @@ -460,8 +524,16 @@ static int schedule_print(struct bpf_map *sys_fd)
if(!ifprint){
ifprint=1;
}else{
printf("%02d:%02d:%02d %-15lf %-15lf %5d %15lf %10d\n",
hour, min, sec, avg_delay / 1000.0, info.max_delay / 1000.0,info.pid_max, info.min_delay / 1000.0,info.pid_min);
char* proc_name_max = get_process_name_by_pid(info.pid_max);
char* proc_name_min = get_process_name_by_pid(info.pid_min);
printf("%02d:%02d:%02d %-15lf %-15lf %10s %15lf %15s\n",
hour, min, sec, avg_delay / 1000.0, info.max_delay / 1000.0,proc_name_max,info.min_delay / 1000.0,proc_name_min);
if (proc_name_max != NULL) {
free(proc_name_max);
}
if (proc_name_min != NULL) {
free(proc_name_min);
}
}
return 0;
}
Expand Down Expand Up @@ -619,7 +691,7 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto schedule_cleanup;
}
printf("%-8s %s\n", " TIME ", "avg_delay/μs max_delay/μs max_pid min_delay/μs min_pid");
printf("%-8s %s\n", " TIME ", "avg_delay/μs max_delay/μs max_proc_name min_delay/μs min_proc_name");
}else if (env.SAR){
/* Load and verify BPF application */
sar_skel = sar_bpf__open();
Expand Down Expand Up @@ -648,7 +720,9 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to attach BPF skeleton\n");
goto sar_cleanup;
}
printf(" time proc/s cswch/s runqlen irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms \n");
if (env.percent){
printf(" time proc/s cswch/s runqlen irqTime/%% softirq/%% idle/%% kthread/%% sysc/%% utime/%% sys/%% \n");
}else{printf(" time proc/s cswch/s runqlen irqTime/us softirq/us idle/ms kthread/us sysc/ms utime/ms sys/ms \n");}
}else if(env.MQ_DELAY){
/* Load and verify BPF application */
mq_skel = mq_delay_bpf__open();
Expand Down Expand Up @@ -681,7 +755,7 @@ int main(int argc, char **argv)
}
while (!exiting) {
if(env.SAR){
sleep(1);
sleep(env.period);
err = print_all();
if (err == -EINTR) {
err = 0;
Expand Down
38 changes: 29 additions & 9 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
OUTPUT := .output
CLANG ?= clang
LIBBPF_SRC := $(abspath ../libbpf-bootstrap/libbpf/src)
BPFTOOL_SRC := $(abspath ../libbpf-bootstrap/bpftool/src)
LIBBPF_SRC := $(abspath ../../lib/libbpf/src)
BPFTOOL_SRC := $(abspath ../../lib/bpftool/src)
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool)
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
Expand All @@ -14,11 +14,14 @@ ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
| sed 's/mips.*/mips/' \
| sed 's/riscv64/riscv/' \
| sed 's/loongarch64/loongarch/')
VMLINUX := ../libbpf-bootstrap/vmlinux/$(ARCH)/vmlinux.h
LOGSRC := ./data/doc
VMDIR := ../../lib/vmlinux
VMLINUXSRC := $(VMDIR)/$(ARCH)
VMLINUX := $(VMLINUXSRC)/vmlinux.h
# Use our own libbpf API headers and Linux UAPI headers distributed with
# libbpf to avoid dependency on system-wide headers, which could be missing or
# outdated
INCLUDES := -I$(OUTPUT) -I../../libbpf/include/uapi -I$(dir $(VMLINUX))
INCLUDES := -I$(OUTPUT) -I ../../lib/libbpf/include/uapi -I$(dir $(VMLINUX))
CFLAGS := -g -Wall
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)

Expand Down Expand Up @@ -57,13 +60,30 @@ $(call allow-override,CC,$(CROSS_COMPILE)cc)
$(call allow-override,LD,$(CROSS_COMPILE)ld)

.PHONY: all
all: $(APPS)
all: deps $(APPS)
#更新vmlinux.h文件
.PHONY: deps
deps:
mkdir -p $(VMLINUXSRC)
bpftool btf dump file /sys/kernel/btf/vmlinux format c > $(VMLINUX)

.PHONY: clean
clean:
$(call msg,CLEAN)
$(Q)rm -rf $(OUTPUT) $(APPS)


rm -rf $(LOGSRC)
rm -rf $(VMDIR)

.PHONY: clean2
clean2:
$(call msg,CLEAN)
rm -f $(APPS)
rm -f $(OUTPUT)/*.skel.h
rm -f $(OUTPUT)/*.o
rm -rf $(LOGSRC)
rm -rf $(VMDIR)

$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT):
$(call msg,MKDIR,$@)
$(Q)mkdir -p $@
Expand All @@ -72,7 +92,7 @@ $(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT):
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
$(call msg,LIB,$@)
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
OBJDIR=$(dir $@)libbpf DESTDIR=$(dir $@) \
INCLUDEDIR= LIBDIR= UAPIDIR= \
install

Expand All @@ -82,7 +102,7 @@ $(BPFTOOL): | $(BPFTOOL_OUTPUT)
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap

# Build BPF code
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL)
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard *.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL)
$(call msg,BPF,$@)
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
Expand All @@ -97,7 +117,7 @@ $(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL)
# Build user-space code
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h

$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT)
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT) $(wildcard %.h)
$(call msg,CC,$@)
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@

Expand Down
24 changes: 13 additions & 11 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# netwatcher - 网络检测工具
## 一、工具介绍
### 1.1 背景

lmp现有许多用于监控linux网络协议栈相关信息的小工具,但这些工具功能零散并且冗余:
| 工具目录 | 功能 | 监控信息 |
| --- | --- | --- |
Expand All @@ -20,6 +21,12 @@ lmp现有许多用于监控linux网络协议栈相关信息的小工具,但这
### 1.2 功能介绍
`netwatcher`是一款基于eBPF的高效网络检测工具,其目的是为了让用户能够轻松快捷地获取到网络协议栈的详细信息,通过高效的数据采集和精准的监控能力,帮助用户深入了解网络行为,确保网络安全和性能的优化。其在车辆智能导航、自动驾驶等关键领扮演着重要角色,面对网络异常或延迟时,`netwatcher`能够提供强大的网络监测和优化支持,帮助企业及时诊断并解决网络障碍,提升系统稳定性和服务可靠性。

netwatcher作为一款基于eBPF的网络检测工具,其设计初衷是帮助用户能够在主机环境中,轻松快捷地获取到 Linux 网络协议栈的详细信息,通过高效的数据收集和精准的监控能力,深入了解网络行为,确保网络安全和性能的优化,其应用范围涉及较广。

netwatcher能够追踪TCP、UDP、ICMP协议数据包从应用程序发出开始,经过内核协议栈到驱动、最终发出过程(发包路径)的时延数据和流量信息,以及数据包从驱动到内核协议栈到用户态程序的过程(收包路径)中的时延数据。对获取到的时延数据采用算法进行阈值比较捕获异常时延数据并给予警告信息。同时监测TCP连接的状态信息(seq、ack、连接状态、重传信息、错误信息、rwnd、cwnd、sndbuf等关键指标),并且可以监控丢包事件(包括skb_drop_reason中定义的77种原因)。

其有助于及时解决各种网络问题,提高系统稳定性和服务可靠性。无论是云计算所需要的确保其基础设施的稳定性和安全性,还是金融机构需要保障交易的及时性和安全性,亦或是电子商务企业追求用户体验和网站性能的优化,netwatcher都提供了强大的网络监测和优化能力,满足不同行业的需求,助力企业顺利应对数字化时代的挑战。

目前,其实现的功能包括:

- TCP相关的信息监测:主机环境下对tcp/ip协议的分析,可以统计流量,延时,错误,链接信息等主要信息
Expand Down Expand Up @@ -49,11 +56,11 @@ lmp现有许多用于监控linux网络协议栈相关信息的小工具,但这
### 1.3 组织结构
- doc/:
- implement.md:详细描述本项目的实现细节
- data/:
- data/:文件夹存放打印的日志信息
- connects.log:符合Prometheus格式的连接信息
- err.log:符合Prometheus格式的错误包信息
- packets.log:符合Prometheus格式的包信息
- udp.loh:符合Prometheus格式的udp包信息
- udp.loh:符合Prometheus格式的udp包信息
- visual.py:暴露metrics接口给Prometheus,输出data文件夹下的所有信息
- netwatcher.c :对bpf.c文件中记录的信息进行输出
- netwatcher.bpf.c:封装内核探针点。
Expand All @@ -62,7 +69,7 @@ lmp现有许多用于监控linux网络协议栈相关信息的小工具,但这
- packet.bpf.h :网络数据包的处理、时间戳的记录、数据包信息的提取等指标具体处理逻辑。
- netfilter.bpf.h:处理netfilter时延的具体逻辑,`submit_nf_time`函数将时延信息提交到用户态,`store_nf_time`函数存储经过每个`HOOK`点的时延。
- drop.bpf.h :数据包丢弃原因的具体处理逻辑。
- dropreason.bpf.h :skb_drop_reason定义77种丢包原因。
- dropreason.h :skb_drop_reason定义77种丢包原因。
- icmp.bpf.h: icmp时延具体实现细节。
- comm.bpf.h :辅助函数、宏、BPF映射、以及内核中使用到的结构体。

Expand All @@ -89,16 +96,15 @@ sudo make test # 测试
`netwatcher`通过一系列命令参数来控制其具体行为:

```bash
Usage: [OPTION...]
Watch tcp/ip in network subsystem

Usage: netwatcher [OPTION...]
Watch tcp/ip in network subsystem
-a, --all set to trace CLOSED connection
-d, --dport=DPORT trace this destination port only
-e, --err set to trace TCP error packets
-i, --http set to trace http info
-I, --icmptime set to trace layer time of icmp
-k, --drop_reason trace kfree
-L, --timeload analysis time load
-L, --timeload analysis time load
-n, --net_filter trace ipv4 packget filter
-r, --retrans set to trace extra retrans info
-s, --sport=SPORT trace this source port only
Expand All @@ -108,10 +114,7 @@ Watch tcp/ip in network subsystem
-u, --udp trace the udp message
-x, --extra set to trace extra conn info
-?, --help Give this help list
--usage Give a short usage message

Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.
```
- 参数`-d`,`-s`用于指定监控某个源端口/目的端口
- 指定参数`-a`会保留已CLOSED的TCP连接信息
Expand Down Expand Up @@ -305,5 +308,4 @@ saddr daddr sprot dprot udp_time rx len
python visual.py
```
## 四、代码实现细节

- 详细实现细节见`doc/implement.md`
5 changes: 2 additions & 3 deletions eBPF_Supermarket/Network_Subsystem/net_watcher/common.bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ const volatile int all_conn = 0, err_packet = 0, extra_conn_info = 0,
packet->ack = pkt_tuple.ack; \
packet->seq = pkt_tuple.seq;

#define MAX(a, b) ((a) > (b) ? (a) : (b))

/* help macro end */

/* help functions */
Expand Down Expand Up @@ -385,7 +387,4 @@ void get_pkt_tuple_v6(struct packet_tuple *pkt_tuple,
pkt_tuple->tran_flag = 1; // tcp包
}
/* help functions end */



#endif
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ad6c1c3

Please sign in to comment.