TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收

在这篇文章中我们看一下server端在接收到异常数据系列时的处理,主要目的是通过wireshark示例对这些异常数据系列的处理有一个直观的认识,感兴趣的自行阅读相关代码和协议,这里不再进行详细介绍

在进行下面的测试前,首先如下设置相关的参数,其中window参数指定了到127.0.0.2的tcp连接的最大接收窗口。

  1. [email protected]:/home/******/tcp12# ip route change local 127.0.0.2 dev lo window 40

一、wireshark示例

1、一个包部分数据在rcv_nxt后

如下图所示,client在与server建立连接后,首先发出No4数据包,系列号对应[1,10],下图中text列表示这个TCP数据包中实际传输的数据,No4的len=10,应用层实际传输的数据内容为"0123456789"。接着client又在No6数据包中传输系列号为[6,15]的数据包,传输的内容同样为"0123456789",长度同样为10bytes。

可以看到这里No4和No6两个数据包部分系列号重复,No4数据包系列号[6,10]对应字符串"56789",而No6数据包系列号[6,10]对应字符串"01234"。server端对于No6数据包正常回复了一个ACK报文,Ack=16,也就是说确认了系列号16以前的数据,同时可以看到No7这个ACK确认包还带有一个DSACK块,指示发送端收到了重复报文。

最终server端应用层实际读取了15bytes数据,内容为"012345678956789",可见server端把No6报文系列号[6,10]对应的数据丢弃了,但是保留了系列号[11,15]的内容。

2、一个乱序包完全在接收窗口外

如下图所示,client在与server端建立连接后,首先正常发送No4报文,接着发送乱序报文No6。从No5这个确认包可以看到Ack+Win=51,也就是说从系列号51开始的数据都是接收窗外外部的数据(包括系列号51对应的byte)。No6报文对应的系列号为[51,60]正好完全处于接收窗口外部,因此server端会丢失No6这个数据包。server端应用层最终读取了10bytes的数据,即"0123456789"。

3、一个乱序包部分在接收窗口外

这个示例与上一个不同之处在于No6系列号范围为[46,55],也即这个数据包[46,50]系列号在接收窗口内,而[51,55]在接收窗口外部。

接着看No7,No7通过SACK完整的确认了No6数据包,把落在接收窗口外部的[51,55]系列号也完整确认了,注意这个示例与上面的对比。当乱序包部分系列号落在接收窗口外部的时候,linux会正常完整的接收这个数据包,包括落在接收窗口外部的数据。而当这个数据包完全落在接收窗口外部的时候,linux则不会接收这个数据包。

另外值得注意的是No8-No11四次挥手关闭连接的过程,No8携带了SACK信息,No9则回复了一个ACK,注意No10这个FIN包的起始系列号为11,server端正常的接收了这个数据包,这也就意味着server端会把收到乱序No6报文丢掉,应用层并不能成功读取。

4、快速路径下连续包落在接收窗口外

linux对于接收到的数据包处理流程分为快速路径和慢速路径,在接收到紧急指针、tcp头中的window size发生变化等场景下都会进入慢速处理路径,慢速路径相比快速路径会执行更多检查处理。我们先来看一下快速路径下,连续包落在接收窗口外部的情况。为了不让server端更新接收窗口,我们通过SO_RCVBUF选项固定server端的接收缓存,同时我们通过特定的数据包让server端进入delay ACK模式。执行下面的测试前取消通过路由表设置的window参数。

相关的数据交互如下,No4数据包用来触发server端快速的进入delay ACK模式,server回复完No5这个确认包后就会进入delay ACK模式。关于delay ACK相关内容可以参考前面的文章。同时注意No5报文通告的Win=2,也就是接收窗口只剩余2bytes。

接着我们看到client端发送的No6-No32报文都没有触发server端回复ACK确认包。其中No6报文部分落在接收窗口外部,而No7-No32报文都是完全落在接收窗口外部的数据包。从No34这个确认包可以看到server端对于部分落在接收窗口内部的No6和完全落在接收窗口外部的No7-No32都接收了。而对于No33则没有进行接收,随后在发送No35数据包server端也没有接收。

这里No6-No32能被正常接收的原因是,linux中TCP会预留一定的缓存,当在快速处理模式下时候并不会执行严格的检查,只要新接收的数据包所占用的缓存没有超过预留的缓存就会正常接收。No6-No32都没有超过预留的缓存,因此server端正常接收。但是server端在接收到No34的时候,预留缓存不足,就会直接丢弃这个数据包,并进入quick ACK模式立即回复一个ACK,可以看到No34是一个零窗ACK报文,因此server端也就退出数据包的快速处理模式,随后在收到No35的时候会进入数据包慢速处理流程,执行检查的时候发现此时接收窗口大小为0,No35落在了接收窗口外面,因此同样会直接丢弃这个数据包并立即回复一个ACK确认包。

5、慢速路径下连续包落在接收窗口外

实际上上一次示例No35的处理已经是在慢速路径下处理的了。我们在看另外一个类似的示例。下图示例中No1-No15报文的处理与上面的示例类似,不同的地方在于No16这个数据包的Win发生了更新。server端在收到No16这个数据包的时候,发现No16更新了window size就会退出快速路径的处理进入慢速路径,以执行更复杂的检查和处理。在慢速路径中server端发现No16落在的接收窗口外部,因此直接丢弃这个数据包并进入quick ACK模式立即回复一个No17确认包,回复No17确认包的时候发现Win=0,server端TCP则退出数据包的快速处理模式,在随后接收到新数据包的时候则直接进入慢速路径处理。

6、乱序包内容部分重叠

如下图所示,client依次发送5个数据包,相关TCP交互如下图所示

