免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3064 | 回复: 4
打印 上一主题 下一主题

tcp_disordered_ack函数中的一个问题 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-03-17 15:27 |只看该作者 |倒序浏览
本帖最后由 jiufei19 于 2010-03-17 15:31 编辑

以前,我曾经发了一个关于tcp_disordered_ack函数的帖子,现在回过头来重新看时,发现以前对一个问题忽略掉了,现在想请大家帮忙看看是否我理解正确
  static int tcp_disordered_ack(const struct sock *sk,  const struct sk_buff  *skb)
  {
      struct tcp_sock *tp = tcp_sk(sk);
      struct tcphdr *th = tcp_hdr(skb);
      u32 seq = TCP_SKB_CB(skb)->seq;
      u32 ack = TCP_SKB_CB(skb)->ack_seq;
  
      return (/* 1. Pure ACK with correct sequence number. */
          (th->ack && seq == TCP_SKB_CB(skb)->end_seq && seq == tp->rcv_nxt) &&
  
          /* 2. ... and duplicate ACK. */

          ack == tp->snd_una &&
  
          /* 3. ... and does not update window. */
          !tcp_may_update_window(tp, ack, seq, ntohs(th->window) << tp->rx_opt.snd_wscale) &&
  
          /* 4. ... and sits in replay window. */
          (s32)(tp->rx_opt.ts_recent - tp->rx_opt.rcv_tsval) <= (inet_csk(sk)->icsk_rto * 1024) / HZ);
  }

我这里有疑问的代码是上述中红色字体部分。想请教大家的是这句代码的场景是什么,即什么情况下会发生此判断所给出的条件。我的理解如下,不晓得正确否?

因为源代码的注释说明了这是一个纯ACK,且携带了正确的local方TCP希望接收的序号,那么是否只有在当peer方发送速度很快,序号发生了回绕后,即再次到达rcv_nxt所给出的序号对应的位置,假定此时peer没有收到local发送的某个序号的分段,于是根据快速重传等场景的描述,peer方发出重复ACK,于是这些重复ACK携带的seq就正好是local方的rcv_nxt。换句话讲,如果peer没有回绕的话,则不可能会产生一个纯ACK,且其seq等于local的rcv_nxt。

这个解释是否正确?还是另有其他场景支持此代码的情形1?

论坛徽章:
0
2 [报告]
发表于 2010-03-18 17:15 |只看该作者
本帖最后由 eexplorer 于 2010-03-18 17:19 编辑

回复 1# jiufei19

这个要放到更大的场景中考虑,才能看清楚问题:

首先,PAWS是为了防止sequence space回绕,导致旧的包被当作新的来处理(因为旧的包的sequence正好落在新回绕的sequence space的可接受范围内)。PAWS是使用timestamp option来处理的。这个对接收方是没问题的,如果接收方受到一个数据包,sequence number是可接受的,但是如果包的timestamp是旧的,那么就可丢弃这个包。

但是对于发送方就有问题了。。。
如果发送方发了一窗口的数据,但中间有几个包丢了,这样接收方就会发回一些duplicat ACK (带有SACKoption),比如 ACK1, ACK2, ACK3。而这些ack在到达发送方的时候是disordered的,如ACK1, ACK3, ACK2。这样收到ACK2的时候,PAWS check的时候就会被reject掉。
tcp_disordered_ack就是为了防止这种情况,所以如果收到一个pure dup ack的包,而且不是太旧(在1024个rto之内),至于condition 3 不update window的话,我想这些disorder的ACK只改变congestion control state,而不能去改变snd_wnd,因为我已经接收到新的ACK3,不能用旧的ACK2去update window。

这样作就有一个问题,在high bandwidth的network上,如果sequence space发生了回绕,我收到的ACK确实是旧的(sequence space回绕前的ACK),这样的ACK应该被reject掉。所以就用了1024个RTO来作限制,这样作虽然不能完全防止这个回绕问题(比如在非常high bandwidth的network上,它在1024个RTO里发生了回绕,那么我们就会错误的把这个旧的ACK传上去,当然这种情况是非常少的)。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
3 [报告]
发表于 2010-03-18 22:36 |只看该作者
回复 2# eexplorer


    谢谢eexplorer的说明,下面是我对你的说明中存在不解之处
