现有的CC算法受限于操作系统内核的粗粒度信号,需要network fabric的一些visibility。 但是,现有的telemetry-based solution需要changes to the end-host。 利用eBPF,可以运行telemetry-based CC在内核里面。
本篇文章并不是第一篇提出在CCA(拥塞控制算法)里面使用INT的。 但是作者argue,现有的方案并不practical。 它们overhead过大、并不适合brownfield deployment(因为需要特殊的硬件,比如RDMA网卡)、需要对宿主机的网络协议栈进行大幅度修改、并且并不灵活(与某些CCA绑定)
文章基于eBPF和TCP实现自己的方案。 为了访问telemetry,文章使用TCP-INT,一个基于P4的telemetry system来将交换机上原地测量的telemetry插入到packets里面。 这样(按照论文的说法)可以minimize data overhead和computational overheads。
文章主要解决了三个挑战
- 必须适用于不同的网络硬件和协议栈。This requires compatibility with existing protocols and integration into the host network stack
- 现有的方法在每一跳都向packet header里面append telemetry data。但是实际上CCA只需要most congested hop的信息。
- 现有的方式在每一个包都插入telemetry,这会引入额外的计算开销,as it interferes with other parts of the host networking stack
文章还开源了https://github.com/inet-tub/powertcp-linux
Background
eBPF for Congetsion Control
When innovating CCAs, it is difficult to deploy in the wild。 这是因为将CCAs集成到现有的网络协议栈并不容易。 CCP提出了一个将CCA从操作系统中解耦的框架,但是它并不被现在的内核原生支持。
近来,kernel通过STRUCT_OPS的程序类型为CCAs提供了eBPF的方便接口。 eBPF CCA必须提供tcp_congestion_ops里面预先定义好的所有函数。 这个结构里面定义了各种会在网络协议栈里面被触发的钩子。 The most important hook is responsible for updating the CWND, and optionally control a socket's pacing rate, after an ACK was received。
理想情况下,the switch would communicate its instantaneous send rate and queue occupancy。
In-band Network Telemetry
原来的网络功能相对固定,因此网络信息并不能够被很好地使用。 有了P4之后,INT能够实现不需要依赖于manufacturing capacity of major switch vendors。
INT的实现方式有很多,但是主要可以分成两种:Postcards和Embedded。 Postcards不修改数据包,在收到每个数据包的时候都发一个新的包(这个包叫做postcard)。 Embedded的就直接修改数据包了。
INT现在还是有以下几个问题的
- interoperability:INT spec prepends一个新的包头格式到包内,这可能破坏现有的网络协议栈
- data overhead:每跳都添加信息,让包大小随着hop的个数变大
- compute overhead:每个packet的信息会让负责处理telemetry的receiver产生计算开销
INT-based Congestion Control
介绍了一些INT-based的拥塞控制算法,包括HPCC、PowerTCP、PING等等。 但是它们都有一些共同的问题,即并没有被(或者并不容易被)整合到内核里面。
TCP's Third Eye
系统主要可以分成两部分:TCP-INT,用来收集指标、传输网络遥测信号给内核;一个运行在eBPF里面的CCA model。
Seeing with TCP-INT
论文使用TCP-INT进行INT相关的telemetry相关操作。 图1给了TCP-INT的具体的流程。 当一个交换机收到一个数据包之后,它会将telemetry插入到packet里面。 当receiver收到一个数据包之后,它会提取telemetry。 receiver然后会将telemetry echo回去(通常是插入下一个包,比如ACK里面)。 最后sender就能够知道整条链路的情况了。
TCP-INT将相关telemetry插入在TCP option里面。 同时,采集的指标是aggregated的。 也就是说,一个交换机local congestion只在大于包里面记录的时候才会更新。
此外,现有的机制为每个包打tag不仅会增加receiver的computational overhead,同时还会影响generic receive offload。 GRO会合并header相同的包,但是因为option的被修改,会导致GRO失效。 为此,论文使用采样的方式,按照特定频率打tag。
Control Law Framework
没什么好说的(文章介绍的里面的也比较少)。 主要是实现MIMD类型的CC。
Implementation
eBPF Program
eBPF program主要负责三部分的工作。
- 从收到的数据包中提取INT
- 为特定的control law计算输入(比如power for powerTCP)
- 执行control model,更新拥塞窗口和pacing rate
具体介绍了以下几部分的内容(都比较简单,基本都是一段)
- upon ACK:tcp_ack这个函数是整个workflow的入口
- extracing INT:从包里面拿到option信息之后存在SK_STORAGE类型的一个map里面
- packet timestamps:不仅支持kernel timestamps,还支持数据包的timestamps
- calculating f(t):利用INT计算
- updating the window sizes and pacing rate:顾名思义
Kernel Patches
提交了两个patch修改两个问题:
- kernel需要同时实现cong_avoid和cong_control,即使在前者没用而且后者实现了的情况下
- eBPF程序并不能够修改socket pacing rate