TCP的实现中,SACK和DSACK是比较重要的一部分. SACK和DSACK的处理部分由Ilpo Järvinen (ilpo.jarvinen@helsinki.fi) 维护. tcp_ack()处理接收到的带有ACK标志的数据段时,如果此ACK处于慢速路径,且此ACK的记分牌不为空,则调用 tcp_sacktag_write_queue()来根据SACK选项标记发送队列中skb的记分牌状态. 笔者主要分析18和37这两个版本的实现. 相对而言,18版本的逻辑清晰,但效率较低:37版本的逻辑…
和18版本相比,37版本的SACK和DSACK的实现做了很多改进,最明显的就是需要遍历的次数少了, 减少了CPU的消耗.37版的性能提升了,代码有大幅度的改动,逻辑也更加复杂了. 本文主要内容:37版tcp_sacktag_write_queue()的实现,也即37版SACK和DSACK的实现. Author:zhangskd @ csdn 数据结构 /* This defines a selective acknowledgement block. */ struct tcp_sack_blo…
我们发送重传包时,重传包也可能丢失,如果没有检查重传包是否丢失的机制,那么只能依靠超时来恢复了. 37版本把检查重传包是否丢失的部分独立出来,这就是tcp_mark_lost_retrans(). 在处理SACK块的同时,会检测是否有出现乱序,如果有乱序,那么会计算乱序的长度并更新. 本文主要内容:检查重传包是否丢失,以及乱序的检测和更新. Author:zhangskd @ csdn 检查重传包是否丢失 tcp_mark_lost_retrans()用于检查重传的包是否丢失,2.6.22内核在…
不论是18版,还是37版,一开始都会从TCP的控制块中取出SACK选项的起始地址. SACK选项的起始地址是保存在tcp_skb_cb结构的sacked项中的,那么这是在什么时候做的呢? SACK块并不是总是合法的,非法的SACK块可能会引起处理错误,所以还需要进行SACK块的合法性检查. 本文主要内容:TCP首部中SACK选项的解析和地址的获取,SACK块的合法性检查. Author:zhangskd @ csdn SACK选项的地址 TCP_SKB_CB(skb)->sacked is in…
上篇文章中我们主要说明如何skip到一个SACK块对应的开始段,如何walk这个SACK块包含的段,而没有涉及到 如何标志一个段的记分牌.37版本把给一个段打标志的内容独立出来,这就是tcp_sacktag_one(). 本文主要内容:tcp_sacktag_one(),给一个段打上标志. Author:zhangskd @ csdn 标志一个包 tcp_sacktag_walk()用于遍历块中的数据包,最终会调用tcp_sacktag_one()来标志一个数据包的记分牌, 即TCP_SKB_C…
18版本对于每个SACK块,都是从重传队列头开始遍历.37版本则可以选择性的遍历重传队列的某一部分,忽略 SACK块间的间隙.或者已经cache过的部分.这主要是通过tcp_sacktag_skip()和tcp_sacktag_walk()完成的. tcp_sacktag_skip()可以直接找到包含某个序号的skb,通常用于定位SACK块的开头. tcp_sacktag_walk()则遍历两个序号之间的skb,通常用于遍历一个SACK块. 本文主要内容:SACK的遍历函数tcp_sacktag…
和18版本不同,37版本把DSACK的检测部分独立出来,可读性更好. 37版本在DSACK的处理中也做了一些优化,对DSACK的两种情况分别进行处理. 本文主要内容:DSACK的检测.DSACK的处理. Author:zhangskd @ csdn dsack检测 根据RFC 2883,DSACK的处理流程如下: 1)look at the first SACK block : -If the first SACK block is covered by the Cumulative Ackno…
本文主要内容:tcp_ack()中的一些细节,如发送窗口的更新.持续定时器等. 内核版本:3.2.12 Author:zhangskd @ csdn 发送窗口的更新 什么时候需要更新发送窗口呢? (1)确认了新的数据 (2)条件1不成立,ACK段的序号是最新的. 这表示虽然ACK段没有确认了新的数据,但是它携带了新数据. (3)条件1和2都不成立,通告窗口变大. ACK既没有确认了新的数据,序号也不是最新的. 虽然如此,但是如果对端的接收窗口变大,我们还是要更新发送窗口. 此时ack_seq必须…
TCP发送数据包后,会收到对端的ACK.通过处理ACK,TCP可以进行拥塞控制和流控制,所以 ACK的处理是TCP的一个重要内容.tcp_ack()用于处理接收到的ACK. 本文主要内容:TCP接收ACK处理,tcp_ack()的实现. 内核版本:3.2.12 Author:zhangskd @ csdn 基础 在我们开始探究tcp_ack()的处理流程前,不妨先来回顾一些即将涉及到的概念和数据结构. struct tcp_sock { ... /* Packets which are "in…
在tcp_clean_rtx_queue()中,并非对每个ACK都进行时延采样.是否进行时延采样,跟这个ACK是否为 重复的ACK.这个ACK是否确认了重传包,以及是否使用时间戳选项都有关系. 本文主要内容:tcp_clean_rtx_queue()的一些细节,时延采样的条件. 内核版本:3.2.12 Author:zhangskd @ csdn 记分牌 TCP_SKB_CB(skb)->sacked称为skb的记分牌,用于跟踪skb的状态. 以下是skb记分牌可能的取值: #define TC…