[译] 网络包内核路径跟踪:2 Perf

栏目: 服务器 · 发布时间: 7年前

内容简介:译者按:本文翻译自一篇英文博客这篇文章只会非常简单地使用perf做内核跟踪。我的环境基于Ubuntu 17.04 (Zesty):

译者按:本文翻译自一篇英文博客 Tracing a packet’s journey using Linux tracepoints, perf and eBPF 。由于原文篇幅较长,我将其分成了三篇,并添加了适当的标题。 本文不会100%逐词逐句翻译,那样的翻译太过生硬,看看《TCP/IP详解》中文版就知道了。 例如,有多少人会在讨论网络问题的时候说 “插口” 而不是 “socket” ?在技术领域,过 度翻译反而会带来交流障碍。 如果能看懂英文,我强烈建议你阅读原文,或者和本文对照看。

这篇文章只会非常简单地使用perf做内核跟踪。

1 安装perf

我的环境基于Ubuntu 17.04 (Zesty):

$ sudo apt install linux-tools-generic
$ perf # test perf

2 测试环境

我们将使用4个IP,其中2个为外部可路由网段( 192.168 ):

  1. localhost,IP 127.0.0.1
  2. 一个干净的容器,IP 172.17.0.2
  3. 我的手机,通过USB连接,IP 192.168.42.129
  4. 我的手机,通过WiFi连接,IP 192.168.43.1

3 初体验:跟踪ping包

perf traceperf 子命令,能够跟踪packet路径,默认输出类似于 strace (头信息少很多)。

跟踪ping向 172.17.0.2 容器的包,这里我们只关心 net 事件,忽略系统调用信息:

$ sudo perf trace --no-syscalls --event 'net:*' ping 172.17.0.2 -c1 > /dev/null
     0.000 net:net_dev_queue:dev=docker0 skbaddr=0xffff96d481988700 len=98)
     0.008 net:net_dev_start_xmit:dev=docker0 queue_mapping=0 skbaddr=0xffff96d481988700 vlan_tagged=0 vlan_proto=0x0000 vlan_tci=0x0000 protocol=0x0800 ip_summed=0 len=98 data_len=0 network_offset=14 transport_offset_valid=1 transport_offset=34 tx_flags=0 gso_size=0 gso_segs=0 gso_type=0)
     0.014 net:net_dev_queue:dev=veth79215ff skbaddr=0xffff96d481988700 len=98)
     0.016 net:net_dev_start_xmit:dev=veth79215ff queue_mapping=0 skbaddr=0xffff96d481988700 vlan_tagged=0 vlan_proto=0x0000 vlan_tci=0x0000 protocol=0x0800 ip_summed=0 len=98 data_len=0 network_offset=14 transport_offset_valid=1 transport_offset=34 tx_flags=0 gso_size=0 gso_segs=0 gso_type=0)
     0.020 net:netif_rx:dev=eth0 skbaddr=0xffff96d481988700 len=84)
     0.022 net:net_dev_xmit:dev=veth79215ff skbaddr=0xffff96d481988700 len=98 rc=0)
     0.024 net:net_dev_xmit:dev=docker0 skbaddr=0xffff96d481988700 len=98 rc=0)
     0.027 net:netif_receive_skb:dev=eth0 skbaddr=0xffff96d481988700 len=84)
     0.044 net:net_dev_queue:dev=eth0 skbaddr=0xffff96d481988b00 len=98)
     0.046 net:net_dev_start_xmit:dev=eth0 queue_mapping=0 skbaddr=0xffff96d481988b00 vlan_tagged=0 vlan_proto=0x0000 vlan_tci=0x0000 protocol=0x0800 ip_summed=0 len=98 data_len=0 network_offset=14 transport_offset_valid=1 transport_offset=34 tx_flags=0 gso_size=0 gso_segs=0 gso_type=0)
     0.048 net:netif_rx:dev=veth79215ff skbaddr=0xffff96d481988b00 len=84)
     0.050 net:net_dev_xmit:dev=eth0 skbaddr=0xffff96d481988b00 len=98 rc=0)
     0.053 net:netif_receive_skb:dev=veth79215ff skbaddr=0xffff96d481988b00 len=84)
     0.060 net:netif_receive_skb_entry:dev=docker0 napi_id=0x3 queue_mapping=0 skbaddr=0xffff96d481988b00 vlan_tagged=0 vlan_proto=0x0000 vlan_tci=0x0000 protocol=0x0800 ip_summed=2 hash=0x00000000 l4_hash=0 len=84 data_len=0 truesize=768 mac_header_valid=1 mac_header=-14 nr_frags=0 gso_size=0 gso_type=0)
     0.061 net:netif_receive_skb:dev=docker0 skbaddr=0xffff96d481988b00 len=84)

