默认情况下sysctl_tcp_recovery的值为1(TCP_RACK_LOSS_DETECTION),也可通过PROC文件:/proc/sys/net/ipv4/tcp_recovery进行修改,如果设置了标志位TCP_RACK_NO_DUPTHRESH,表明RACK不使用重复ACK阈值(DupAck Threshold),默认未设置此标志。

#define TCP_RACK_LOSS_DETECTION  0x1 /* Use RACK to detect losses */
#define TCP_RACK_STATIC_REO_WND  0x2 /* Use static RACK reo wnd */
#define TCP_RACK_NO_DUPTHRESH    0x4 /* Do not use DUPACK threshold in RACK */$ cat /proc/sys/net/ipv4/tcp_recovery
1

如下tcp_rack_reo_wnd函数,如果当前套接口没有观察到乱序发生,并且当前处于拥塞恢复状态(TCP_CA_Recovery)或者TCP_CA_Loss拥塞丢失状态,返回乱序窗口零,以便尽快的确认丢失报文,触发重传。反之,如果拥塞状态不处于以上的两种状态,RACK开启了DUPTHRESH的支持,并且SACK确认报文数量超过了乱序等级,很有可能发生了丢包,接下来可能会进入TCP_CA_Recovery或者TCP_CA_Loss状态,也返回值为零的乱序窗口,以便RACK作出快速响应。

否则,函数tcp_rack_reo_wnd返回正常的乱序窗口。

static u32 tcp_rack_reo_wnd(const struct sock *sk)
{struct tcp_sock *tp = tcp_sk(sk);if (!tp->reord_seen) {/* If reordering has not been observed, be aggressive during* the recovery or starting the recovery by DUPACK threshold.*/if (inet_csk(sk)->icsk_ca_state >= TCP_CA_Recovery)return 0;if (tp->sacked_out >= tp->reordering &&!(sock_net(sk)->ipv4.sysctl_tcp_recovery & TCP_RACK_NO_DUPTHRESH))return 0;}/* To be more reordering resilient, allow min_rtt/4 settling delay.* Use min_rtt instead of the smoothed RTT because reordering is* often a path property and less related to queuing or delayed ACKs.* Upon receiving DSACKs, linearly increase the window up to the* smoothed RTT.*/return min((tcp_min_rtt(tp) >> 2) * tp->rack.reo_wnd_steps, tp->srtt_us >> 3);

如下丢失报文检查函数,如果当前报文的发送时间戳加上最近测量的RTT和乱序窗口时长,小于当前TCP时间,即认为此报文已经丢失。以上函数将乱序窗口时长设置为0,报文更容易被认定为丢失。

static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout)
{*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);.../* 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);

如下tcp_rack_mark_lost函数,根据以上tcp_rack_detect_loss函数返回的timeout超时时间值,设置ICSK_TIME_REO_TIMEOUT定时器。

void tcp_rack_mark_lost(struct sock *sk)
{...tcp_rack_detect_loss(sk, &timeout);if (timeout) {timeout = usecs_to_jiffies(timeout) + TCP_TIMEOUT_MIN;inet_csk_reset_xmit_timer(sk, ICSK_TIME_REO_TIMEOUT,timeout, inet_csk(sk)->icsk_rto);

如下定时器到期处理函数,如果tcp_rack_detect_loss函数标记了新的丢失报文,函数tcp_xmit_retransmit_queue将进行立即重传。

void tcp_rack_reo_timeout(struct sock *sk)
{struct tcp_sock *tp = tcp_sk(sk);u32 timeout, prior_inflight;prior_inflight = tcp_packets_in_flight(tp);tcp_rack_detect_loss(sk, &timeout);if (prior_inflight != tcp_packets_in_flight(tp)) {if (inet_csk(sk)->icsk_ca_state != TCP_CA_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);

除了以上的乱序超时处理函数之外,在函数tcp_identify_packet_loss中,也调用tcp_rack_mark_lost标记丢失报文。

static void tcp_identify_packet_loss(struct sock *sk, int *ack_flag)
{struct tcp_sock *tp = tcp_sk(sk);if (tcp_rtx_queue_empty(sk))return;if (unlikely(tcp_is_reno(tp))) {...} else if (tcp_is_rack(sk)) {u32 prior_retrans = tp->retrans_out;tcp_rack_mark_lost(sk);if (prior_retrans > tp->retrans_out)*ack_flag |= FLAG_LOST_RETRANS;

以上函数的调用位于ACK处理函数tcp_fastretrans_alert中,对应于最开始的函数tcp_rack_reo_wnd,如果套接口位于TCP_CA_Recovery或者TCP_CA_Loss状态,标记丢失报文尽快重传。否则套接口处于其他的拥塞状态,tcp_time_to_recover函数将尽快判断进入TCP_CA_Recovery状态。

static void tcp_fastretrans_alert(struct sock *sk, const u32 prior_snd_una,int num_dupack, int *ack_flag, int *rexmit)
{switch (icsk->icsk_ca_state) {case TCP_CA_Recovery:...tcp_identify_packet_loss(sk, ack_flag);break;case TCP_CA_Loss:tcp_process_loss(sk, flag, num_dupack, rexmit);tcp_identify_packet_loss(sk, ack_flag);.../* fall through */default:...tcp_identify_packet_loss(sk, ack_flag);if (!tcp_time_to_recover(sk, flag)) {tcp_try_to_open(sk, flag);return;}.../* Otherwise enter Recovery state */tcp_enter_recovery(sk, (flag & FLAG_ECE));fast_rexmit = 1;}...*rexmit = REXMIT_LOST;