为了方便对比,我把五个数据包对应的做如下图展示,其中第一行表示系列号比特位,第二行表示server端应用层实际读取的数据流,余下的5行分别表示client依次发送的5个数据包,其中数据包的红色部分表示最终被server端丢弃,数据包的绿色部分表示最终被server端接收。从下图可以看到一旦一个新接收的报文与之前报文重叠的时候,如果是新接收报文的前端发生重叠,那么新接收报文的前端内容会被丢掉,如果是后端重叠,那么之前接收的报文的内容将会被丢掉。

补充说明:

1、linux相关函数数据包接收处理:tcp_rcv_established、tcp_data_queue、tcp_data_queue_ofo

2、慢速路径快速路径等相关函数:tcp_fast_path_check,重点是tp->pred_flags这个标志变量在不同地方的更新

来自为知笔记(Wiz)

TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收

时间: 2024-10-10 23:50:30

TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收的相关文章

TCP系列33—窗口管理&流控—7、Silly Window Syndrome(SWS)

一.SWS介绍 前面我们已经通过示例看到如果接收端的应用层一直没有读取数据,那么window size就会慢慢变小最终可能变为0,此时我们假设一种场景,如果应用层读取少量数据(比如十几bytes),接收端TCP有了少量的新的接收缓存后如果立即进行window update把新的window size通告发送端的话,发送端如果立即发送数据,那么接收端缓存可能又会立即耗尽,window size又变为0,接着应用层重复读取少量数据,这个过程重复的话,那么发送端就会频繁的发送大量的小包,这种场景我们就

TCP系列34—窗口管理&流控—8、缓存自动调整

一.概述 我们之前介绍过一种具有大的带宽时延乘积(band-delay product.BDP)的网络,这种网络称为长肥网络(LongFatNetwork,即LFN).我们想象一种简单的场景,假设发送端的发送窗口为5000bytes,网络的RTT为200ms,那么每秒的最大速率则为5000*(1000/200)=25000bytes/s,这大约为24kb/s,可以看到这个速率是非常低的,这就是TCP发送窗口对于发送速率的限制,实际的window size应该至少为带宽时延积才能高效的利用网络传输

TCP系列35—窗口管理&流控—9、紧急机制

一.概述 我们在最开始介绍TCP头结构的时候,里面有个URG的标志位,还有一个Urgent Pointer的16bits字段.当URG标志位有效的时候,Urgent Poinert用来指示紧急数据的相对于TCP头中系列号Seq的位置,系列号和紧急指针值的和我们称呼为退出点(exit point).应用程序写入数据的时候可以通过MSG_OOB的socket选项来指定紧急数据.实际上因为紧急数据只有一个指针来指示并没类似长度的字段,因此紧急数据也只能有1bytes.RFC6093已经建议不要在继续使

七周二次课(1月23日) 10.6 监控io性能 10.7 free命令 10.8 ps命令 10.9 查看网络状态 10.10 linux下抓包

七周二次课(1月23日)10.6 监控io性能10.7 free命令10.8 ps命令10.9 查看网络状态10.10 linux下抓包 =====================================================================================================================================================================================

10.6 监控io性能 - 10.7 free命令 - 10.8 ps命令 - 10.9 查看网络状态 - 10.10 linux下抓包

- 10.6 监控io性能 - 10.7 free命令 - 10.8 ps命令 - 10.9 查看网络状态 - 10.10 linux下抓包 - 扩展tcp三次握手四次挥手 http://www.doc88.com/p-9913773324388.html  - tshark几个用法:http://www.aminglinux.com/bbs/thread-995-1-1.html  # 10.6 监控io性能 ![mark](http://oqxf7c508.bkt.clouddn.com/b

10.6 监控io性能 10.7 free命令 10.8 ps命令 10.9 查看网络状态 10.10 linux下抓包

iostat sysstat 包里面包括 sar 和 iostat [[email protected] ~]# iostat Linux 3.10.0-693.2.2.el7.x86_64 (centos7.4) 2018年01月23日 _x86_64_ (1 CPU) avg-cpu:  %user   %nice %system %iowait  %steal   %idle 0.41    0.00    0.27    0.01    0.00   99.31 Device:     

tcp协议头窗口,滑动窗口,流控制,拥塞控制关系

参考文章 TCP 的那些事儿(下) http://coolshell.cn/articles/11609.html tcp/ip详解--拥塞控制 & 慢启动 快恢复 拥塞避免 http://blog.csdn.net/kinger0/article/details/48206999 TCP window Full http://blog.csdn.net/abccheng/article/details/50503457 名词解释 MTU:maximum transmission unit,最大

UART中的硬件流控RTS与CTS

转自:http://blog.csdn.net/zeroboundary/article/details/8966586 在RS232中本来CTS 与RTS 有明确的意义,但自从贺氏(HAYES ) 推出了聪明猫(SmartModem)后就有点混淆了,不过现在这种意义为主流意义的,各大芯片制造厂家对UART控制器的流控基本采用HAYES MODEM流控解释. 在RS232中RTS 与CTS 是用来半双工模式下的方向切换,本文不解释: 如果UART只有RX.TX两个信号,要流控的话只能是软流控:如

TCP的滑动窗口

TCP发送方的窗口可以划分成四个部分: 1.已经发送并且确认的TCP段: 2.已经发送但是没有确认的TCP段: 3.未发送但是接收方准备接收的TCP段, 4.未发送并且接收方也为准备接受的TCP段. 第3部分是可用窗口,长度为snd_una + snd_wnd - snd_nxt. 第2部分和第3部分合并起来,成为发送窗口,简称窗口. 发送窗口的左边界是snd_una,右边界是snd_una + snd_wnd . 同理,TCP接受方的窗口可以划分成四个部分: 1.已经接收并且已经确认的TCP段