C 跟踪通过内核的数据包(linux)
我有两台机器,它们被设置为使用Ip安全,机器A(让我们称它们为A和B)有一个套接字,绑定到本地机器上的特定UDP端口,它经常轮询它以查看是否接收到任何内容 当我禁用Ip安全性时,两台机器之间的数据可以正常传输,我可以正常发送和接收数据包。但是,当启用Ip安全性时,数据包不会到达机器B发送的机器A上的套接字 我在两台机器上都执行了C 跟踪通过内核的数据包(linux),c,sockets,networking,linux-kernel,packet,C,Sockets,Networking,Linux Kernel,Packet,我有两台机器,它们被设置为使用Ip安全,机器A(让我们称它们为A和B)有一个套接字,绑定到本地机器上的特定UDP端口,它经常轮询它以查看是否接收到任何内容 当我禁用Ip安全性时,两台机器之间的数据可以正常传输,我可以正常发送和接收数据包。但是,当启用Ip安全性时,数据包不会到达机器B发送的机器A上的套接字 我在两台机器上都执行了tcpdump,我可以看到(加密的)数据包从机器B发出并在机器a上接收。但是在那之后,数据包进入内核,在数据包解密的某个地方或者在其他某个阶段,数据包被丢弃 我希望能够在
tcpdump
,我可以看到(加密的)数据包从机器B发出并在机器a上接收。但是在那之后,数据包进入内核,在数据包解密的某个地方或者在其他某个阶段,数据包被丢弃
我希望能够在包通过内核时跟踪它,并查看它被丢弃的位置。是否有一些/proc
可用于此目的?我能想到的另一种方法是在整个内核中插入调试语句并重新编译,然后再次尝试发送数据包并进行调试
感谢并抱歉您的长消息,但这是必要的 请参考名为的项目。它允许您将用户友好的脚本挂接到任何内核代码中,而无需重新编译内核。例如:
probe function("ip_rcv").call {
printf("%d: ->ip_rcv()\n", gettimeofday_ms())
}
它将为网络层中接收到的每个数据包发出内核打印。当然,您需要阅读源代码,以便从那里深入到网络堆栈中
SystemTap的功能非常强大,并且有很多关于可以插入的各种挂钩的文档。是的,正如Dan所说,SystemTap非常有用。但我最喜欢的是ftrace 供参考: 因此,一般来说,为了跟踪网络流量,请将以下内容放在bash shell中并以root用户身份运行:
mkdir /debug
mount -t debugfs nodev /debug
mount -t debugfs nodev /sys/kernel/debug
echo '*' >/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$$
在接收入口路径上依此类推:
5) | tcp_recvmsg() {
5) | lock_sock_nested() {
5) 0.042 us | _cond_resched();
5) | _raw_spin_lock_bh() {
5) 0.040 us | local_bh_disable();
5) 0.414 us | }
5) 0.040 us | _raw_spin_unlock();
5) 0.040 us | local_bh_enable();
5) 1.814 us | }
5) | skb_copy_datagram_iovec() {
5) 0.042 us | _cond_resched();
5) 0.588 us | }
5) 0.042 us | tcp_rcv_space_adjust();
5) | __kfree_skb() {
5) | skb_release_all() {
5) | skb_release_head_state() {
5) 0.044 us | sock_rfree();
5) 0.670 us | }
5) | skb_release_data() {
5) | put_page() {
5) 0.049 us | put_compound_page();
5) 0.449 us | }
这是:
网络链接处理:
6) | rtnetlink_rcv() {
6) | mutex_lock() {
6) 0.090 us | _cond_resched();
6) 1.455 us | }
6) | netlink_rcv_skb() {
6) | rtnetlink_rcv_msg() {
6) 0.150 us | mutex_unlock();
6) | __netlink_dump_start() {
6) | netlink_lookup() {
6) 0.091 us | _raw_read_lock();
6) 0.100 us | netlink_compare();
6) 1.791 us | }
6) | mutex_lock() {
6) 0.095 us | _cond_resched();
6) 0.913 us | }
6) 0.100 us | try_module_get();
6) 0.090 us | mutex_unlock();
这也是入口:
3) | tcp_v4_rcv() {
3) | sk_filter() {
3) | security_sock_rcv_skb() {
3) 0.076 us | cap_socket_sock_rcv_skb();
3) 0.867 us | }
3) 1.630 us | }
3) 0.076 us | _raw_spin_lock();
3) 0.477 us | tcp_prequeue();
3) | tcp_v4_do_rcv() {
3) 0.088 us | tcp_md5_do_lookup();
3) 0.109 us | tcp_parse_md5sig_option();
3) 0.072 us | ipv4_dst_check();
3) | tcp_rcv_established() {
3) 0.076 us | tcp_parse_aligned_timestamp.part.34();
3) | tcp_queue_rcv() {
3) | tcp_try_coalesce.part.41() {
3) 0.835 us | skb_try_coalesce();
3) 1.722 us | }
3) 2.637 us | }
这就是出口(从系统调用“sendmsg()”开始):
希望你喜欢……哦,我今天刚看了这个。我插入了100条调试语句并重新编译内核,发现了问题。但这对于未来的需求来说是非常棒的。非常感谢。有什么理由使用function_graph tracer而不仅仅是function tracer吗?这两个是不同的输出:请看,它显示了两种不同的类型。
5) | SyS_sendmsg() {
5) | __sys_sendmsg() {
5) | sockfd_lookup_light() {
5) 0.080 us | fget_light();
5) 0.502 us | }
5) | ___sys_sendmsg() {
5) 0.117 us | copy_msghdr_from_user();
5) 0.101 us | verify_iovec();
5) | sock_sendmsg() {
5) | security_socket_sendmsg() {
5) | apparmor_socket_sendmsg() {
5) 0.092 us | aa_revalidate_sk();
5) 0.580 us | }
5) 1.044 us | }
5) | unix_stream_sendmsg() {
5) 0.113 us | wait_for_unix_gc();
5) | security_socket_getpeersec_dgram() {
5) 0.044 us | apparmor_socket_getpeersec_dgram();
5) 0.479 us | }
5) | sock_alloc_send_pskb() {
5) | __alloc_skb() {
5) | kmem_cache_alloc_node() {
5) 0.042 us | _cond_resched();
5) 0.648 us | }
5) | __kmalloc_reserve.isra.27() {
5) | __kmalloc_node_track_caller() {
5) 0.074 us | kmalloc_slab();
5) 0.040 us | _cond_resched();
5) 0.504 us | __slab_alloc();
5) 1.878 us | }
5) 2.276 us | }
5) 0.175 us | ksize();
5) 4.217 us | }