TCP’s Third Eye: Leveraging eBPF for Telemetry-Powered Congestion Control

现有的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。

文章主要解决了三个挑战

  1. 必须适用于不同的网络硬件和协议栈。This requires compatibility with existing protocols and integration into the host network stack
  2. 现有的方法在每一跳都向packet header里面append telemetry data。但是实际上CCA只需要most congested hop的信息。
  3. 现有的方式在每一个包都插入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主要负责三部分的工作。

  1. 从收到的数据包中提取INT
  2. 为特定的control law计算输入(比如power for powerTCP)
  3. 执行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