免费注册 查看新帖 |

Chinaunix

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

Linux网络内核tcp_rcv_established处理的一个问题?【已解决】 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-21 17:16 |只看该作者 |倒序浏览
大家好,在我继续阅读Linux TCP源码时,对如下红色字体部分的!before部分的判断不太理解,望大家能给予解答,谢谢!

int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, struct tcphdr *th, unsigned len)
{
     ...
     if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
          ...
          tcp_reset(sk);
          return 1;
     }
step5:  
     if (th->ack)
         tcp_ack(sk, skb, FLAG_SLOWPATH);
     ...
  }
  
这里的判断是说当本地TCP收到的这个skb分段如果携带SYN标志,并且其序号如果不小于tp->rcv_nxt,则reset该连接,但是我们知道此处处理的分段只能
是2种类型,一是纯SYN,即发起tcp connect的一方,对于这个情况,上述before的判断是很显然合理的,但是对于第2种类型,即该分段是一个SYN+ACK
的话,我们知道此时作为该段代码的执行者local方TCP必然是发出connect的一方,于是local方TCP的tp->rcv_nxt必然为0(参见下面的tcp_connect_init函数)
而作为peer方TCP发来的SYN+ACK所携带的序号必然是初始序号ISN,这个序号肯定大于local方的tp->rcv_nxt(=0),则似乎此时local方TCP必然会进行reset
处理了,没有机会执行后面的tcp_ack了,这里我的理解哪里出了问题?
  
--------------------------------
和此问题相关的主要部分代码
--------------------------------

  tcp_make_synack()
{
   TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
   th->seq = htonl(TCP_SKB_CB(skb)->seq);
   ...
}

static void tcp_connect_init(struct sock *sk)
{
     ...
     tp->rcv_nxt = 0;
}

int tcp_connect(struct sock *sk)
{
     ...
     tp->snd_nxt = tp->write_seq;
     TCP_SKB_CB(buff)->seq = tp->write_seq++;
     ...
     tcp_transmit_skb;
     ..
  }
  
  static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, gfp_t gfp_mask)
  {
      ...
      th->seq = htonl(tcb->seq);
      ...
  }

[ 本帖最后由 jiufei19 于 2009-8-24 08:57 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-08-22 11:45 |只看该作者

回复 #1 jiufei19 的帖子

具体的code不太熟悉,但是有一点:

tcp_rcv_established是在socket已经处于established状态时才会调用。

你说的情况是在建立connection的时候。。。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
3 [报告]
发表于 2009-08-22 21:15 |只看该作者

回复 #2 eexplorer 的帖子

感谢eexplorer的提醒,的确,我又仔细梳理了下源码,tcp_rcv_established是在tcp_v4_do_rcv函数中如下方式被调用的:

     if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
         TCP_CHECK_TIMER(sk);
         if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
             rsk = sk;
             goto reset;
         }
         ...
     }

这里看出是在连接被established后发生的,那么如果是这样,为啥本问题那句红色有问题代码中还要有th->syn为真这个条件呢,也就是说似乎可能存在这样的事实,即在连接已经建立好后,还有可能收到SYN+ACK分段,并且该分段的序号如果小于local方TCP的tp->rcv_nxt的话,那么local方还是必须对此SYN+ACK分段进行处理,即调用tcp_ack进行后续处理,否则如果该分段序号大于local方的rcv_nxt,才reset掉,那么在连接已经建立过程中什么样的场景会再次产生SYN+ACK呢?

[ 本帖最后由 jiufei19 于 2009-8-22 21:17 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2009-08-23 15:50 |只看该作者

回复 #3 jiufei19 的帖子

有一种情况有可能发生client在established状态收到syn+ack包:
1. client 发起连接,send syn
2. server ack with syn+ack
3. client reply with ack

如果client在step 3发送的ack包并没有及时送到server端,那么server会重发syn+ack包。这时client已经在established状态了,如果syn包的seq是在rcv_nxt之前的话,那么client需要重新发送一个ack包。

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
5 [报告]
发表于 2009-08-24 08:56 |只看该作者

回复 #4 eexplorer 的帖子

非常感谢eexplorer的解释,原因的确如此!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP