首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 操作系统 >

内核tcp协议栈SACK的处置

2012-09-07 
内核tcp协议栈SACK的处理上一篇处理ack的blog中我们知道当我们接收到ack的时候,我们会判断sack段,如果包含

内核tcp协议栈SACK的处理
上一篇处理ack的blog中我们知道当我们接收到ack的时候,我们会判断sack段,如果包含sack段的话,我们就要进行处理。这篇blog就主要来介绍内核如何处理sack段。

SACK是包含在tcp的option中的,由于tcp的头的长度的限制,因此SACK也就是最多包含4个段,也就是32个字节。我们先来看tcp中的SACK段的表示:



然后我们来看SACK的处理,在内核中SACK的处理是通过tcp_sacktag_write_queue来实现的,这个函数比较长,因此这里我们分段来看。

先来看函数的原型



2 如果sack的第二个段完全包含了第二个段,则说明我们收到了重复的sack,下面这张图描述了这种关系。




最后要注意的是,这里收到D-SACK后,我们需要打开当前sock d-sack的option。并设置dsack的flag。

然后我们还需要判断dsack的数据是否已经被ack完全确认过了,如果确认过了,我们就需要更新undo_retrans域,这个域表示重传的数据段的个数。

来看代码:




在进入这段代码分析之前,我们先来看几个重要的域。

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);












热点排行