TCP重传分析

news/2024/5/17 18:50:59 标签: tcpretrans, tcp_ack, tcp, 协议栈

0x01 缘由

     最近在结合linux tcp/ip协议栈,以及上层socket编程来进行相关学习,学习过程中发现一些有趣的东西,但是也想做做记录。于是有了这篇文章。
     tcp超时重传机制:https://baike.baidu.com/item/TCP%E8%B6%85%E6%97%B6%E9%87%8D%E4%BC%A0%E6%9C%BA%E5%88%B6/2122456?fr=aladdin

0x02 工具介绍

     翻译:http://www.brendangregg.com/blog/2014-09-06/linux-ftrace-tcp-retransmit-tracing.html
     工具下载:https://github.com/laoar/tcpretrans>tcpretrans
     对网络数据包分析工具较多,有tcpdump、tcpretrans>tcpretrans、wireshark等工具。下面介绍一款不太熟悉的工具tcpretrans>tcpretrans。
     包的细节和内核状态,如下图:
      
     tcpretrans>tcpretrans是一个perf-tools脚本集,并使用ftrace来动态地调用tcp_retransmit_skb()内核函数。这种处理方式的资源开销是可以忽略不计的。它仅仅加了一些指令到重传路径。它也使用一些linux内核特征,ftrace 和kprobes,甚至不需要内核debuginfo。
     它不会记录和过滤每个包,如果使用tcpdump/libpcap/kerbel-packet-filter方式,可能因为流量大而变得痛苦。用一个跟踪方式意味着能够挖掘内核状态,然而在线路上利用tcpdump是做不到这点的。仅实现了包含内核状态列,其他列可以定制。
     -s选项将包含一个内核堆栈跟踪,当导致重传时:
    
     这种情况发生在,当收到一个包(ip_rcv()),处理TCP ACK(tcp_ack>tcp_ack()),然后通过tcp_fastretrans_alert()触发。下图是一个tcp快速重传:
     
     下面是基于定时器的超时重传:
     
      栈的回调情况,以及tcp_write_timer_handler()。基于时间定时器的回传的情况比快速重传的情况更糟糕,因为它们的应用基于定时器的延迟。在Linux中通常是1000 ms。
     tcpretrans>tcpretrans是基于ftrace的一个修改,不能在没有任何修改的系统工作。(也不支持IPv6)。为了挖掘一些细节,像点分制IP地址,我真的应该开发一个款类似SystemTap的工具。然而,我想尝试仅仅使用ftrace去做,使其更简单的在我的(Netflix 云)上使用。
     基本流程:
     1.用kprobes添加指令到tcp_retransmit_skb(),并且读取%di寄存器。
     2.假设skb指针指向%di寄存器(为确定的知道需要利用内核debuginfo,通畅不会在生产环境中使用)。在非X86系统,可能是另外一个寄存器,那么这个脚本需要修改为相关寄存器。
     3.等待1秒。
     4.用skb指针读内核tcp_retransmit_skb()缓存事件。
     5.通过skb指针读/proc/net/tcp和socket cache。
     6.假设一个长时间的会话的重传发生时,这个会话的细节我们仍然可以在/proc/net/tcp中读到。
     7.分析tcp_retransmit_skb()内核缓存事件,打印已经从/proc/net/tcp中读取的重传事件的细节内容。
     8.Goto 3。

     下面是蘑菇街工程师为了定位tcp重传问题,改进的一个版本tcpretrans>tcpretrans。
     

0x03 tcp重传产生的原因

     1、网络丢包,没有收到对方ack,导致确认丢包;
     2、网络延迟太大,导致超时重传;

