先从需求谈起吧。
        在上一篇文章《 Google's BBR TCP拥塞控制算法的四个变速引擎》的最后,我提到bbr算法作为一个标称功率十足的引擎需要源源不断的能源供给,而这类能源就是数据包。又提到,TCP的快速重传机制几乎只会将判断为LOST的数据包重传一次,因此当重传数据包再次丢失,滑动窗口无法滑动的时候,将会无法提供数据包发送,bbr引擎就会失速,此时只能等待TCP的超时!当然,超时的代价有点大,不单单是对于拥塞控制而言,对于整个连接而言,都无异于异常劫难!

因此,bbr需要源源不断的数据包供给它开大马力运行,bbr并不在乎这些数据包是新数据包,标记为LOST的数据包,重传过的数据包,甚至是构造的错包...只要有数据包即可!bbr真正彻底实现了拥塞控制与数据包标记/发送之间解耦合。

说完了需求,再谈方案。
        Linux内核在bbr之前就已经引入了RACK机制,旨在快速发现并重传那些曾经重传后再次丢失的数据包,这些数据包的处理至关重要,如果不及时处理,便会陷入RTO的深渊。当然,RTO的回调在你自己手上,你也可以处理得不那么激进,然而对于已经失速的连接,继续勉强撑着也算是自欺欺人了...RACK解决了这个问题。然而bbr之前的RACK并没有获得最大收益,原因在于虽然RACK可以即时地探知哪些数据包丢失,特别是那些重传后再次丢失的数据包,但是由于此时拥塞窗口的计算已经固定地朝着ssthresh的方向PRR跌落下去,受限于拥塞窗口,即时准备再多的可发送数据也无法着实发送出去!bbr引擎可以即时消化掉RACK送上来的能源,二者配合就开启了一台动力十足的高端引擎。
        RACK(请先看 这个draft)从名字上看,Recent ACK,即最近的ACK,当然也包括SACK,因此正确的名字应该是Recent (s)ACK,RACK并不记录数据被(s)ACK的时间,而是在收到ACK的时候,记录被该ACK确认的数据包的发送时间,在这些发送时间中取Recent,即最晚发送的。RACK的思想是,记录这个Recent (s)ACK所确认数据包的发送时间T.rack,然后给定一个时间窗口twin,在时间T.rack-twin之前发送的未被确认的数据包均被标记为LOST,然后这些数据包会被交给发送逻辑去发送。这非常符合常理。
        RACK的代码超级简单,核心逻辑就一个文件两个函数,位于net/ipv4/tcp_recovery.c中的:

/** 在一次(s)ACK的处理过程中更新被确认的数据包的最晚发送时间rack.mstamp。* xmit_time-当前处理的被确认的数据包的发送时间* sacked-当前处理的被确认的数据包的sacked标记,被选择确认过吗?被重传过吗?等等。*/
void tcp_rack_advance(struct tcp_sock *tp, const struct skb_mstamp *xmit_time, u8 sacked);
/** 根据tcp_rack_advance记录的最晚发送的被确认的数据包的发送时间rack.mstamp以及* 重传队列里未被选择确认的数据包的发送时间skb.mstamp的差,判断是否标记为LOST。* RACK内置有一个twin,凡是符合rack.mstamp-skb.mstamp>twin的数据包,均标记为LOST。* 如果该数据包被重传过,那么清除其被重传过的印记!*/
int tcp_rack_mark_lost(struct sock *sk);

以上就是关于RACK的两个接口,TCP在处理ACK的时候会调用这两个接口:
1).处理ACK携带的信息(TCP头的ACK号或者选项中sACK块)时调用tcp_rack_advance;
2).在发送ACK并非顺序ACK时,进入异常Alert时,调用tcp_rack_mark_lost。

