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では関数グラフと呼ばれます。

Linuxカーネル関数をftracefunction_graphtracerで使用できるようにする方法は?

そして、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内にあります。ここで、はシェルスクリプトプロセスです。20秒の目的は、ユーザースペースアクティビティを実行できるようにすることです。この時点で多くのUDPアクティビティを開始するだけです。デフォルトではすべてをトレースするため、上記のスクリプトから「 echo udp_ *> / debug / traceing/set_ftrace_filter 」を削除することもできます。

于 2013-01-20T05:56:03.257 に答える
4

Linux のネットワーク スタックはカーネルの大きな部分を占めており、その研究に時間を費やす必要があります。この本が役立つと思います (古いカーネル 2.4 と 2.6 に焦点を当てていますが、最新のカーネル 3.x でもロジックは同じです):

Linux ネットワークの内部を理解する

The Linux Networking Architecture - 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_deliverおよび ip_local_deliver_finish=> この関数は、適切なトランスポート層を選択する責任があります)

于 2013-01-19T02:53:14.020 に答える
2

より視覚的な方法を好む場合は、flame-graphsを試してください。UDP 送信フローの例を次に示します (netperf を使用して UDP パケットを送信します)。 ここに画像の説明を入力

そして、これは udp_send_skb を拡大した同じグラフです。 ここに画像の説明を入力

カーネル内の関連するフローについても同じことができます。特定の機能やキーワードで検索したり、ズームイン/ズームアウトしたりすることもできます。これにより、フロー内のより重い関数についてのアイデアも得られます。

お役に立てれば。

于 2017-11-25T11:55:24.170 に答える