- 论坛徽章:
- 1
|
大家好,在我继续阅读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 编辑 ] |
|