Skip to main content

7. 拥塞控制 (Congestion Control)

SCTP使用类似于TCP的拥塞控制机制来避免网络拥塞和确保公平的网络资源共享。

7.1. SCTP与TCP拥塞控制的差异 (SCTP Differences from TCP Congestion Control)

虽然SCTP的拥塞控制基于TCP的机制,但存在以下关键差异:

7.1.1. 多宿主和多路径

SCTP支持多宿主端点,每个目的传输地址维护独立的拥塞控制参数:

  • 每个目的地的cwnd: 每个路径有自己的拥塞窗口
  • 每个目的地的ssthresh: 每个路径有自己的慢启动阈值
  • 每个目的地的RTO: 每个路径有自己的重传超时

这允许SCTP在不同路径上独立地进行拥塞控制。

7.1.2. 基于TSN的确认

SCTP使用TSN而非字节序列号进行确认。这意味着:

  • 拥塞窗口以字节为单位维护
  • SACK确认的是TSN范围
  • cwnd更新基于确认的字节数而非TSN数量

7.1.3. 多流传输

SCTP的多个流共享同一个关联的拥塞控制参数。流之间没有单独的拥塞控制,这确保了:

  • 所有流公平共享带宽
  • 避免单个流垄断资源

7.2. SCTP慢启动和拥塞避免 (SCTP Slow-Start and Congestion Avoidance)

SCTP的拥塞控制算法遵循TCP的慢启动和拥塞避免原则。

7.2.1. 初始化和重启

当关联首次建立或路径在空闲后重新启动时:

cwnd = min(4*MTU, max(2*MTU, 4380字节))
ssthresh = 对等方的a_rwnd

注意: 初始cwnd的计算确保至少可以发送2个完整的数据包,但不超过4个MTU大小的数据包。

7.2.2. 慢启动阶段

在慢启动期间(cwnd <= ssthresh):

当收到新数据的SACK时:

cwnd = cwnd + min(确认的字节数, MTU)

规则:

  • cwnd每次最多增加一个MTU
  • 只有当所有确认的数据都是在当前cwnd下发送时才增加
  • 当cwnd达到或超过ssthresh时,进入拥塞避免阶段

7.2.3. 拥塞避免阶段

cwnd > ssthresh时:

使用适当字节计数 (Appropriate Byte Counting, ABC):

每个RTT内:
partial_bytes_acked = partial_bytes_acked + 确认的字节数

当 partial_bytes_acked >= cwnd 时:
cwnd = cwnd + MTU
partial_bytes_acked = partial_bytes_acked - cwnd

目标: 每个RTT增加cwnd约1个MTU。

7.2.4. 拥塞检测和响应

检测拥塞的信号:

  1. 重传超时 (RTO到期)
  2. 快速重传 (收到4个重复SACK)

响应RTO超时:

ssthresh = max(cwnd/2, 4*MTU)
cwnd = 1*MTU
partial_bytes_acked = 0

响应快速重传:

ssthresh = max(cwnd/2, 4*MTU)
cwnd = ssthresh
partial_bytes_acked = 0

7.2.5. 空闲期后的处理

如果目的地在RTO时间内没有数据传输(空闲):

选项1 (推荐):

cwnd = max(cwnd/2, 4*MTU)

选项2 (保守):

cwnd = min(4*MTU, max(2*MTU, 4380字节))

这防止了在长时间空闲后突然发送大量数据。

7.3. 路径MTU发现 (Path MTU Discovery)

SCTP端点应该 (SHOULD) 使用路径MTU发现(如[RFC4821]中定义的分组层PMTUD)来:

  • 确定到目的地的最大可用MTU
  • 避免IP分片
  • 优化数据传输效率

7.3.1. PMTU发现过程

  1. 初始MTU: 使用保守的初始值(通常是576字节对于IPv4,1280字节对于IPv6)

  2. 探测更大的MTU:

    • 发送带有"Don't Fragment"标志的数据包
    • 如果成功,尝试更大的MTU
    • 如果失败(收到ICMP "Packet Too Big"),使用较小的MTU
  3. 周期性重探测: 定期尝试更大的MTU,以适应路径变化

7.3.2. MTU更新对拥塞控制的影响

当PMTU增加时:

cwnd = (cwnd / 旧MTU) * 新MTU
ssthresh = (ssthresh / 旧MTU) * 新MTU

当PMTU减少时:

cwnd = (cwnd / 旧MTU) * 新MTU
ssthresh = (ssthresh / 旧MTU) * 新MTU
partial_bytes_acked = min(partial_bytes_acked, cwnd)

这确保了拥塞控制参数与MTU大小保持一致的关系。

7.3.3. 失败处理

如果PMTU发现失败或不可用:

  • 使用保守的MTU值
  • 不使用"Don't Fragment"标志
  • 允许IP层进行分片

总结

SCTP的拥塞控制设计考虑了以下关键因素:

  1. 多路径支持: 每个路径独立的拥塞控制
  2. TCP友好性: 与TCP公平共享网络带宽
  3. 多流效率: 避免队头阻塞同时保持拥塞控制
  4. 路径自适应: 通过PMTU发现优化传输

这些机制确保SCTP既能高效利用网络资源,又能与其他流量公平共存。