Nettrace eBPF程序自动挂载方式探究

开源工具学习记录之流程梳理

近期对腾讯的的开源项目: nettrace(网络故障分析工具) ,进行源码学习。
开源仓库:Nettrace开源仓库
开源工具实现注释:nettrace学习记录

Nettrace 自动挂载方式探究

在nettrace中,构建了一个跟踪点链表树,树中包含不同的跟踪组,每个跟踪组中包含实现当前功能的所有跟踪点,这是实现跟踪点自动挂载的基础。nettrace工具提供了不同模式的数据采集方法,会根据参数来判断当前处于何种跟踪模式,不同的跟踪模式通过不同的跟踪点实现数据采集。那么如何根据不同的跟踪模式,自动加载该跟踪模式下对应的挂载点是一个值得深入探讨的问题,这也是数据采集模块实现的重点。

在这里插入图片描述

1.跟踪组及跟踪链表的构建

在nettrace入口函数main()中,第一步便是构建跟踪点树

int main(int argc, char *argv[])
{
   
   
	/*1.初始化跟踪组*/
	init_trace_group();
	...
}

该函数在trace_group.c中,接下来将介绍trace_group.c文件;

在项目编译过程中,会通过gen_trace.py脚本去解析trace.yaml文件,生成trace_group.ckprobe_trace.h文件,前者定义了所有的挂载点以及跟踪点链表, 并组建成了跟踪点树, 后者对所有的挂载点定义了其索引;

                               nettrace.c ----------------- nettrace
                                  trace.c                       |
                                    xxxxx                       |
                                                                |
                                                                |
                            trace_group.c                       ||
trace.yaml -- gen_trace.py                                      ||
                            kprobe_trace.h                      ||
                                            kprobe.o → kprobe.skel.h
                                          ╱
                                  kprobe.c

trace_group.c文件中依靠init_trace_group()函数初始化了跟踪组,将项目所涉及的所有跟踪点构建成树的形式;

trace_group.c文件中定义的跟踪组、跟踪点、跟踪链表以及对应的数据处理规则;

trace_group_t group_link = {
   
   
	.name = "link",
	.desc = "link layer (L2) of the network stack",
	.children = LIST_HEAD_INIT(group_link.children),
	.traces = LIST_HEAD_INIT(group_link.traces),
	.list = LIST_HEAD_INIT(group_link.list),
};
trace_t trace_dev_gro_receive = {
   
   
	.desc = "",
	.type = TRACE_FUNCTION,
	.analyzer = &ANALYZER(default),
	.is_backup = false,
	.probe = false,
	.name = "dev_gro_receive",
	.skb = 2,
	.custom = false,
	.def = true,
	.index = INDEX_dev_gro_receive,
	.prog = "__trace_dev_gro_receive",
	.parent = &group_link_in,
	.rules = LIST_HEAD_INIT(trace_dev_gro_receive.rules),
};
trace_list_t trace_dev_gro_receive_list = {
   
   
	.trace = &trace_dev_gro_receive,
	.list = LIST_HEAD_INIT(trace_dev_gro_receive_list.list)
};
rule_t rule_trace_dev_gro_receive_0 = {
   
   	.level = RULE_ERROR,
	.expected = 4,c
	.type = RULE_RETURN_EQ,
	.msg = PFMT_ERROR"packet is dropped by GRO"PFMT_END,
};

trace_group.c文件中初始化跟踪树的函数;

void init_trace_group()
{
   
   
	list_add_tail(&group_link.list, &root_group.children);
	list_add_tail(&group_link_in.list, &group_link.children);
	list_add_tail(&trace_napi_gro_receive_entry_list.list, &group_link_in.traces);
	all_traces[INDEX_napi_gro_receive_entry] = &trace_napi_gro_receive_entry;
	...
}

2.跟踪点自动挂载的实现

将跟踪点树构建完成后,需要根据不同的跟踪模式去挂载对应的跟踪点,nettrace的实现方式如下:

在这里插入图片描述

  • 首先会在环境准备阶段,根据参数解析出用户设定的模式并将该模式作为跟踪模式;
  • 其次会根据设定好的跟踪模式,去将该跟踪模式所对应的挂载点进行标记;
  • 在将不同的跟踪模式对应的跟踪点进行标记后,会遍历跟踪树中所有的跟踪点,检查当前跟踪点在当前系统下是否无效(分为tp,kprobe两种),并将其初始化;
  • 在对当前跟踪模式下所有有效跟踪点启用后,会查看这些有效跟踪点中是否存在冗余现象,即启用了两个功能相似的跟踪点;nettrace针对具有相同跟踪功能的跟踪点,设置了备用链,即一条备用链上的所有跟踪点都是功能相似的,类似于足球赛中的替补选手,仅启用备用链中第一个有效的跟踪点;
  • 最后,会在加载附加bpf程序时,根据挂载点的状态,选择手动加载或自动加载(有的跟踪点需要手动加载);

在这里插入图片描述

2.1 跟踪模式的设定与挂载点的绑定

2.1.1 跟踪模式的确定

trace_prepare()->trace_prepare_args()函数中,通过参数对跟踪模式进行设置,并标记该跟踪模式所对应的跟踪点;

static int trace_prepare_args()
{
   
   
	...
	/*定义七种跟踪模式*/
#define ASSIGN_MODE(name, __mode) do {
     
     			\
	if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值