专栏首页Serverless+使用 BPF 记录 TCP 重传和丢包记录
原创

使用 BPF 记录 TCP 重传和丢包记录

背景

在云函数的日常运营中,经常有用户提出要求协助排查网络问题。一般的手段就是使用 tcpdump 抓包,但是部署抓包往往是在问题发生之后,而且抓包后复现的时机也不确定,往往费时费力。本文讲述使用 BPF 记录 TCP 的重传和丢包记录,作为定位网络问题的一种辅助手段。

在 BPF 出现之前

BPF 出现之前,在 Linux 上我们也是可以解决这个问题的,只不过比较繁琐,需要对内核、调试器、编译器等许多基础知识有较深理解,参见这里

TCP 重传为例,我们使用 perf 工具来查找跟踪的点位:

$ sudo perf list 'tcp:*'

List of pre-defined events (to be used in -e):

  tcp:tcp_destroy_sock                               [Tracepoint event]
  tcp:tcp_probe                                      [Tracepoint event]
  tcp:tcp_rcv_space_adjust                           [Tracepoint event]
  tcp:tcp_receive_reset                              [Tracepoint event]
  tcp:tcp_retransmit_skb                             [Tracepoint event]
  tcp:tcp_retransmit_synack                          [Tracepoint event]
  tcp:tcp_send_reset                                 [Tracepoint event]


Metric Groups:

对于 TCP 重传,显然 tcp_retransmit_skb 是一个合适的跟踪点位。让我们来看看这个函数在内核代码中的签名:

int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs);

struct sock 的定义在这里,它包含了我们所需要的信息。这是一个庞大且复杂的结构体,而且对于 kprobe 来说,我们只能使用寄存器以及偏移来输出其值。

要知道这个结构体中每个字段的真实偏移,我们需要内核的符号表,使用 GDB 来确定其值:

$ sudo apt install linux-image-unsigned-5.8.0-37-generic-dbgsym
$ gdb /usr/lib/debug/boot/vmlinux-5.8.0-37-generic
(gdb) ptype struct sock
...
(gdb) print (int)&((struct sock*)0)->__sk_common.skc_dport
$1 = 12

除此之外,我们还需要了解 X86_64调用约定,诸如函数调用的第一个参数使用 di 寄存器传递等。

有了这些背景知识后,我们可以使用 kprobe 来达成这一目标,记录 TCP 重传的例子如下:

$ echo 'p:kprobes/tcp_retransmit tcp_retransmit_skb port=+12(%di):u16 dst=+0(%di):u32 state=+18(%di):u8' >> /sys/kernel/debug/tracing/kprobe_events
$ echo 1 > /sys/kernel/debug/tracing/events/kprobes/tcp_retransmit/enable

这个例子不仅晦涩难懂,而且不易开发及调试,好在现在我们有了 BPF

BPF 横空出世

BPF 是一项革命性技术,它能在内核中运行沙箱程序, 而无需修改内核源码或者加载内核模块。

对于上面的例子,一个等价的 BPF 程序如下:

#include <uapi/linux/ptrace.h>
#include <net/sock.h>

int log_tcp_retransmit(struct pt_regs *ctx, struct sock *sk) {
    u16 port = sk->__sk_common.skc_dport;
    u32 daddr = sk->__sk_common.skc_daddr;
    u8 state = sk->__sk_common.skc_state;
    bpf_trace_printk("tcp_retransmit port=%d dst=%d state=%d\n", port, daddr, state);
    return 0;
}

使用 C 编写,不需要理解 ABI 等细节,而且方便调试。你可以在这里找到完整的代码。对于 TCP 重传,也是一样的道理。

重传的日志记录在 /sys/kernel/debug/tracing/trace,下面是一些真实的记录:

$ sudo cat /sys/kernel/debug/tracing/trace
# tracer: nop
#
# entries-in-buffer/entries-written: 103/103   #P:1
#
#                                _-----=> irqs-off
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth
#                              ||| /     delay
#           TASK-PID     CPU#  ||||   TIMESTAMP  FUNCTION
#              | |         |   ||||      |         |
...
          <idle>-0       [000] ..s. 2621728.977959: 0: tcp_retransmit port=37897 dst=831376843 state=1
           <...>-3202753 [000] ..s. 2622104.077378: 0: tcp_retransmit port=37897 dst=831376843 state=1
...

转换一下格式,可以看到重传的目的地址及端口等信息:

2621728.977959 2021-03-05 19:48:18.959403       tcp_retransmit  203.205.141.49           2452   TCP_ESTABLISHED
2622104.077378 2021-03-05 19:54:34.058822       tcp_retransmit  203.205.141.49           2452   TCP_ESTABLISHED

结论

本文讲述使用 BPF 带来的可观测性能力,获取 TCP 的重传及丢包记录,作为辅助定位网络问题的手段。与传统的 kprobe 方式相比, BPF 带来的可编程性极大地提升了开发效率,既没有增加系统的复杂度,也不会牺牲执行效率和安全性。

原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

登录 后参与评论
0 条评论