0x04 源码解读

     kernel 2.6.32,本来想详细分析TCP拥塞状态机 tcp_fastretrans_alert()(传送:http://blog.csdn.net/shanshanpt/article/details/22202259)函数,但是考虑里面的内容,暂时搁置,先看自己熟悉的一块,对ack包的处理情况。tcp_ack>tcp_ack函数:
    博客其他文章有对tcp流重组算法等做了一个说明,类似linux内核也需要考虑类型的场景,现在单独调试tcp_ack>tcp_ack处理过程,进一步加深印象:
     1.调试环境准备,前面有几篇文章讲述了调试linux内核环境,下面开启设置断点到tcp_ack>tcp_ack()
     2.通过ssh连接guest机器,进行三次握手,当客户端发送syn后,guest机器,需要回复ack,这样就进入我们设置的断点,函数栈调用信息如下:
     
     本来想自己好好去理解源码段,看到有人已经分析得比较清楚了,站在别人的基础上看待问题,是一种快速学习的手段。
     传送:http://blog.csdn.net/zhangskd/article/details/7103336

0x05 问题

     显示networking disabled 解决办法
     第一步,先把网络停掉
     sudo service network-manager stop
     第二步,清理对应的网络状态文件
     sudo rm /var/lib/NetworkManager/NetworkManager.state
     第三步,启动网络即可
     sudo service network-manager start

0x06 总结

     我有时在想,学习linux网络协议栈的用处有啥?但是想想大部分网络设备产品和服务端程序,都涉及到相关知识点,希望以此开阔自己的视野。

http://www.niftyadmin.cn/n/1460764.html

相关文章

tcp/ip协议栈-驱动到应用

0x01 缘由 本次学习的目的主要按照如下大纲开展:以服务端客户端程序调试三次握手、数据传输、四次挥手过程。搭建环境如下:前期调试linux内核环境从物理层向上:进入物理层:驱动程序处理中断?进入链路层:网卡…

链路层到网络层(eth-ip-udp)

0x01 缘由 上章节已经简单的学习了从硬件驱动层到链路层的相关过程,计划这章接讲解arp_rcv,但是考虑整个学习计划还是先从ip_rcv为主线展开学习,还是跟着上次的调试节奏进入网络层的源码跟踪和学习。0x02 整体调用栈 0x03 源码跟踪 1.跟踪ip…

tomcat安全

说明:此文章紧做为培养安全开发人员安全意识,不能用于任何违法安全活动。0x01 缘由 最近在复习python这块的开发,于是与安全合起来学习之。0x02 tomcat安全 网上有很多介绍,大部分是对账号密码把控不严导致。传送:http…

tcp/ip-路由相关结构

0x01 缘由 上章节已经学习了网络层(ip层),其中关键部分就是找下一跳路由,本次学习主要围绕路由相关知识点进行学习。0x02 相关结构 1.路由缓存机制: struct rtable {union{struct dst_entry dst; //目的条目} u;struct flowi …

tcp/ip协议栈-tcp层(1)

0x01 缘由 上章节简单学习了内核网络栈路由的过程,这章节继续tcp三次握手过程。0x02 调式环境 在guest虚拟机中跑一个server端,然后其他机器跑个客户端进行分析。0x03 源码解析 主要分几部分来:1.收到客户端syn包处理流程2.服务端构造syn ac…

tcp/ip协议栈--tcp处理中的几个队列

0x01 缘由 昨天简单过了下tcp层的syn的过程,其中对几个队列处理有点疑问,对数据如何到用户态的过程也存在的疑问?带着这几个问题网上查找了相关资料,发现一位大神讲解得比较清楚。传送:http://blog.csdn.net/russell_t…

Linux的直接I/O机制

Linux 中提供了一种不经过操作系统内核的缓存文件访问机制,这样一种文件访问机制对于那种将 I/O 缓存存放在用户地址空间的应用程序来说,是非常高效的。本文将基于 2.6.18 版本的内核来讨论 Linux 中直接 I/O 的技术的设计与实现。 对于传统的操作系统来…

tcp/ip协议栈--socket API 之connect()

0x01 缘由 前面一些博文简单学习了服务端 socket()、bind()、listen()、accept()过程,当没有客户端连接服务端时,服务端进程阻塞在accept处,等待客户端连接。…