开源工具学习记录之流程梳理
近期对腾讯的的开源项目: 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.c与kprobe_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

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



