内核tcp协议栈SACK的处理
上一篇处理ack的blog中我们知道当我们接收到ack的时候,我们会判断sack段,如果包含sack段的话,我们就要进行处理。这篇blog就主要来介绍内核如何处理sack段。
SACK是包含在tcp的option中的,由于tcp的头的长度的限制,因此SACK也就是最多包含4个段,也就是32个字节。我们先来看tcp中的SACK段的表示:
在进入这段代码分析之前,我们先来看几个重要的域。
tcp socket的high_seq域,这个域是我们进入拥塞控制的时候最大的发送序列号,也就是snd_nxt.
然后这里还有FACK的概念,FACK算法也就是收到的不同的SACK块之间的hole,他就认为是这些段丢失掉了。因此这里tcp socket有一个fackets_out域,这个域表示了//开始遍历,可以看到这里将将我们未处理的sack段的序列号清0.for (i = 0; i < ARRAY_SIZE(tp->recv_sack_cache) - used_sacks; i++) {tp->recv_sack_cache[i].start_seq = 0;tp->recv_sack_cache[i].end_seq = 0;}//然后保存这次处理了的段。for (j = 0; j < used_sacks; j++)tp->recv_sack_cache[i++] = sp[j];//标记丢失的段。tcp_mark_lost_retrans(sk);tcp_verify_left_out(tp);if ((state.reord < tp->fackets_out) && ((icsk->icsk_ca_state != TCP_CA_Loss) || tp->undo_marker) && (!tp->frto_highmark || after(tp->snd_una, tp->frto_highmark)))tcp_update_reordering(sk, tp->fackets_out - state.reord, 0);