- 论坛徽章:
- 1
|
大家好,我在阅读linux的tcp部分源码时遇到一个问题,望各位大侠帮助解答,具体问题描述如下:
tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_una)
{
...
for (i=0; i<num_sacks; i++, sp++) {
...
/* Event "B" in the comment above. */
if (after(end_seq, tp->high_seq))
flag |= FLAG_DATA_LOST;
...
}
...
}
上面代码中if那句的判断原理我一直没有太明白其依据究竟是什么?为了说明我的疑惑,我用附件的一副图进行说明,请各位帮我指出哪里有问题
1、图中对于发送方画图时似乎表示收到SACK后才发送下一个分段,实际不一定,请勿误会
2、Sx假定是因为某种原因丢失的分段,从Sx后,接收方连续收到S1,S2,S3三个分段,于是根据TCP的规范,此时接收方将针对每个收到的Sx后的分段进行立刻确认,实际也就是进行SACKed,而对于发送方,当收到SACK3后,知道此时网络发生了拥塞,于是进入到recovery阶段(或者是通过FACK方式知道拥塞发生,其判断是if ((snd.fack - snd.una> (3* MSS) || dupacks ==3) , 不过这里为方便讨论,假定仍然是通过连续收到3个重复ACK来代表拥塞,其实也就是假定在3个重复ACK到来前没有再出现丢失分段的现象,此时FACK方式和普通3个重复ACK方式是一样的)
3、假定发送方在收到SACK3之前最近一次发送的分段为S5,S6是在Sx重发之后才会发送的下一分段
4、tp->high_seq的含义是发生拥塞时的snd_nxt,于是似乎其值应为S6
因为if判断中end_seq为发送方收到的SACK中某个block,这里判断的原理是若其值在tp->high_seq之后,即存在一个已被接收的分段,其分段的右边界大于tp->high_seq后,就表示有数据丢失了,所以设置flag为FLAG_DATA_LOST,但是根据我这里的图示,S5因为是重发Sx之前最后一个发出的分段,其正确到达了接收方,那么其右边界就是(S5+MSS)+1,而下一个即将发送的分段也是S6=S5+MSS+1, 那么怎么可能满足这个after的判断呢?并且既然已经连续收到了3个重复ACK了,那么已经可以表示当前有分段丢失了呀,为啥还要做这个判断呢?
我的理解哪里出现错误了?
-----------
补充一点
-----------
源码中那句英文注释如下,下面是我的翻译
964 * B. SACK arrives sacking data transmitted after never retransmitted
965 * hole was sent out.
966 * SACK到达发送方,这些SACK对在hole所对应的数据被发出后的那些发出的数据进行确认,
967 * 此时,这些hole数据并未进行过重发(即对hole之后发出的数据进行了确认)
[ 本帖最后由 jiufei19 于 2009-9-6 19:32 编辑 ] |
|