如果在tcp_rack_detect_loss函数中标记了丢失报文,lost_out有值,进入TCP_CA_Recovery拥塞状态,重传丢失报文(REXMIT_LOST)。

static bool tcp_time_to_recover(struct sock *sk, int flag)
{struct tcp_sock *tp = tcp_sk(sk);/* Trick#1: The loss is proven. */if (tp->lost_out)return true;

内核版本 5.0

RACK与重复ACK相关推荐

  1. TCP重复ACK与乱序

    介绍 TCP的一大常见问题在于重复ACK与快速重传.这一现象的发生也是由于性能问题,本章讨论如何发现这一问题以及他们意味着什么. 另一个常见问题是前一片段丢失以及乱序片段.某些情况下,这一现象喻示着故 ...

  2. TCP快速重传为什么是三次冗余ack,这个三次是怎么定下来的?

    先理解ACK的基本工作原理,当发送端发送第N-1个包后,接收端答复的ACK序列号实际上跟发送端发送下一个包,也就是第N个包的序列号一致. 假设有个主机ISN是5000,发送500字节报文至接收方.一旦 ...

  3. linux重置网络协议,Linux 内核网络协议栈 ------ tcp_ack 函数处理接收到的ACK包之后 ....

    注意 tcp_ack 是来处理接收到的ACK的,那么到底怎么去做呢?看下面: 先还上把tcp_sock的结构放在这里,下面一些数据的分析需要用到: structtcp_sock { /* inet_c ...

  4. TCP快速重传为什么是三次冗余ack

    先理解ACK的基本工作原理,当发送端发送第N-1个包后,接收端答复的ACK序列号实际上跟发送端发送下一个包,也就是第N个包的序列号一致. 重复ACK是指在接收方收到乱序报文时,所发出的一类TCP报文. ...

  5. java中shutdownoutput_Java Socket shutdownOutput和shutdownInput是否为“Duplicate ACK#:1”

    起初,我很抱歉对以下问题做了长时间的解释. 我有一个简单的TCP客户端.以下是代码片段: ...... ouputStream = socket.getOutputStream(); . ..... ...

  6. 计算机网络sequence number,TCP协议中SequenceNumber和Ack Numbe

    Sequence Number lzyws7393074532892018-04-25 Number Sequence qq_391789932452017-09-21 理解TCP序列号(Sequen ...

  7. TCP-F(orward)ACK:植入快速重传灵魂的强制快速重传

    纸上学来终学浅,绝知此事要躬行. 今日和友人争辩快速重传,只拿着书本上的东西和人对飙近20分钟,还自认为略有取胜,真是汗颜加羞愧. 中文版计算机网络,书上还写着接收到3次重复ACK启用快速重传.TCP ...

  8. TCP数据接收之ACK的处理

    在TCP输入数据段的处理过程中,如果发现输入段携带了ACK信息,则会调用tcp_ack()进行ACK相关的处理.实际中,ACK信息总是会携带的,因为携带ACK不需要任何的附加开销,所以对于输入的每一个 ...

  9. ​TCP 拥塞控制详解

    作者:engleliu,腾讯 PCG 开发工程师 本文主要介绍 TCP 拥塞控制算法,内容多来自网上各个大佬的博客及<TCP/IP 详解>一书,在此基础上进行梳理总结,与大家分享.因水平有 ...

  10. TCP基础知识 复习

    前言 说来惭愧,大二时候学的计算机网络好多都不太记得了,不过还好有认真学过,捡起来也挺快的,就是对于现在业界中使用的网络算法的不是很懂: 1 TCP报文段结构 1.1 序号和确认号 序号,是报文段首字 ...

最新文章

  1. Python:Scrapy实战项目手机App抓包爬虫
  2. 数据中心行业人士如何进行继续教育
  3. Xcode 8 控制台输出大量不用的log的问题解决NSLog失效的解决
  4. 打开高效文本编辑之门_Linux Awk之条件判断与循环
  5. Oracle顶级认证OCM考试实战总结
  6. linux定时备份mysql数据并同步到其他服务器
  7. 洛谷 P2756 飞行员配对方案问题 (二分图/网络流,最佳匹配方案)
  8. 关于Mysql java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)的问题...
  9. 从Ant Build演进Gradle Build:导入Ant Build文件
  10. 微软服务器配置核查,注册表配置检查
  11. 键盘事件与JS Filter
  12. typora代码块语言linux命令,typora工具的使用以及MarkDown语法
  13. 一款软件测试脚本生成工具
  14. 中美线径对照表_线径与线号对照表
  15. ISO19000-2000标准(转载)
  16. gtest基础使用01:编写第一条单元测试用例
  17. 计算机专业自我简介50字,2021年个人简历自我评价50字
  18. 新年新气象,新的一年新的开始,给自己定个小小的目标,以此为证
  19. [分享]包饺子全攻略
  20. java读取pdf签名_Java 获取PDF中的数字签名信息

热门文章

  1. SpringBoot基础-Environment解析
  2. 快速上云(手把手教你把项目同步上云)
  3. QT MSVC2017 64-bit 打开Access数据库【亲测可用】
  4. 913_emacs中使用restart-emacs
  5. php做seo优化,php做seo优化能力有哪些
  6. SPL lookup
  7. TPM分析笔记(二)TPM2.0 规范文档
  8. 【EXLIBRIS】#小词旮旯# 004 Camera
  9. MSTAR648方案遥控器配置
  10. python爬取在线视频思路,用python实现多线程爬取影视网站全部视频方法【笔记】...