只保留事件名和 skbaddr ,看起来清晰很多:

net_dev_queue           dev=docker0     skbaddr=0xffff96d481988700
net_dev_start_xmit      dev=docker0     skbaddr=0xffff96d481988700
net_dev_queue           dev=veth79215ff skbaddr=0xffff96d481988700
net_dev_start_xmit      dev=veth79215ff skbaddr=0xffff96d481988700
netif_rx                dev=eth0        skbaddr=0xffff96d481988700
net_dev_xmit            dev=veth79215ff skbaddr=0xffff96d481988700
net_dev_xmit            dev=docker0     skbaddr=0xffff96d481988700
netif_receive_skb       dev=eth0        skbaddr=0xffff96d481988700

net_dev_queue           dev=eth0        skbaddr=0xffff96d481988b00
net_dev_start_xmit      dev=eth0        skbaddr=0xffff96d481988b00
netif_rx                dev=veth79215ff skbaddr=0xffff96d481988b00
net_dev_xmit            dev=eth0        skbaddr=0xffff96d481988b00
netif_receive_skb       dev=veth79215ff skbaddr=0xffff96d481988b00
netif_receive_skb_entry dev=docker0     skbaddr=0xffff96d481988b00
netif_receive_skb       dev=docker0     skbaddr=0xffff96d481988b00

这里有很多信息。

首先注意, skbaddr 在中间变了( 0xffff96d481988700 -> 0xffff96d481988b00 )。 变的这里,就是生成了ICMP echo reply包,并作为应答包发送的地方。接下来的时间,这 个包的skbaddr保持不变,说明没有copy。copy非常耗时。

其次,我们可以清楚地看到 packet在内核的传输路径 :首先通过 docker 0网桥,然后veth pair的 宿主机端( veth79215ff ),最后是veth pair的容器端(容器里的 eth0 );接下来是返回路径。

至此,虽然我们还没有看到网络命名空间,但已经得到了一个不错的全局视图。

4 进阶:选择跟踪点

上面的信息有一些杂,还有很多重复。我们可以选择几个最合适的跟踪点,使得输出看起来 更清爽。要查看所有可用的网络跟踪点,可以执行perf list:

$ sudo perf list 'net:*'

这个命令会列出tracepoint列表,名字类似于 net:netif_rx 。冒号前面是事件类型,后面是事件名称。

这里我选择了4个:

net_dev_queue
netif_receive_skb_entry
netif_rx
napi_gro_receive_entry

效果:

$ sudo perf trace --no-syscalls           \
    --event 'net:net_dev_queue'           \
    --event 'net:netif_receive_skb_entry' \
    --event 'net:netif_rx'                \
    --event 'net:napi_gro_receive_entry'  \
    ping 172.17.0.2 -c1 > /dev/null
       0.000 net:net_dev_queue:dev=docker0 skbaddr=0xffff8e847720a900 len=98)
       0.010 net:net_dev_queue:dev=veth7781d5c skbaddr=0xffff8e847720a900 len=98)
       0.014 net:netif_rx:dev=eth0 skbaddr=0xffff8e847720a900 len=84)
       0.034 net:net_dev_queue:dev=eth0 skbaddr=0xffff8e849cb8cd00 len=98)
       0.036 net:netif_rx:dev=veth7781d5c skbaddr=0xffff8e849cb8cd00 len=84)
       0.045 net:netif_receive_skb_entry:dev=docker0 napi_id=0x1 queue_mapping=0

漂亮!

« [译] 网络包内核路径跟踪:1 开篇 [译] 网络包内核路径跟踪:3 eBPF »


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言点滴

C语言点滴

赵岩 / 人民邮电出版社 / 2013-10-1 / 45.00元

C语言兼具高级语言和汇编语言的特点,学习起来难度较大,令不少初学者望而生畏。同时,C语言又是一门应用非常广泛的编程语言,在实际应用中如何根据不同的应用场景高效地使用C语言,也是大家非常感兴趣的话题。  《C语言点滴》精心选取C语言一些必备知识,这也是初学者容易搞不清楚、犯错误的知识点,进行深入地分析和介绍,以期帮助读者清除C语言学习之路上的“绊脚石”,降低初学入门的难度,培养继续深入的兴趣。  全......一起来看看 《C语言点滴》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具