6.5 Ingress/Egress Queue
Last updated
Last updated
前面的所有讨论,都是在网络内部(即本章描述的AQM算法)和网络边缘(即前几章描述的基于TCP的算法)的拥塞控制方法之间划清界限,分别描述。但这条线并不一定那么清晰。为了看清这一点,你只需要把端到端路径想象成在发送主机的内核/设备接口处有一个入向队列,在接收主机的设备/内核接口处有一个出向队列。这些边缘队列可能会随着虚拟交换机和虚拟网卡越来越普遍,而变得越来越重要。
令人困惑的是,从网络路径的角度来看,“入向队列”实际上是发送主机上的出向(egress)队列;而“出向队列”从网络路径的角度来看,则是接收主机上的入向(ingress)队列。如图40 所示:我们使用了入向(ingress)和出向(egress)这两个术语,是站在网络的角度,而不是终端主机的角度。
网络的角度在图40中得到了展示,这两个队列都位于TCP之下,在端到端网络路径上提供了另一个可以注入拥塞控制逻辑的位置。CoDel和ECN就是这个想法的例子:它们已经在Linux内核的设备队列级别上实现了。
这里的一个问题是数据包究竟是在入向队列处还是在出向队列处被丢弃?在发送主机的入向队列处丢弃(即在发送时),TCP会在 Write函数的返回值中得到通知,这会使其“忘记”它已经发送了该数据包。虽然TCP会因为写入失败而减小其拥塞窗口,但它会再次发送此数据包。相比之下,在接收主机的出向队列处丢包意味着TCP发送者直到使用其标准机制之一(例如,三个重复ACK或超时)检测到丢包之前都不知道应该重新传输数据包。当然,如果出向队列实现了ECN就会有帮助。
在讨论更广泛的拥塞控制背景时,我们可以做出两个有趣的观察。一是Linux提供了一种便捷且安全的方法来注入新代码,包括拥塞控制逻辑,即使用 eBPF。eBPF也在许多其他场景中成为一项重要技术。拥塞控制的标准内核API已经被移植到eBPF上,而且大多数现有的拥塞控制算法也被移植到了这个框架中。通过绕过部署Linux内核等相关的繁琐工作,这简化了实验新的或者其他现存的拥塞控制算法的任务。
更多阅读:The Linux Kernel. BPF Documentation.
第二个观察结果是,通过明确暴露入口/出口队列给决策进程,我们为构建一个拥塞控制机制打开了一扇门,该机制包含一个“决定何时发送数据包”的组成部分,以及一个“决定是排队还是丢弃数据包”的组成部分。我们将在7.1节中介绍On-Ramp时,介绍一种使用这两个组件一个创新的方法。