在Linux内核中的UDP数据包的路径(Path of UDP packet in linux ke

2019-07-18 10:33发布

我想找到一个Linux内核的UDP数据包的路径。 对于这一点,我想在一些文档(我读了这个迄今为止,这是TCP),然后在相应的内核函数的一些printk的声明,以确认。 我会通过重新编译内核代码做到这一点。

这是去了解它的方式吗? 你有什么建议/引用?

Answer 1:

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_finiship_local_deliverip_local_deliver_finish =>该功能负责选择好的输送层)



Answer 2:

具体回答你的问题,了解UDP处理的IPv4可以使用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$$

现在,输出文件是为shell脚本过程中/tmp/tracing.out里面找到。 20秒的目的是为了让用户空间活动的发生 - 就在这个点开始大量的UDP活动。 您也可以从上面的脚本删除“ 回声udp_ *> /调试/跟踪/ set_ftrace_filter”,因为默认是追查一切。



Answer 3:

如果你喜欢一个更直观的方式,尝试火焰grahps 。 下面是UDP传输流(使用的netperf发送UDP数据包)的一个例子:

这里是放大的上udp_send_skb在同一张图:

您可以在内核的任何相关流程做同样的。 您也可以搜索特定的功能或键字和放大/缩小。 这也为您提供了在流动较重功能的想法。

希望这可以帮助。



文章来源: Path of UDP packet in linux kernel