tcp在kernel-4.3内核中加入了RACK机制,用从时间维度上来判断丢包,用最新被(S)ACK确认的数据包为基准,其发送时间减去一个乱序时间窗口之前的数据包如果没有收到反馈,就可以判断为丢失了。主要为了解决尾部丢包和二次重传的问题。
旧版RACK一个比较明显的缺点就是容易误判,尤其是在重传数据包被(S)ACK确认,是否更新最近被确认的数据包问题上,只是简单用判断重传到被确认的时间是否大于min_rtt。如果min_rtt很小,连接又有乱序情况,很容易误判一大片丢包,造成传输效率低下的问题。
当然,旧版的RACK还存在其他问题,比如时间窗口值为(1ms,min_rtt/4)的最大值,几乎可以认为是一个固定的值,当发现误判时,收到客户端反馈回来的D-SACK信息,并不能动态的调节这个乱序时间窗口。其次,RACK的另一个好处是解决尾部丢包问题,但是这是ack驱动的,每次丢包判断只能在更新了最近被(S)ACK之后进行。如果某一次判定,最新更新数据包的发送时间与该发送时间减去乱序时间窗口的时间区间,还剩下两三个数据包未能判断丢失,只能等下次满足判断条件的ack到来。
为了解决上述所说的三个问题,linux-4.14的内核中改进了RACK实现机制,使其变成一个更高效的丢包判断机制,以至于可以取消FACK这种为了较为激进的机制。首先加入了REO定时器,该定时器是复用RTO定时器,通过事件event来区分。定时器的处理函数tcp_write_timer_handler()。
void tcp_write_timer_handler(struct sock *sk)
{.......event = icsk->icsk_pending;switch (event) {case ICSK_TIME_REO_TIMEOUT:tcp_rack_reo_timeout(sk);break;case ICSK_TIME_EARLY_RETRANS:tcp_resume_early_retransmit(sk);break;......}
}
当某次判断的乱序时间窗口内只要有一个包未能判断丢包,则会启动这个REO定时器,该定时器的超时时间就是乱序时间窗口值,定时器处理函数中调用tcp_rack_reo_timeout()判断数据包丢失,就解决了ack驱动,有效的解决了尾部丢包问题。
void tcp_rack_reo_timeout(struct sock *sk)
{struct tcp_sock *tp = tcp_sk(sk);struct skb_mstamp now;u32 timeout, prior_inflight;skb_mstamp_get(&now);prior_inflight = tcp_packets_in_flight(tp);tcp_rack_detect_loss(sk, &now, &timeout);/*判断丢包*/if (prior_inflight != tcp_packets_in_flight(tp)) {/*满足条件,说明rack有新判断出丢包*/if (inet_csk(sk)->icsk_ca_state != TCP_CA_Recovery) {/*之前未丢包,切换到recovery状态*/tcp_enter_recovery(sk, false);if (!inet_csk(sk)->icsk_ca_ops->cong_control)tcp_cwnd_reduction(sk, 1, 0);}/*有判断出新丢包,则进行重传*/tcp_xmit_retransmit_queue(sk);}if (inet_csk(sk)->icsk_pending != ICSK_TIME_RETRANS)/*重置为RTO定时器*/tcp_rearm_rto(sk);
}
判断丢包函数处理过程
static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout)
{struct tcp_sock *tp = tcp_sk(sk);struct sk_buff *skb, *n;u32 reo_wnd;*reo_timeout = 0;reo_wnd = tcp_rack_reo_wnd(sk);/*获取乱序时间窗口值*/list_for_each_entry_safe(skb, n, &tp->tsorted_sent_queue,tcp_tsorted_anchor) {/*遍历传输队列*/struct tcp_skb_cb *scb = TCP_SKB_CB(skb);s32 remaining;/* Skip ones marked lost but not yet retransmitted */if ((scb->sacked & TCPCB_LOST) &&!(scb->sacked & TCPCB_SACKED_RETRANS))continue;/*忽略已经标记丢失但未重传的skb*//*已经判断完最近被(s)ack确认skb的之前所有的包*/if (!tcp_rack_sent_after(tp->rack.mstamp, skb->skb_mstamp,tp->rack.end_seq, scb->end_seq))break;/* A packet is lost if it has not been s/acked beyond* the recent RTT plus the reordering window.*/remaining = tcp_rack_skb_timeout(tp, skb, reo_wnd);/*小于等于零,可以判断为丢包,大于零,为需要在额外等待的时间*/if (remaining <= 0) {tcp_mark_skb_lost(sk, skb);list_del_init(&skb->tcp_tsorted_anchor);} else {/* Record maximum wait time *//*记录需要等待最长的额外时间,用该值重置REO定时器*/*reo_timeout = max_t(u32, *reo_timeout, remaining);}}
}
时间窗口值是第二比较大的改变,时间窗口值不在是max(1ms, min_rtt/4)这样比较固定的值,是可以根据客户端反馈回来的D-SACK信息进行动态调整的,并且是以轮数为单位进行调整。当某一轮收到一个D-SACK数据包,就将时间窗口增加一个min_rtt/4,当然时间窗口值不能超过当前srtt的值,最大可以增加到64min_rtt的时间窗口值。当连续十六轮都没有再收到过D-SACK数据包,就将时间窗口值重置为min_rtt/4。这部分代码主要在tcp_recovery.c的函数tcp_rack_update_reo_wnd()
void tcp_rack_update_reo_wnd(struct sock *sk, struct rate_sample *rs)
{struct tcp_sock *tp = tcp_sk(sk);/*TCP_RACK_STATIC_REO_WND为0x02,如果设置了该值,就回到旧版的静态时间窗口功能,默认是开启0x01*/if (sock_net(sk)->ipv4.sysctl_tcp_recovery & TCP_RACK_STATIC_REO_WND ||!rs->prior_delivered)return;/* Disregard DSACK if a rtt has not passed since we adjusted reo_wnd */if (before(rs->prior_delivered, tp->rack.last_delivered)) /*刚调整完乱序时间窗口,还未经过一轮,则忽略处理改d-sack*/tp->rack.dsack_seen = 0;/* Adjust the reo_wnd if update is pending */if (tp->rack.dsack_seen) {tp->rack.reo_wnd_steps = min_t(u32, 0xFF,tp->rack.reo_wnd_steps + 1);/*将时间窗口增加一个min_rtt/4*/tp->rack.dsack_seen = 0;tp->rack.last_delivered = tp->delivered;tp->rack.reo_wnd_persist = TCP_RACK_RECOVERY_THRESH;/*重置为16轮*/} else if (!tp->rack.reo_wnd_persist) {/*连续16轮没再收到D-SACK信息,则认为网络乱序已经变好,将时间窗口值变小*/tp->rack.reo_wnd_steps = 1;}
}
新版rack机制相比之下,确实有很大的改善,但是动态调整机制需要客户端支持D-SACK机制,作者patch中提到说大部分的机器都支持D-SACK机制,就我司服务端抓取的日志来看,未支持的D-SACK机制机器还是有一定的占比的。其次,服务端只要是收到了D-SACK就认为是因为我们乱序时间窗口值不够大造成的误判,所以调大了这个值,但可能我们使用了其他的判断丢包机制造成的误判。最后,连续十六轮未发现D-SACK机制,就马上将reo_wnd_steps重置为1,也就是时间窗口值设置为min_rtt/4。之前乱序reordering更新也没有说连续十几轮没发现乱序就减小当前乱序值,直接将降回初始值,是不是太乐观了,可以考虑改稳妥些,连续十六轮未发现新的D-SACK,将reo_wnd_steps减半。