相关文章

  • TCP为什么可靠?

    上一篇记录了TCP三次握手四次挥手的细节以及为什么会在TIME_WAIT状态停留时间为2MSL。

    Liusy
  • TCP重传分析

    TCP协议是一种面向连接的可靠的传输层协议,它保证了数据的可靠传输。既然是可靠的传输,那对于丢包情况肯定有一套重传的机制。

    ivanlwyan
  • 日均超30亿分钟!腾讯实时音视频技术低延时的秘密

    新冠肺炎疫情的突发,让全球远程办公、在线教育、在线协作、远程面试等领域需求急剧增加,这也让支撑远程通信的实时音视频技术成为焦点。由腾讯实时音视频(Tencent...

    smiling
  • ​TCP 拥塞控制详解

    作者:engleliu,腾讯 PCG 开发工程师 本文主要介绍 TCP 拥塞控制算法,内容多来自网上各个大佬的博客及《TCP/IP 详解》一书,在此基础上进行...

    腾讯技术工程官方号
  • 日均超30亿分钟!腾讯实时音视频技术低延时的秘密

    新冠肺炎疫情的突发,让全球远程办公、在线教育、在线协作、远程面试等领域需求急剧增加,这也让支撑远程通信的实时音视频技术成为焦点。由 腾讯实时音视频(Tence...

    腾讯即时通信IM
  • (二十一)TCPIP面试宝典-进入大厂必备总结(下)

    TCP 作为传输层的协议,是一个IT工程师素养的体现,也是面试中经常被问到的知识点。在此,我将 TCP 核心的一些问题梳理了一下,希望能帮到各位。

    用户3479834
  • 网络协议 9 - TCP协议(下):聪明反被聪明误

        上次了解了 TCP 建立连接与断开连接的过程,我们发现,TCP 会通过各种“套路”来保证传输数据的安全。除此之外,我们还大概了解了 TCP 包头格式所对...

    北国风光
  • KCP 协议:为流速和低延时设计的协议丨音视频基础

    (本文基本逻辑:KCP 协议简介 → KCP 协议特性 → KCP 协议基本使用方式 → KCP 协议最佳实践)

    关键帧
  • 不为人知的网络编程(七):如何让不可靠的UDP变的可靠?

    最近和很多实时音视频领域的朋友交流中都有谈论到 RUDP(Reliable UDP),这其实是个老生常谈的问题,RUDP 在很多著名的项目上都有使用,例如 Go...

    JackJiang
  • 28 张图,一次性说清楚 TCP协议

    做IT相关的工作,肯定都离不开网络,网络中最重要的协议是TCP。无论是实际工作还是笔试面试,你看哪里能少得了TCP?

    星哥玩云
  • 什么是TCP?看这些图你就知道了

    做IT相关的工作,肯定都离不开网络,网络中最重要的协议是TCP。无论是实际工作还是笔试面试,你看哪里能少得了TCP?

    黄啊码
  • 这篇TCP神总结,请务必收下!

    考虑最简单的情况:两台主机之间的通信。这个时候只需要一条网线把两者连起来,规定好彼此的硬件接口,如都用USB、电压10v、频率2.4GHz等,这一层就是物理层,...

    用户8611941
  • 28 张图,搞懂TCP

    文章来源:网络技术平台 做IT相关的工作,肯定都离不开网络,网络中最重要的协议是TCP。无论是实际工作还是笔试面试,你看哪里能少得了TCP? 考虑最简单的情况:...

    SDNLAB
  • RUDP传输那些事儿

    最近和很多实时音视频领域的朋友交流中都有谈论到RUDP(Reliable UDP),这其实是个老生常谈的问题,RUDP在很多著名的项目上都有使用,例如googl...

    LiveVideoStack
  • 深入解析常见三次握手异常

    在后端接口性能指标中一类重要的指标就是接口耗时。具体包括平均响应时间 TP90、TP99 耗时值等。这些值越低越好,一般来说是几毫秒,或者是几十毫秒。如果响应时...

    开发内功修炼
  • UDP 协议的那点事儿

    最近在回顾计算机网络的知识,以前上课没有认真学,只记住了几个高大上的术语,所以趁着这次回顾,把学到的知识用博客的形式记录下来,一来加深自己的印象,二来希望让你对...

    乔戈里
  • TCP/IP协议之传输层:TCP/UDP协议详解(一)

    在TCP/IP网络体系结构中,TCP(传输控制协议,Transport Controll Protocol、UDP(用户数据报协议,User Data Prot...

    用户7557625
  • 面试必考 | TCP 协议(第三弹)—流量控制和拥塞控制

    MMS(Maximum Segment Size):TCP一次传输发送的最大数据段长度。

    用户3946442
  • 使用 BPF 自定义安全组

    上一篇文章阅读量比较多,看起来网络的主题比较受欢迎。这一篇文章我们继续探索 BPF 在网络领域的应用:使用 BPF 来实现安全组。

    ritchiechen

扫码关注腾讯云开发者

领取腾讯云代金券