TCP拥塞控制图解 不包括RTO,因为它太简单了 【勘误1】

熬过了几个夜晚,终于把TCP的拥塞处理的Linux撸了一遍,仓促中也总结了一幅巨大的图,然而今天下午的例会讨论后,我自己说着说着发现还有一些值得商榷的地方,有的是笔误,也有的是一些细节依然没有搞清楚,因此特此勘误,原文我只修改了文字,因为重新贴图代价实在太大,再者,我希望留下一些错误的印记,这样也能看清楚整个发展的历程,希望两篇一起看。

虽然在大师级的神看来,这不算什么,但是对于我,这是一个比较浩大的工程,错误之处在所难免,请谅解!谢谢!如果能共同进步,这就是我分享的最终目的和动力。

PS:
 1.今天是我的生日,我觉得就这么睡去不符合这个特殊日子的风格,因此就趁着二两酒把这篇勘误补齐吧。
 2.这是第一篇勘误,我相信原图还有很多问题,以后会持续更新,风格和方式与这个一致。

问题1:mark lost的时候到底是怎么进行的

这个涉及到了原图中的What to retransmit,到底Linux内核函数tcp_mark_head_lost是怎么进行的呢?看下面的发送序列:
 UNA|hole1|hole2|sack1|sack2|hole3|hole4|sack3-7|unack1|unack4|snd_nxt|...
 我们得知,sack_out的值是2+5=7,假设默认reordering是3,那么在不启用fack的情况下,应该有7-3=4个数据包被标记为LOST,该标记哪些呢?

选择:从una开始,标记没有被sack的4个数据包,即UNA,hole1,hole2,hole3。这也是我在原图中的理解,但事实上呢?我们开看代码(Linix 3.10),tcp_mark_head_lost:

