“经典ECN反馈补全这里排除的通知路径:CE不制造数据缺口,ECE可因首份ACK丢失而持续回显,发送端对同一发送前缀仅作一次拥塞响应。包9同时带CWR与新CE时,接收端先解除旧回显再保留新通知…”
路由器想说“这里开始拥堵”,不一定要先毁掉携带数据的包。ECN让它在合格包上留下拥塞标记,再由接收者回告发送者。数据仍能被正常确认,但发送者要减少压力;这两项事实并不冲突。
形式陈述
固定经典协议与教学范围
本页取RFC3168的经典TCP反馈,并采用已验证勘误3639和5966。沿用TCP的展开字节序号、累计ACK及两个发送前沿u=SND.UNA、n=SND.NXT。只研究已经成功协商ECN、单向数据按序且不丢失、ACK可丢失/复制,且接收端信用始终充足的连接;不处理序号绕回、乱序缺口、快速恢复、超时重传及完整握手回退。
新数据包发送ECT(0)。IP字段四个码点为Not-ECT=00、ECT(1)=01、ECT(0)=10、CE=11;在本文经典语义中,两种ECT均允许被标CE。后来的ECT(1)实验和AccECN反馈有新规范,不能将这里的二值锁存当成它们的实现。[1,§§5、6.1;3]
能力协商是前置合同,不从收到一个ECT数据包反推。经典握手发起SYN置ECE/CWR,接受方SYN-ACK只置ECE;后续回退和异常握手仍须照规范处理,附件不模拟这些连接建立分支。
路由器、接收者、发送者各记什么
路由器收到AQM的“选中通知”后,如果包为ECT且还有存储容量,可以改为CE并保留。Not-ECT包在同一选中事件下丢弃。已有CE不擦除;物理队列满时,即使ECT也须按容量规则丢弃。非拥塞原因的拒绝不能随意换成CE。[1,§5]
接收者保留一个echo位,初始0。每个合法按序数据段先推进累计接收位置,再按以下顺序处理标志:收到CWR先令echo=0;本包若为CE,再令echo=1。发ACK时复制当前echo到ECE。因而同一包同时带CWR和CE,最后仍回显1;新拥塞不能被同包的“已减窗”消息抹掉。[2,3639]
发送者保留guard(上次响应时已发新数据的右端,初始未设)和pending_cwr。处理合法推进ACK a时,若ECE=1,且(guard未设或a>guard),发出一次拥塞响应,将guard设为当前n,并记pending_cwr=true;落在guard以内的重复反馈不再触发响应。旧ACK不让u回退,也不因再次到达而额外减窗。
guard把一次响应覆盖的已发送字节窗口具体化。这个教学判据建立在前述按序、无数据丢失模型上,不声称为任意TCP恢复轨迹规定了唯一通用guard算法。guard内的更多ECE仍表示接收者在回显,只是不生成第二次相同窗口响应。
窗口响应和首次新包
主例使用Reno式拥塞退让中的减小窗口思想:每次被接受的ECN事件令整数字节窗口cwnd减半并向下取整,例如17变8;不做快速恢复的三段临时膨胀,也不重传已收到的数据。附件的受限响应输入要求减窗前cwnd≥4M,输出仍至少2M;本模块不计算ssthresh或普通ACK增长,交回完整拥塞控制器处理。低于该范围必须转交完整规则,不能沿用本页算例冒充全部TCP。[1,§6.1.2]
累计ACK推进后,实际在途字节为n−u。新数据长度ℓ只有在n−u+ℓ≤cwnd及接收信用足够时才可发送;减窗可能使已有在途量暂时超过新窗口,此时停发新增字节,不删除旧在途数据。
pending_cwr只放到随后第一个新数据包,发出后清除;不是每个ACK都发CWR,也不是把它随意放进纯ACK或重传包。若这份数据包丢失,真实TCP需要完整丢失恢复;本任务明确不覆盖这一分支。[2,5966]
直觉
两段反馈各有一次丢失风险
CE从路由器到接收者;ECE从接收者到发送者;CWR再从发送者回到接收者。首个ECE-ACK丢了,接收者继续回显,使后面的ACK还能带回消息。重复回显则要求发送者避免连续把窗口再三减半。
CWR的意思是发送者已经做过一次减窗,并不阻止这个新包又遇到拥塞。先清旧回显、再设置新CE,正好表达“旧事件已响应,新事件仍要报告”。
例子与边界
丢掉首份回显,后面仍能通知
设M=1000B,初始u=0、n=8000、cwnd=8000,八包占据字节区间[0,8000),接收信用足够。第1包被CE,接收者置echo1并发ACK1000/ECE1,故意丢失这份ACK。第2包没被CE,但echo尚未解除,ACK2000仍带ECE1。
发送端收到ACK2000,第一次响应使cwnd由8000降为4000,guard=8000,pending_cwr=true;u推进到2000,在途6000,故不能新增发送。ACK3000后在途5000,仍不能;ACK4000后在途4000,仍没空间;ACK5000后在途3000,才允许再发一个1000B的新包9。
包9占[8000,9000),携CWR且发送后n=9000。此时ACK8000即使还带ECE,也没有越过guard=8000,不再减窗。若错误地对ACK2000、3000、4000各减半,窗口会8000→4000→2000→1000,同一次旧拥塞被重复支付三次。
同一个CWR包又遇到CE
让包9在路上被标CE。它到达时,接收者已经按序收完前八包;先按CWR清echo,再按CE置1,返回ACK9000/ECE1。9000超过旧guard8000,这次属于新发送数据窗口,发送者由4000减到2000,guard=9000,再记pending_cwr。
接着发送未CE的包10,区间[9000,10000),携CWR。接收者清echo并回ACK10000/ECE0。旧ACK8000之后再到,只是旧信息;不能回退累计确认或触发第三次减窗。附件只检验反馈模块,不以最终ECE0宣称链路永远不再拥塞。
丢弃与标记的队列轨迹不同
容量还有一格时,一个被选中的ECT包可以CE后入队,占用加一;相同Not-ECT包被丢,占用不变。下一到达看到的q不同,所以RED平均与后续概率也必须重算。ECN避免了这次数据缺口,没有替路由器变出一个空格。
如果不设guard,只要ECE持续1,每个ACK都可能触发减窗;如果接收者只回显一次,丢掉ACK1000就可能完全丢失通知;如果把同包处理顺序倒成“先CE再CWR”,包9的新拥塞又会被清掉。这三种错误分别发生在发送者状态、反馈可靠性和接收者更新次序。
推论与应用
能证明的是反馈与发送许可
echo满足“最近一次CWR清除后是否又见CE”的锁存含义,同包CE最后生效。guard在每次新响应时设为当时n,且n只增长;因此此后ACK不越过该边界就不会再次响应。合法发送检查又保证每个新发送事件满足当时窗口额度。这些不变量可以逐事件检验。
ACK丢失不会自动破坏数据累计确认,但永远没有后续ACK时也不能保证反馈完成。ECN同样无法强迫恶意或失配的发送端合作;持续超额流量仍须丢弃或限流。有限容量、拥塞反馈、端到端进展是分别需要条件的结论。
留给完整TCP的分支
RFC3168还专门处理cwnd只有一MSS时如何进一步限速,并涉及重传计时器;本例把该输入移交而不继续模拟。真实丢失和ECE交织时要避免对同一窗口双重反应,同时又识别重传包再丢的新增拥塞。旧Reno/RTO页提供其基本对象,本页的按序模型不能替代这些恢复条件。
一次包或ACK事件只更新常数个标志与序号,在有界字算术下为O(1)。保存全部包、确认和拒绝的审核日志另随事件数增长;真实TCP的重组、计时器及载荷复制费用未计入这份反馈模块。完整执行、位翻转迁移与队列比较见排队与反馈终点。
参考资料
- RFC3168: The Addition of Explicit Congestion Notification to IP,§5给码点/容量,§6.1.1给协商,§§6.1.2–6.1.3给发送响应、回显与CWR;本页窗口guard及数值为明示的受限教学接口
- RFC3168已验证勘误,Errata3639明确CE标记的CWR包仍应启动回显,5966明确CWR放在第一个新数据包。读取日期2026-10-09;不将被拒绝的其他报告当规范
- RFC8311,§4给后续实验的放宽;RFC9768,摘要与§1给AccECN的更精细反馈范围。仅用于版本边界,本页不实现这些扩展