一个更高效的RACK机制相关推荐

  1. 【数据科学】 推荐一个更高效的数据清洗方法,建议收藏

    今天来分享一个高效率的数据清洗的方法,毕竟我们平常在工作和生活当中经常会遇到需要去处理杂七杂八的数据集,有一些数据集中有缺失值.有些数据集中有极值.重复值等等. 01 导入库和读取数据 我们首先导入所 ...

  2. 多任务学习,如何设计一个更好的参数共享机制?| AAAI 2020

    2019-12-26 05:44:43 作者 | 孙天祥 编辑 | 刘萍 原文标题:稀疏共享:当多任务学习遇见彩票假设 本文介绍了复旦大学邱锡鹏团队在AAAI 2020 上录用的一篇关于多任务学习的工 ...

  3. hutool的定时任务不支持依赖注入怎么办_设计一个任务调度算法,时间轮算法,比优先队列更高效...

    当年我还是个学生的时候,有一次去参加欢聚时代的一个面试,有一道面试题记忆尤新,让你来实现一个定时任务,你会怎么做?为了简化问题,我们只用考虑内存方案,不用考虑数据持久化. 数组法 最简单的,我们可以把 ...

  4. 微服务平台(Micro Service Platform : MSP)旨在提供一个集开发、测试、运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效。...

    微服务平台(Micro Service Platform : MSP)旨在提供一个集开发.测试.运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效. MSP采用业界 ...

  5. pushd 命令,了解一下! 一个比 cd 更高效的目录切换命令

    第一篇博客,写点自己一直很想分享的东西! 熟悉基于Linux内核所衍生的各种发行版(RedHat, Centos, Fedora)操作系统的各位大佬,肯定对cd命令非常了解,知道它是用于目录切换的,今 ...

  6. Adaptive Execution让Spark SQL更高效更好用

    本文所述内容均基于 2018年9月17日 Spark 最新 Spark Release 2.3.1 版本,以及截止到 2018年10月21日 Adaptive Execution 最新开发代码.自动设 ...

  7. c语言c2182是什么错误,C语言中一种更优雅的异常处理机制

    上一篇文章对C语言中的goto语句进行了较深入的阐述,实际上goto语句是面向过程与面向结构化程序语言中,进行异常处理编程的最原始的支持形式.后来为了更好地.更方便地支持异常处理编程机制,使得程序员在 ...

  8. 更强、更稳、更高效:解读 etcd 技术升级的三驾马车

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 陈星宇(宇慕 ...

  9. CVPR 2020 | 自适应聚合网络AANet:更高效的立体匹配

    ‍‍ ©PaperWeekly 原创 · 作者|张承灏 单位|中科院自动化所硕士生 研究方向|双目深度估计 本文介绍的是中科大团队在 CVPR 2020 上提出的一种高效立体匹配网络--自适应聚合网络 ...

  10. pyppeteer:比selenium更高效的爬虫利器

    pyppeteer github地址:https://github.com/miyakogi/pyppeteer pyppeteer 英文文档地址: https://miyakogi.github.i ...

最新文章

  1. 2022-2028年中国加密货币交易所市场研究及前瞻分析报告
  2. Android P 电量管理,Android P亮点汇总:更智能 更简单
  3. received packet with own address as source address
  4. arduino 休眠 节能_Arduino低功耗掉电模式看门狗唤醒
  5. 关于LIMIT(超出界限时,SQL执行也没有问题,而且结果集中只会到有数据的最后一条记录,不会出现空,已经过测试)
  6. mysql游标是什么特性_[转]MySQL游标特性
  7. 国际音标的HTML实体对照表
  8. macOS Monterey兼容哪些Mac电脑?
  9. 看拉扎维《模拟CMOS集成电路设计》的一些总结和思考(九)——运算放大器
  10. CAD线型设置:CAD软件中如何加粗曲线?
  11. 教你用Axure绘制三级菜单
  12. 软件测试睡眠原理,测一测你的睡眠质量
  13. java 小说系统_java 实现小说管理系统
  14. jQuery 效果 ——fadeIn() 方法、fadeOut() 方法
  15. 地图可视化 - 气泡点图
  16. 梅科尔工作室--梁嘉莹-鸿蒙笔记3
  17. 华为HCIE安全之常用的局域网攻击
  18. Hbuildx 无法运行项目的问题
  19. 【单目摄像头测量距离:相似三角形法】
  20. 优势分析- 性格测试

热门文章

  1. HDFS dfsclient读文件过程 源码分析
  2. js中的this指向问题
  3. 儿童吹泡泡水简单配方_请问儿童吹泡泡液如何制作?
  4. 计算机毕业设计ssm基于网络安全维护的机房设备管理19rya系统+程序+源码+lw+远程部署
  5. 如何提高团队管理能力10
  6. 汽车电子嵌入式相关知识
  7. [gdc17]寒霜引擎的HDR渲染探索
  8. 4和2大于号小于号箭头那边_‘’口诀化‘’教学之二――大于号和小于号
  9. opc ua与opc da区别_OPC,OPCDA,OPCUA
  10. 从零搭建Angular10项目