static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
{
    struct tcp_sock *tp = tcp_sk(sk);
    struct sk_buff *skb;
    int cnt, oldcnt;
    int err;
    unsigned int mss;
    /* Use SACK to deduce losses of new sequences sent during recovery */
    const u32 loss_high = tcp_is_sack(tp) ?  tp->snd_nxt : tp->high_seq;
    ...

    tcp_for_write_queue_from(skb, sk) {
        if (skb == tcp_send_head(sk))
            break;
        /* TODO: do this better */
        /* this is not the most efficient way to do this... */
        tp->lost_skb_hint = skb;
        tp->lost_cnt_hint = cnt;

        if (after(TCP_SKB_CB(skb)->end_seq, loss_high))
            break;

        oldcnt = cnt;
        if (tcp_is_fack(tp) || tcp_is_reno(tp) ||
            // 请注意,被标记为SACKED的数据包也会占据mark lost计数!!如上例,当UNA,hole1,hole2被标记完
            // 以后,下一个本应该标记hole3,但是由于sack1占据可一个“位置”,因此如果只标记4个LOST,那么将会
            // 到sack1为止!!,不会再标记hole3!
            // 但这并不意味着LOST标记仅仅会标记左边数第一系列的空洞,如果标记数为5,那么由于sack2也占据了一个
            // 位置,标记为LOST的依然是UNA,hole1,hole2,但是如果是标记6个LOST,那么结果将是标记UNA,hole1,hole2,
            // hole3为LOST!明白了吗?
            (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
            cnt += tcp_skb_pcount(skb);

        if (cnt > packets) {
            ...
        }

        tcp_skb_mark_lost(tp, skb);

        if (mark_head)
            break;
    }
    tcp_verify_left_out(tp);
}

总结:标记LOST的时候,会从左到右,标记的时候并不会跳过已经被SACK的数据包,只是,如果它已经被SACK了,那么将不会被置LOST标志。这有什么意义?在SACK reneging的时候,将会有意义。
这意味着,可以重传多少数据包和空洞的位置有关,一个合理的假设是,如果中间大量连续积累了SACKed的数据包,仅仅说明在这些数据包前面的空洞丢失的可能性比较大,这是真丢包,而不是乱序,然而话如果反着说,如果被SACKed的数据包间隔交替到来,这恰恰说明乱序的可能大于丢包,此时我们到底要重传哪些呢?如果给我安放一个偏置电阻的权力,我就可以完美解决这个问题,然而电阻可以在电子市场一块钱抓一把,跟老板混熟了还可以白拿,偏置算法可就是不是随便百度一下就能用的了....(百度?嗯,百度!)

问题2:关于When to retransmit

原图中,在描述SACK模式的时候,我在图中只画了3个数据包被SACK,但是事实上,要想触发重传,必须有至少4个数据包被SACK,这是一个笔误。

问题3:原图中的乱序检测,在描述重复SACK的时候,我将reordering的右沿滑到了snd_high,但事实上,应该是最高被SACK的那个位置,正如下面的文字描述的那样,犯这样的错误,真不应该!

问题4:严格说,这是我自己想的一个问题,原图原文不一定错,然而人不就是不断否定自己才能进步么?

请看How to retransmit,旁白中有关于RFC3517的描述,规范了传输的优先级,第一优先传输LOST数据包,第二传输新数据,然而我们看到,tcp_xmit_retransmit_queue,发现Linux实现第二优先传输新数据的时候,完全依赖“output路径”,也就是说在传输完LOST数据包之后,只要发现有新数据等待传输,直接就退出了tcp_xmit_retransmit_queue,至于说output路径到底什么时候被触发,
已经可以传输多少新数据,完全不管!
       在解耦合方面,这么做是恰当的(请注意这个函数的名字是retranmit,而不是transmit),但是难道这样不会造成窗口浪费吗?试想当前窗口为100,我有10个LOST数据需要重传,这意味着
       可以发送90个新数据包,然而可能此时没有那么多新数据包,难道这个时候进行“前向重传”不好吗?

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/ksiwnhiwhs/p/10390496.html

时间: 2024-08-30 13:13:55

TCP拥塞控制图解 不包括RTO,因为它太简单了 【勘误1】的相关文章

TCP拥塞控制

TCP必须使用端到端拥塞控制而不是使网络辅助的拥塞控制,因为IP层不向端系统提供显式的网络拥塞反馈.TCP采用的方法是让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率. TCP限制向其连接发送流量 TCP连接的每一端都是由一个接收缓存.一个发送缓存和几个变量组成.运行在发送方的TCP拥塞控制机制跟踪一个额外的变量,拥塞窗口(cwnd),它对一个TCP发送方能向网络中发送流量的速率进行了限制:在一个发送方中未被确认的数据量不会超过cwnd和rwnd中的最小值,即 LastBy

TCP拥塞控制 (1)

Basic: TCP,传输控制协议,是目前网络中应用最广泛的传输协议.SMTP.SSH.FTP.HTTP等因特网底层协议均是TCP. TCP面向连接,提供端到端的数据可靠传输.连接时三次握手,断开是四次挥手.具体表现为: 1.       TCP对传输的数据做了序号标记,其中序号标记安装字节数增长.TCP对端在接收到数据后发出一个ACK给对端(ACK中就包含序列号).TCP使用确认和超时重传机制保障了数据的可靠性传输. 2.       由于发送和接收端的数据处理能力不同,为了避免数据发送过快而

linux内核工程导论-网络:tcp拥塞控制

这篇文章本来是在tcp那篇里面的,但是那篇太长了,不专一.就完善了一下提取出来了. TCP拥塞控制 拥塞控制讨论的是很多个同时存在的tcp连接应该怎么规划自己的数据包发送和接收速度,以在彼此之间共享带宽,同时与其他实体的机器公平的竞争带宽,而不是自己全占. 拥塞控制的核心是AIMD(additive-increase/multiplicative-decrease ),线性增加乘性减少.为啥不用线性增加线性减少,或者是乘性增加乘性减少呢?这个有人专门研究过,只有AIMD可以收敛聚合使得链路公平.

TCP 拥塞控制

TCP 拥塞控制 相关名词 滑动窗口 tcp通过滑动窗口进行流量控制,所谓的窗口可以理解为接收端所能提供的缓冲区大小. TCP是一个滑动窗口协议,即一个TCP连接的发送端在某个时刻能发多少数据是由滑动窗口控制的 RTT(Round trip time) 表示从发送端到接收端的一去一回需要的时间. TCP在数据传输过程中会对RTT进行采样(即对发送的数据包及其ACK的时间差进行测量,并根据测量值更新RTT值) RTO (Retransmission TimeOut) 发送数据包,启动重传定时器,重

《网络协议》TCP 拥塞控制

TCP 拥塞控制主要有几种:慢启动.拥塞避免.快重传 以及 快恢复. 慢启动 为了防止网络拥塞,TCP 采用了一种慢启动算法,对发送数据量进行控制.为了调节发送端的数据发送量,引入了拥塞窗口,在慢启动时,将这个拥塞窗口设为 1 个报文段发送数据,之后每收到一次确认应答,拥塞窗口的值就加 1 个报文段.在发送数据包时,将拥塞窗口的大小与接收端主机通知的窗口大小进行比较,然后选择较小的值来控制数据量的发送.拥塞窗口是发送端使用的流量控制,而通告窗口则是接收端使用的流量控制. 慢启动算法步骤如下(cw

TCP拥塞控制 2

解决传统TCP缺陷: 1.窗口太小,最大65535. TCP利用了选项功能,其头部存在预留项,用于扩展等用途.窗口扩大选项增加了额外的16位来表示窗口大小,窗口的值由首部的16位大小和选项的16位值共同组成. 不过不是用加法组成的,而是利用移位窗口值的幂来表示的,也就是说如果移位窗口值为 10,那么窗口的最大值就是65535*210,这个值就比较大了,足够表示窗口的大小了. 2.数据包丢失,即认定为网络出现了拥塞 在高速网络中,这种假设是不成立的.如果笼统地认为分组丢失就是拥塞所引起的,从而降低

计算机网络概述 传输层 TCP拥塞控制

TCP拥塞控制 计算机网络中的带宽.交换结点中的缓存和处理机等,都是网络的资源.在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏.这种情况就叫做拥塞. 拥塞控制就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载.拥塞控制是一个全局性的过程,和流量控制不同,流量控制指点对点通信量的控制. 拥塞控制 和 流量控制 的区别? 1. 拥塞控制:拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况: 2. 流量控制:流量

TCP拥塞控制及连接管理

在阅读此篇之前,博主强烈建议先看看TCP可靠传输及流量控制. 一.TCP拥塞控制 在某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏——产生拥塞(congestion).出现资源拥塞的条件:对资源需求的总和 > 可用资源:拥塞带来的问题:若网络中有许多资源同时产生拥塞,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降. 1. 拥塞的控制方法一(慢开始和拥塞避免) 发送方维持一个叫做拥塞窗口 cwnd (congestion window)的状态变

TCP拥塞控制机制

我们知道TCP是拥有拥塞控制机制的,而UDP是没有的,为什么需要拥塞控制机制呢,就是防止丢包过多导致传输效率低下.网络中传输的包太多,路由器的缓存又不够,每一个发送端都以自己想要的发送速率发送包,自然会导致网络拥塞.所以我TCP就包括了拥塞控制机制. 有几种拥塞控制方法? 2种 1.端到端拥塞控制.网络层没有显示的告知传输层此时网络出现拥塞了,传输层通过报文段的丢失(超时或3次冗余确认得知)认为网络出现拥塞了,TCP会缩减其拥塞窗口,减小发送速率. 2.网络辅助的拥塞控制.网络层显示的告知发送端