• bcc和ftrace追踪内核网络模块实战


    什么是bcc和ftrace

    bcc是ebpf技术的一个前端,集成了ebpf/kprobe/uprobe的很多东西,对一些常见功能做了整合。而ebpf是近几年出现的比较热门的一项技术,它的前身是bpf(Berkeley Packet Filter),也就是我们tcpdump使用的过滤数据包的技术。ebpf对bpf进行了扩展,它能在内核中运行自定义程序, 而无需修改内核源码或者加载内核模块。

    ftrace有两种概念,一种是广义的ftrace框架,一种是狭义的追踪技术。广义的ftrace框架包含了krpobe trace event很多追踪技术,而狭义的ftrace就是我们今天的重点,我们会对其中一种tracer的使用做着重介绍。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xXsk1Lcm-1662108017055)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220901180624519.png)]

    tracer的概念可以直译为追踪器,可以理解为内核提供的一些追踪技术,比如有function tracer,function graph tracer等等,我们今天着重介绍function graph tracer,因为function tracer的很多功能用bcc就可以实现,而function graph却是bcc没有的功能。

    function graph tracer的效果如图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQTITu8Z-1662108017058)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902155700599.png)]

    ​ bcc 效果如图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-64CqUnQC-1662108017059)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902105610168.png)]

    怎样使用bcc ftrace

    安装

    bcc使用yum install bcc -y就能安装。ftrace不用安装,是内核提供的,只要开启了CONFIG_DYNAMIC_FTRACE就行,而这个选项我们是默认开启的。

    内核版本越高,bcc和ftrace能使用的功能就越多,也就是说,在低内核版本上,可能一些功能并没有集成进去也就不能使用。

    bcc安装完成后如图所示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4J6vHH23-1662108017061)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902102329193.png)]

    而ftrace需要手动开启内核一些选项

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PtsBxO76-1662108017063)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902102507564.png)]

    trace语法:

    ​ name或者p:name:对内核函数name()进行插桩

    ​ r::name: 对内核函数name()的返回值进行插桩

    ​ lib:name或者p:lib:name: 对用户态lib库中的函数name()进行插桩

    ​ r:lib:name:对用户态lib库中的函数name()进行插桩

    ​ path::name: 对位于path路径下的用户态函数name()进行插桩

    ​ r:path:name: 对位于path路径下的用户态函数name()的返回值进行插桩

    ​ t:system:name: 对名为system:name的跟踪点进行插桩

    ​ u:lib:name: 对lib库中名为name的USDT探针进行插桩

    ​ *: 用来匹配任意字符的通配符。-r选项允许使用正则表达式

    详细可见《bpf之巅——洞悉linux系统和应用性能》

    开发过程中的一个实际案例

    环境

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FGLXPUvF-1662108017065)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902112844237.png)]

    ifdown测试

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-96yfbKIW-1662108017067)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902112511721.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cjmkNjeZ-1662108017068)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902112520454.png)]

    我们可以看到,client在down掉网卡后,返回值还是正常的,但是server接受不到数据了

    ip link set down 测试

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gg2eYJ5J-1662108017070)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902113550846.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Gcb1GJc3-1662108017072)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902113609816.png)]

    这里有两个问题:

    1. 为什么ifdown之后,client还是可以发送成功?

    2. 为什么ifdown之后,server收不到消息,而ip link set down测试中server可以接收到消息

    bcc trace 追踪__sk_dst_check()

    ip link set down

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r1L51uLv-1662108017073)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902114715357.png)]

    ifdown

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z05Oqbrm-1662108017074)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902115434975.png)]

    ftrace追踪ip_route_output_ports()

    Ip link set down后,路由查找的过程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6vXtUToz-1662108017075)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902163500641.png)]

    ifdown后,路由查找的过程

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApDU7pRb-1662108017076)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902163448592.png)]

    对比两种输出的不同和内核代码,可以发现,ifdown后,会直接查找设备失败,进而直接返回给上层(tcp)-EHOSTUNREAD。而ip link down后,会查找设备成功,进而查找路由成功。

    再对比内核代码,发现在fib_table_lookup() 中,有以下逻辑:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dVQkTjgG-1662108017078)(C:\Users\MyPC\AppData\Roaming\Typora\typora-user-images\image-20220902163531091.png)]

    然后发现/proc/sys/net/ipv4/conf/ens40/ignore_routes_with_linkdown这个选项,控制了link down后,原来路由是否还会生效,而这个值默认是0,也就是不忽略原来的路由项。

    https://blog.csdn.net/sinat_20184565/article/details/106182579

    至此,终于真相大白,我们可以来解答我们的两个疑问了

    1. 为什么ifdown之后,client还是可以发送成功?

      1. 因为ip层向tcp返回了EHOSTUNREACH,而tcp进行了重试,再次收到EHOSTUNREACH,再达到重试/proc/sys/net/ipv4/tcp_retries2这么多次之前,tcp是不会返回失败的。
    2. 为什么ifdown之后,server收不到消息,而ip link set down测试中server可以接收到消息。

      1. 因为ifdown后,设备被删除了,直接向tcp层返回了EHOSTUNREACH,而下一次重试又会失败。所以消息发不出去,server收不到消息
      2. 而ip link set down后,设备没有被删除,而/proc/sys/net/ipv4/conf/ens40/ignore_routes_with_linkdown默认为0,也就是不忽略已经down掉的Link的路由,所以会查找路由成功,进而发送成功,server接收成功。

    脚本

    #!/bin/bash
    
    if [ $# != 2 ]; then
        echo "USAGE: $0 func_name command"
        echo "e.g: $0 yrfs_ops_write \"echo aa > /mnt/yrfs/aa\""
        exit -1
    fi
    
    num_args="$#"
    cmd="${@: -1}"
    func_name="$1"
    
    echo $cmd
    
    
    debugfs=/sys/kernel/debug
    
    echo nop > $debugfs/tracing/current_tracer
    echo 0 > $debugfs/tracing/tracing_on
    
    # echo $$ > $debugfs/tracing/set_ftrace_pid
    echo function_graph > $debugfs/tracing/current_tracer
    echo $func_name > $debugfs/tracing/set_graph_function
    
    # options
    echo 1 > $debugfs/tracing/options/funcgraph-tail
    echo 1 > $debugfs/tracing/options/funcgraph-proc
    
    echo 1 > $debugfs/tracing/tracing_on
    eval $cmd
    cp $debugfs/tracing/trace ~/trace_ret
    
    echo nop > $debugfs/tracing/current_tracer
    echo 0 > $debugfs/tracing/tracing_on
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    
    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    六大排序实现
    Adult数据集预处理
    嵌入式&QT&Git面试题
    cmdline(二):uboot cmdline怎么传?&&cmdline kernel怎么用?
    代码规范整理
    Arthas 介绍以及入门教程
    GDB调试CoreDump文件
    4_使用预训练模型 微调训练CIFAR10
    【秋招】最全算法岗面试,吃透offer拿到手软!
    ICPC 2023 网络赛 j (线性dp
  • 原文地址:https://blog.csdn.net/sjc2870/article/details/126666335