这个RACK机制的简单性就在于,它不再区分正常的顺序ACK以及SACK,它只比较时间戳,不管发送顺序如何,只基于确认携带的信息来决定一个数据包是不是要被重传。以下面的序列为例:
1|2|3|4|5|6|7|8|
假设一个ACK确认了4,那么UNA则是5,假设这个ACK没有携带SACK信息,只是确认了4,那么rack.mstamp就是4发送的时间了,现在的问题是,4之后的5,6,7,8怎么可能在4之前发送呢?它明明是位于4之后的啊!RACK的简单性就体现在这里!5,6,7,8虽然在4后面但是谁也不能保证它们就一定是按照序列号顺序发送的,更加合理的做法是记录发送时间序列!典型的场景是,4,5,6,7,8均是重传过的数据包,首先重传了7,8,然后重传了6,然后重传4,最后重传5,这样发送的时间序列就是:
1|2|3|7|8|6|4|5|
现在4被确认了,按照上述时间序,我有理由继续等待5的确认到来,因为5是在4之后发送的,然而7,8,6却都是在4之前发送的,到底等不等呢?这里7是最先发送的,要判断skb7.mstamp与rack.mstamp之间的差值了,如果大于twin,说明继续等待7的选择确认是不可忍受的,反之,如果在twin之内,那么便有理由继续等待了,可能是乱序了!同样的策略处理8和6。
        这样处理是不是更加简单些呢?只需要按照时间序比较数据包最近一次的发送时间与rack.mstamp之间的差即可!完全忽略这个数据包是不是曾经被重传过,这样就解决了按照序列号进行LOST判断的复杂性问题。
        然而,在乱序的情况下,你可能会认为RACK机制可能会误传很多并未丢失(实际上是乱序到达或者ACK乱序反馈)的数据包,事实上这里就体现了twin时间窗口的作用,RACK的时间序并非严格的时间序,它是一个带有缓冲的准时间序机制。就算你认为twin也没用,再不济你也可以将RACK关掉的!
        注意twin的选择,一般而言是最小RTT的1/4,这里的最小RTT是与SRTT无关的,它是真实测量出来的离散RTT的win_minmax(请在《 Google's BBR TCP拥塞控制算法的四个变速引擎》看win_minmax详情)最小值,基于一个自动向后滑动的时间窗口采样的最小RTT,这里的主要目的不是平滑掉噪点(这有点像鸵鸟策略...),而是过滤掉非拥塞导致的抖动,这是一种主动发现噪点的行为,可以将 BufferBloat的影响最小化。

有了RACK机制,bbr再也不用为无包可发这种事发愁了。
        只要bbr可以根据(s)ACK采集到带宽和RTT,那么bbr就可以根据这些带宽,RTT的反馈全速率运行,而能让带宽和RTT反馈回来的,正是发出去的包,再次重申,无论是新包还是重传包,只要发送去,它们都可以反馈回结果,不管是ACK,SACK,还是DSACK...我们又绕回来了,RACK机制即使在已经发生丢包/乱序等事件时也能提供源源不断的可发送的数据包(即标记为LOST的数据包)。这个过程平滑的运行,不必再等待RTO超时!
        在bbr之前,一旦发生丢包或者严重乱序,TCP就会接管拥塞控制算法,但现在不了!以前的做法是错误的,所谓的丢包,乱序,这些都是TCP的拥塞控制状态机逻辑自己猜的,相当大程度是不真实的,任何算法都无法准确猜出是不是真的发生了丢包,想欺骗一只蝙蝠撞墙是很容易的,同样,TCP也是一个瞎子!所以,bbr的做法是正确的:
bbr算法本身:计算发送速率和窗口。
TCP拥塞控制状态机:准备新数据,标记LOST(传统方式以及RACK方式),即提供可传输的数据包,灌入bbr算法提供的食道。
TCP传输逻辑:实际传输任何可以传输的数据包,新的数据包,所有标记为LOST的数据包。
以上3者相互配合,回答了 ”传输多少?“,”传输什么?“,”怎么传输?“等问题,并且三者之间完全基于当下的(s)ACK反馈来交互,彼此之间则完全独立。
...
接下来干什么?
接下来我来吐个槽,事情要从工业革命后,人们企图将蒸汽机装在马车上开始...

RACK为TCP BBR提供动力源相关推荐

  1. 来自Google的TCP BBR拥塞控制算法解析

    写本文的初衷一部分来自于工作,更多的来自于发现国内几乎还没有中文版的关于TCP bbr算法的文章,我想抢个沙发.本文写于2016/10/15!         本文的写作方式可能稍有不同,之前很多关于 ...

  2. Google的TCP BBR拥塞控制算法深度解析

    原作者:dog250,授权发布 重新整理:极客重生 hi ,大家好,今天推荐一篇我认为在TCP BBR技术里面分析非常透彻的文章,希望大家可以学习到一些真正的知识,理解其背后的设计原理,才能应对各种面 ...

  3. 个人感悟—来自Google的TCP BBR拥塞控制算法解析

    地址:TCR BBR拥塞控制算法另类解析 写本文的初衷一部分来自于工作,更多的来自于发现国内几乎还没有中文版的关于TCP bbr算法的文章,我想抢个沙发.本文写于2016/10/15! 本文的写作方式 ...

  4. 骨干网络演化释义以及TCP BBR的部署环境问题

    昨天本应该去公司加班的,但我由于不在本地而没去享受这奢华的周末盛宴.不过我要一路上远程值守,有问题要上,这是必须的.无聊的时候,没有问题制造问题也要上?这是贱.所以,在没有问题的时候,我写下一些简单的 ...

  5. 深夜聊聊Bufferbloat以及TCP BBR

    这篇文章的写作动机来源于知乎上的一个问题,有人问既然Bufferbloat是个问题,为什么路由器的缓存还要设计那么大.起初,我也是觉得缓存越大越好,这个就像人们拼命比拼谁的电脑内存大一样,因为在一般人 ...

  6. ubuntu 20.04 快速开启TCP BBR实现高效单边加速

    Linux Kernel 内核升级到 4.9 及以上版本可以实现 BBR 加速,由于Ubuntu 18.04 默认的内核就是 4.15版本的内核,由于Ubuntu 20.04 默认的内核就是 5.4 ...

  7. TCP BBR - 如何安装、启动、停止BBR!

    TCP BBR从Linux 4.9 内核开始,就作为它内核的一部分存在了,如果想使用BBR,那么首先就是判断内核版本是否大于4.9,如果符合版本标准,那么直接启动BBR就可以了,如果低于4.9,升级内 ...

  8. TCP BBR的startup bbr_high_gain为什么是2/ln2?

    温州皮鞋厂老板上周就一直在问这个.正好昨天和今天早上有空,加上又在雨夜,就写一波. 温州皮鞋厂老板的问题如下: 慢启动: init_cwnd×2n=cwndinit_cwnd×2n=cwndinit\ ...

  9. TCP BBR Startup gain计算总结和Startup失速问题

    浙江温州皮鞋湿! 在前面几篇文章中,我采用纯数学的方式推导了TCP BBR Startup gain的由来,本文将通过一个BBR动力学模型对Startup gain的值做出直观地解释. BBR动力学模 ...

  10. TCP BBR之Startup gain的另一种推导法以及最新进展

    自从上周有个大半夜帮温州皮鞋厂老板计算了那个2ln22ln⁡2\displaystyle\frac{2}{\ln2}之后,就着这个问题又进行了一些思考,过程中非常感谢BBR的作者之一Neal Card ...

最新文章

  1. is属性用法 vue_Vue中is属性的用法 可以动态切换组件
  2. CyanogenMod源码编译模拟器
  3. Mac下crontab -e没结果的解决办法
  4. Sargable 与 谓语下推 (predicate pushdown) 简介
  5. ICLR最高分论文揭秘模型泛化,GNN是潜力股
  6. [转载] java synchronized静态同步方法与非静态同步方法,同步语句块
  7. libmodbus使用
  8. Vue 从零开始搭建PC端项目完整框架(附GitHub地址和Vue项目执行流程)
  9. mysql删除图书信息,图书管理系统(一):出版社列表增加、删除和编辑
  10. Google Play关键词选词方法及常用选词工具
  11. 内存数据库将数据保存在计算机内存,内存数据库
  12. 12306余票查询(六)——优化页面结构,加入js请求数据部分
  13. 阿里云算力的十年更迭史,重点都在这了!
  14. 深度强化学习篇2:从Playing Atari with Deep Reinforcement Learning 看神经网络的输入,学习的状态空间
  15. 操作系统实验报告_ucore_lab1
  16. 计算机提示无法识别usb,小编教你电脑出现无法识别usb设备怎么办
  17. VIL100数据集处理
  18. Self-Supervised Deep Blind Video Super-Resolution
  19. OCR应用(证件识别、文档识别)
  20. 搜索引擎网址提交入口

热门文章

  1. gis 大屏_大屏简介
  2. 计算机密码的怎么查询,电脑密码如何查看? 手把手教你查看方法
  3. 第1章 数学基础和机器学习问题(范数+矩阵迹+矩阵求导+机器学习框架)
  4. thermal系列(6)-thermal-engine守护进程
  5. java string 深拷贝_探讨java深拷贝
  6. 阿里网盘挂载到本地(Webdav)
  7. wiresshark抓包
  8. 语音特征提取(语谱图Spectrogram,Fbank, MFCC, 及其delta-一阶差分)——python代码
  9. DAS NAS SAM FC
  10. 如何构建企业TPM管理体系?