5

我想在 Linux 内核中找到一个 UDP 数据包的路径。为此,我想阅读一些文档(到目前为止我有这个,它是针对 TCP 的),然后在相关的内核函数中有一些 printk 语句来确认这一点。我将通过重新编译内核代码来做到这一点。

这是解决问题的方法吗?你有什么建议/参考吗?

4

4 回答 4

7

具体回答您的问题,要了解 IPv4 的 UDP 处理,您可以使用 ftrace,如下所示:

在入口(接收方):

 96882  2)               |                                ip_local_deliver_finish() {
 96883  2)   0.069 us    |                                  raw_local_deliver();
 96884  2)               |                                  udp_rcv() {
 96885  2)               |                                    __udp4_lib_rcv() {
 96886  2)   0.087 us    |                                      __udp4_lib_lookup();
 96887  2)               |                                      __skb_checksum_complete_head() {
 96888  2)               |                                        skb_checksum() {
 96889  2)               |                                          __skb_checksum() {
 96890  2)               |                                            csum_partial() {
 96891  2)   0.161 us    |                                              do_csum();
 96892  2)   0.536 us    |                                            }
 96893  2)               |                                            csum_partial() {
 96894  2)   0.167 us    |                                              do_csum();
 96895  2)   0.523 us    |                                            }
 96896  2)               |                                            csum_partial() {
 96897  2)   0.158 us    |                                              do_csum();
 96898  2)   0.513 us    |                                            }
 96899  2)               |                                            csum_partial() {
 96900  2)   0.154 us    |                                              do_csum();
 96901  2)   0.502 us    |                                            }
 96902  2)               |                                            csum_partial() {
 96903  2)   0.165 us    |                                              do_csum();
 96904  2)   0.516 us    |                                            }
 96905  2)               |                                            csum_partial() {
 96906  2)   0.138 us    |                                              do_csum();
 96907  2)   0.506 us    |                                            }
 96908  2)   5.462 us    |                                          }
 96909  2)   5.840 us    |                                        }
 96910  2)   6.204 us    |                                      }

跟踪的另一部分显示如下:

 98212  2)               |                              ip_rcv() {
 98213  2)               |                                ip_rcv_finish() {
 98214  2)   0.109 us    |                                  udp_v4_early_demux();
 98215  2)               |                                  ip_route_input_noref() {
 98216  2)               |                                    fib_table_lookup() {
 98217  2)   0.079 us    |                                      check_leaf.isra.8();
 98218  2)   0.492 us    |                                    }

对于网络代码的出口,下面提取了一些片段:

 4)   0.547 us    |  udp_poll();
 4)               |  udp_sendmsg() {
 4)               |    udp_send_skb() {
 4)   0.387 us    |      udp_error [nf_conntrack]();
 4)   0.185 us    |      udp_pkt_to_tuple [nf_conntrack]();
 4)   0.160 us    |      udp_invert_tuple [nf_conntrack]();
 4)   0.151 us    |      udp_get_timeouts [nf_conntrack]();
 4)   0.145 us    |      udp_new [nf_conntrack]();
 4)   0.160 us    |      udp_get_timeouts [nf_conntrack]();
 4)   0.261 us    |      udp_packet [nf_conntrack]();
 4)   0.181 us    |      udp_invert_tuple [nf_conntrack]();
 4)   0.195 us    |      udp_invert_tuple [nf_conntrack]();
 4)   0.170 us    |      udp_invert_tuple [nf_conntrack]();
 4)   0.175 us    |      udp_invert_tuple [nf_conntrack]();
 4)               |      udp_rcv() {
 4) + 15.021 us   |        udp_queue_rcv_skb();
 4) + 18.829 us   |      }
 4) + 82.100 us   |    }
 4) + 92.415 us   |  }
 4)               |  udp_sendmsg() {
 4)               |    udp_send_skb() {
 4)   0.226 us    |      udp_error [nf_conntrack]();
 4)   0.150 us    |      udp_pkt_to_tuple [nf_conntrack]();
 4)   0.146 us    |      udp_get_timeouts [nf_conntrack]();
 4)   1.098 us    |      udp_packet [nf_conntrack]();
 4)               |      udp_rcv() {
 4)   1.314 us    |        udp_queue_rcv_skb();
 4)   3.282 us    |      }
 4) + 20.646 us   |    }

上面在 ftrace 中称为函数图:

如何使 ftrace function_graph 跟踪器可以使用 linux 内核函数?

我用于跟踪 udp 的 bashscript 如下(以 root 身份运行):

#!/bin/bash

mkdir /debug
mount -t debugfs nodev /debug
mount -t debugfs nodev /sys/kernel/debug
echo udp_* >/debug/tracing/set_ftrace_filter
echo function_graph >/debug/tracing/current_tracer
echo 1 >/debug/tracing/tracing_on
sleep 20
echo 0 >/debug/tracing/tracing_on
cat /debug/tracing/trace > /tmp/tracing.out$$

现在输出文件位于 /tmp/tracing.out 内,其中是 shell 脚本进程。20 秒的目的是允许用户空间活动发生——此时只是开始大量的 UDP 活动。您还可以从上面的脚本中删除“ echo udp_* >/debug/tracing/set_ftrace_filter ”,因为默认是跟踪所有内容。

于 2013-01-20T05:56:03.257 回答
4

linux 网络堆栈是内核的一大块,你需要花一些时间研究它。我认为这本书可能会有所帮助(专注于旧内核 2.4 和 2.6,但最新内核 3.x 的逻辑保持不变):

了解 Linux 网络内部结构

Linux 网络架构——Linux 内核中网络协议的设计与实现

您还可以查看以下链接:

http://e-university.wisdomjobs.com/linux/chapter-189-277/sending-the-data-from-the-socket-through-udp-and-tcp.html

http://www.linuxfoundation.org/collaborate/workgroups/networking/kernel_flow

http://wiki.openwrt.org/doc/networking/praxis

http://www.ibm.com/developerworks/linux/library/l-linux-networking-stack/?ca=dgr-lnxw01lnxNetStack

http://gicl.cs.drexel.edu/people/sevy/network/Linux_network_stack_walkthrough.html

您还需要浏览内核源代码:

http://lxr.linux.no/#linux+v3.7.3/

使用这个函数开始你的网络子系统之路: ip_rcv,它在收到数据包时调用。然后调用其他函数 ( ip_rcv_finish,ip_local_deliverip_local_deliver_finish=> 这个函数负责选择好的传输层)

于 2013-01-19T02:53:14.020 回答
2

如果您喜欢更直观的方式,请尝试flame-grahps。下面是一个 UDP 传输流示例(使用 netperf 传输 UDP 数据包): 在此处输入图像描述

这是在 udp_send_skb 上放大的同一张图: 在此处输入图像描述

您可以对内核中的任何相关流程执行相同的操作。您还可以搜索特定功能或关键字并放大/缩小。这也让您了解流程中较重的功能。

希望这可以帮助。

于 2017-11-25T11:55:24.170 回答
0

这个链接也不错。它讨论了 udp 和底层 IP、NIC 等:

https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data/

于 2021-03-22T23:07:41.233 回答