----------------------------------------------------------------------
但是对于发送方就有问题了。。。
如果发送方发了一窗口的数据,但中间有几个包丢了,这样接收方就会发回一些duplicat ACK (带有SACKoption),比如 ACK1, ACK2, ACK3。而这些ack在到达发送方的时候是disordered的,如ACK1, ACK3, ACK2。这样收到ACK2的时候,PAWS check的时候就会被reject掉。
-----------------------------------
我们知道TCP是累积确认的,即便存在SACK,确认序号仍然保持只对当前按序正确收到的序号进行确认,因此即便在一个窗口中丢失了多个分段,则ACK1, ACK2,ACK3实际都是针对同一个最高序号进行的确认的,因此我对eexplorer这段说明有点不理解。

另外,我觉得这里所谓的disordered的意思似乎是因为peer方作为发送者发生了回绕后,此时产生的重复ACK的序号恰好和local方的rcv_nxt相等,因此称为disordered,不晓得我理解是否正确?

eexplorer的后面说明,我还在理解当中,稍后再回复

论坛徽章:
0
4 [报告]
发表于 2010-03-19 11:47 |只看该作者
回复  eexplorer


    谢谢eexplorer的说明,下面是我对你的说明中存在不解之处
------------------- ...
jiufei19 发表于 2010-03-18 22:36



考虑如下场景:
发送方发了[1-1024][1025-2048][2049-3072][3073-4096]四个包,如果第一个包收到了,但是第二个包掉了,同时第3,4个包也收到了。假设接收方发送了如下3个ACK:
ACK1: seq = 1, ack = 1025 ts1 (收到segment 1)
ACK2: seq = 1, ack = 1025 ts2 (收到segment 3)
ACK3: seq = 1, ack = 1025 ts3 (收到segment 4)

假如发送方收到的顺序是ACK1, ACK3, ACK2。在发送方收到ACK2的时候,因为ts2 < ts3,那么paws_check的时候就会被reject。但是ACK2有可能含有有用的信息(如sack option),tcp_disordered_check就是为了防止这种错误发生。

这样做的一个漏洞就是,如果sender的sequence space正好发生了回绕,而如果ACK2是没回绕之前的ACK的话,照理是应该被丢弃。所以在tcp_disordered_ack中加了一个1024 RTO的限制。这样的话,除非在非常high bandwidth的network上,回绕发生的非常快(1024 RTO之内),我们会错误的把应该丢弃的ack传到tcp stack继续处理。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
5 [报告]
发表于 2010-03-19 22:24 |只看该作者
本帖最后由 jiufei19 于 2010-03-19 23:12 编辑

回复 4# eexplorer


    非常感谢eexplorer的解释,你的如下说明的确是正确的
----------------------------------
考虑如下场景:
发送方发了[1-1024][1025-2048][2049-3072][3073-4096]四个包,如果第一个包收到了,但是第二个包掉了,同时第3,4个包也收到了。假设接收方发送了如下3个ACK:
ACK1: seq = 1, ack = 1025 ts1 (收到segment 1)
ACK2: seq = 1, ack = 1025 ts2 (收到segment 3)
ACK3: seq = 1, ack = 1025 ts3 (收到segment 4)

假如发送方收到的顺序是ACK1, ACK3, ACK2。在发送方收到ACK2的时候,因为ts2 < ts3,那么paws_check的时候就会被reject。但是ACK2有可能含有有用的信息(如sack option),tcp_disordered_check就是为了防止这种错误发生。
-----------------------------------

后半截的如下说明我进行下补充
------------------------------
这样做的一个漏洞就是,如果sender的sequence space正好发生了回绕,而如果ACK2是没回绕之前的ACK的话,照理是应该被丢弃
------------------------------
假定回绕发生后产生了一个ACK2_wrap,这个ACK2_wrap先到达local方,而ACK2后到达,显然ACK2_wrap的TS2_w比TS2要晚,因此按照普通PAWS的处理原则,应该丢弃ACK2,但是这个ACK2可能携带了有用信息,于是只要这个ACK2的时间戳和最近的时间戳记录值ts_recent相差不要太大,则仍然可以继续接受,否则这个ACK2就要被PAWS检查所丢弃(例如在HZ=1000下,也就是不要差过一个rto,其含义就是只要local方还没有启动重传前都可以接受,否则因为重传已经启动了,这个ACK2就可以被直接丢弃了,也即因为重传已经发生了,ACK2所携带的改进重传的信息如SACK已经失去了意义)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP