Linux tcp_ack 确认处理与 sack_update_reord 重排判断

发布时间:2026/9/14 2:44:02

Linux tcp_ack 确认处理与 sack_update_reord 重排判断 Linux tcp_ack 确认处理与 sack_update_reord 重排判断tcp_ack 是 TCP 输入路径的确认处理核心函数在 tcp_rcv_established 和 tcp_rcv_state_process 中被调用。该函数处理传入 ACK 段所携带的累积确认和选择确认SACK信息负责更新发送窗口、调整拥塞状态、触发 cwnd 恢复以及判断报文重排序程度。tcp_ack 的返回值是累计确认的报文段数量packets_acked为拥塞控制算法提供输入。cstatic int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag){struct tcp_sock *tp tcp_sk(sk);u32 prior_snd_una tp-snd_una;u32 ack_seq TCP_SKB_CB(skb)-end_seq;u32 ack TCP_SKB_CB(skb)-seq;u32 prior_packets tp-packets_out;int acked 0;if (after(ack, tp-snd_una)) {acked tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_state);} else if (ack tp-snd_una) {if (flag FLAG_DSACKING_ACK)tcp_dsack_process(sk, skb, sack_state);tcp_update_wl(tp, ack);}if (tp-packets_out 0 flag (FLAG_SYN_ACKED | FLAG_DATA_ACKED))tcp_cong_control(sk, ack, flg, sack_state.rate, acked);...}tcp_clean_rtx_queue 是确认处理的核心——遍历重传队列sk_write_queue将 end_seq 落在 tcp_skb_cb-seq 到 TCP_SKB_CB(skb)-end_seq 范围内的 skb 移出队列。每个 skb 的 tcp_skb_cb-sacked 标志位决定该 skb 被确认、SACKed、还是 LOST。对于 ACK 确认的 skb调用 __skb_unlink 从重传队列移除并通过 sk_wmem_free_skb 释放 skb。acks 状态机需谨慎处理 D-SACK 检测当 ACK 确认了一段已经 SACKed 的数据tp-duplicate_sack[0] 记录第一个 D-SACK block用于计算 spurious retransmit。SACK 块在 tcp_sacktag_write_queue 中处理该函数被 tcp_ack 调用。每个 SACK block 表示接收端已收到的乱序数据区间。函数从 sk_write_queue 的 tcp_highest_sack 起始遍历标识被 SACK block 覆盖的 skb。cstatic void tcp_sacktag_write_queue(struct sock *sk,const struct sk_buff *ack_skb,u32 prior_snd_una,struct tcp_sacktag_state *state){struct tcp_sock *tp tcp_sk(sk);struct sk_buff *skb;int found_dup_sack 0;int i, first_sack_index;if (!tp-rx_opt.num_sacks)return;state-flag 0;state-fack_count 0;skb tcp_write_queue_head(sk);while (skb skb ! tcp_write_queue_tail(sk)) {if (!tcp_skb_is_write_queue(sk, skb))break;...skb skb-next;}}sack_update_reord 评估重排序程度。当发现 SACK block 覆盖的序列号区间早于已确认数据的末尾则该 SACK 块对应的 skb 在发送路径中序号连续但接收端乱序到达表明发生了 reordering。该函数的核心逻辑是如果被 SACK 确认的 skb 的 TCP_SKB_CB(skb)-seq 小于 tp-snd_una累积确认序列号则该数据段在发送缓冲区中的位置早于最新确认的数据发生了重排。cstatic void sack_update_reord(struct tcp_sock *tp,struct tcp_sacktag_state *state,u32 seq, u32 mss){if (seq_cmp(tp-snd_una, seq) 0) {if (!tp-reord || seq_cmp(tp-reord, seq) 0) {tp-reord seq;state-reord true;}}}tp-reord 字段记录重排序边界用于区分丢包和乱序。如果 ACK/SACK 确认的 skb 序列号大于等于 tp-reord则不触发快速重传。tp-reord 在 tcp_mark_head_lost 中同样被用于丢包判决。这里的关键竞态当接收端延迟发送 SACKDelayed SACK时sender 可能将正常乱序误判为丢包导致 spurious RTO。reord 的初始值为 tp-snd_nxt 2 * MSS在三次握手完成后初始化。tcp_ack 中的 flag 位掩码传递关键信息FLAG_SND_UNA_ADVANCED、FLAG_DATA_ACKED、FLAG_SYN_ACKED、FLAG_DSACKING_ACK、FLAG_ECE、FLAG_LOST_RETRANS 等。flag 通过 tcp_sacktag_write_queue 和 tcp_clean_rtx_queue 累积生成最终传递到 tcp_cong_control。FLAG_ECE 标志决定是否启用 ECN 信号触发 cwnd 的减半而非丢包事件。cstatic void tcp_cong_control(struct sock *sk, u32 ack, u32 flag,const struct rate_sample *rs,int acked){if (flag FLAG_ECE)tcp_enter_cwr(sk);else if (flag FLAG_SND_UNA_ADVANCED)tcp_cwnd_reduction(sk, ack, rs, flag, acked);else if (flag FLAG_DATA_ACKED)tcp_cwnd_application_limited(sk);}dupack重复 ACK计数由 tcp_ack 中的 tp-snd_una 不变但 packets_out 不为零的情形触发。当 tp-snd_una 不前进且 SACK 不含新信息tp-packets_out 与 prior_packets 相等时记录 dupthresh由 RFC 6675 定义为 3。在 reordering 场景下优先使用 SACK 判定而非 dupack 计数跟踪 skb-sacked TCPCB_SACKED_ACKED 的位状态结合 fackets_out由 SACK 确认的 skb 数量决定是否调用 tcp_time_to_recover。一个边界场景是 SACK 块覆盖的数据已经被快速重传此时 tcp_mark_head_lost 可能因为 reord 信息不准确而产生额外的 LOST 标记导致 cwnd 虚幻收缩。为避免此问题tcp_clean_rtx_queue 清除 TCPCB_SACKED_RETRANS 位时需同步检查 seq 是否落入 retrans_hint 区域。如果 retransmitted skb 被确认但未被 sender 记录为有效的 LOSTtcp_sacktag_write_queue 的回溯检测会重置 retrans_stamp防止 RTO 过早触发。
延伸阅读

更多相关文章

2026/9/10 1:08:22

5分钟上手Buzz:彻底改变你的音频转录工作流

5分钟上手Buzz:彻底改变你的音频转录工作流 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz 还在为会议录音整理而…

2026/9/12 19:07:37

JavaScript GIF解码架构解析:gifuct-js高效解决方案实现原理

JavaScript GIF解码架构解析:gifuct-js高效解决方案实现原理 【免费下载链接】gifuct-js Fastest javascript .GIF decoder/parser 项目地址: https://gitcode.com/gh_mirrors/gi/gifuct-js 在Web开发中处理GIF动画时,传统JavaScript库常面临性能…

2026/9/8 6:44:15

C2000 CLA协处理器:架构、中断配置与流水线优化实战

1. CLA核心架构与工作原理深度解析 控制律加速器(CLA)是德州仪器(TI)C2000系列微控制器中一个独立、可编程的32位浮点数学协处理器。它的设计初衷非常明确:将主CPU(C28x)从繁重的实时控制算法计…

2026/9/14 2:43:33

AI论文生成工具:核心技术架构与应用实践

1. 项目概述:AI论文生成工具的核心逻辑"好写作AI"本质上是一个基于关键词驱动的智能内容生成系统,其核心功能是通过语义理解、知识图谱和自然语言生成技术,将用户输入的有限关键词扩展为结构完整的学术论文。这类工具在2023年全球A…

2026/9/14 2:43:33

思特威CIS与汇顶交互传感选型实战指南

1. 项目概述:为什么终端厂商现在必须认真看懂这两家国产传感芯片公司?最近半年,我跑了六家做智能硬件的客户,从TWS耳机厂到扫地机器人ODM,再到车载中控屏方案商,聊下来发现一个共同现象:采购和硬…

2026/9/14 2:43:33

STM32 AI开发流程重构:从代码生成到全链路闭环

1. 这不是“用AI写代码”,而是重构嵌入式开发的底层逻辑“嵌入式软件AI编程”这个标题,很多人第一反应是:让ChatGPT生成几行GPIO初始化代码,再复制粘贴进Keil里编译——这根本不是AI编程,这只是AI代打。我带过27个嵌入…

2026/9/14 2:43:33

Linux嵌入式驱动系统路径:设备树、I2C/CAN与内核模块协同原理

1. 这不是“写个驱动就完事”的事——它是一条贯穿Linux嵌入式系统的完整技术链路你手头有一块RK3568开发板,芯片手册里写着I2C0接了温湿度传感器,CAN总线挂了电机控制器,但ls /dev里啥也没有;你照着《Linux设备驱动开发详解》第3…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码