TAS: TCP Acceleration as an OS Service 论文记录

TAS: TCP Acceleration as an OS Service

摘要

随着数据中心网络的速度增快,许多CPU周期被用于处理TCP包,本文的目的就在于将CPU从繁重的TCP包处理中解放出来。现有的方法有自定义TCP协议栈,或者将包的处理卸载到专用的硬件。但是这些方法在安全性、通用性方面不完全可取。

作者提出TAS(TCP Acceleration as an OS Service ),即是将常见的TCP处理逻辑分离出来,并且放在专用的CPU上来做,将其作为一种服务。作者分离的常见逻辑即是TCP的快路径执行方式,由于大多数的情况都是快路径发送,所以这种做法相当于删除了大部分冗余代码和判断。但是仍然支持所有的功能和TCP堆栈。除此之外,为了提高性能,TAS还提供动态分配,可以动态分配CPU数量处理任务,这取决于流量负载均衡。TAS最多可将吞吐量提高90%,尾部延迟降低57%。

介绍

现有的主要矛盾是:CPU的处理速度停滞不前,硬件的发展处于一个停滞状态,然而数据中心需求高吞吐量低延迟的网络,并且又要通过TCP来实现可靠保序,不丢包的传输,而大量的TCP处理占用CPU周期导致了速度低下。

作者研究TCP的开销发现,主要是如下四个方面:
1、在与应用程序相同的处理器上运行,这样会引发系统调用开销并轮询应用程序共享的L1,L2和转换缓存
2、它们在多个缓存线上传播每个连接状态,导致错误共享并降低缓存效率
3、它们共享机器中所有处理器内核的状态,从而导致高速缓存一致性和锁定开销
4、执行整个TCP状态机,导致有过多分支和判断,无法批处理等

解决思路:TCP虽然是一个比较复杂的传输协议,但常见的应用案例相对简单,例如在数据中心,数据包几乎不会在IP层分段,数据包也基本上是顺序到达,所以能否基于这种情况,来消除现有的开销?

TAS将快路径的处理从整个的OS kernel中分离出来,并使用专用的CPU,它只保存最基本、必要的状态信息。快路径直接从用户级队列中取数据包,非特权应用程序库代码在这些快速路径队列之上实现POSIX套接字抽象,允许TAS对应用程序透明操作。

TAS的另外一个好处是现有的情形是,应用程序和TCP堆栈共用CPU,对于网络密集型的应用,相比较于应用的处理,更多的CPU周期被用于TCP栈的开销,所以这种共享CPU的方式,限制了TCP处理的拓展性。TAS就不仅可以将TCP处理从cache和TLB的污染中隔离出来,还可以独立地进行扩展。

背景

当常见的TCP包的处理逻辑从不常见的代码逻辑中分离,并且用专用的设备和核来做时,它可以被加速。作者首先讨论了传统软件网络协议栈和TCP硬件卸载所做的权衡。然后量化了Linux内核,IX OS和TAS中使用的TCP堆栈的这些权衡。

单片、内核
这是最常见的的设计方式,在软件中作为单个的块或者代码实现所有功能,具有复杂的模块,每个模块实现协议栈的部分功能,模块之间通过函数调用和软件中断互连,并且涉及特权模式的切换,应用程序级和栈级数据包的区分。这样做的可扩展性受到了限制,但是安全性高,代码和数据的覆盖范围广。

Kernel bypass
这种方式减轻了内核堆栈的保护开销,它将数据包处理分为可信的控制平面和不可信的数据平面,其中控制层面在内核中做处理连接和保护设置,数据平面在现有连接上进行数据包处理和将数据递交给应用程序。这种方式需要我们根据应用程序定制网络协议栈,去掉不需要的功能来提高效率,但是这种方式的缺点是,除了粗粒度速率限制和防火墙之外,无法控制低级传输协议行为,例如拥塞响应。尤其在多连接中,数据传输可能产生拥堵。

Protected kernel bypass(笔者没听说过的一种方式)
为了解决可信任问题,IX利用硬件CPU虚拟化来插入中间保护层,以客户内核模式运行网络堆栈,而OS内核在主机内核模式下执行。这种方式可以部署可信的网络协议栈,同时允许为每一个应用程序定制和进行简化,但是这样又引入了新的开销。

NIC offload
过去已经提出了各种TCP卸载引擎。 这些引擎提供各种拆分或TCP数据包处理职责,并将它们分配给在CPU上执行的软件和在NIC上执行的专用硬件引擎。最受欢迎的一种是TCP chimney offload,它在操作系统内核中做连接控制没在NIC上做数据交换,也就是将工作从CPU卸载到了NIC,这种设计的数据包处理十分高性能,但是这种设计难以推进和定制,所以市场渗透率很低

专用CPU
这种方式是用整个CPU单独执行TCP栈,通过消息队列来进行交互而不是通过系统的调用,所以减轻了开销,可以批处理以提高效率,这样也不会有缓存污染情况。这种方式通过流水线并行和堆栈与应用程序之间的性能隔离来获得高而稳定的吞吐量。但是由于复杂,所以可能有流水线停滞和缓存不命中的情况发生,导致即使多专用处理器,整个堆栈的效率也不高。

专用快路径(作者的做法)
这种方法在建立在专用CPU的基础上,但是它更加细化,将数据平面分为常见和不常见的代码路径,为每个路径分配独立的线程,审视现代处理器上的高效堆栈实现,TAS可以获得更高的CPU效率。但这种方法不需要新硬件(与NIC卸载不同),保护TCP堆栈免受不受信任的应用程序(与内核旁路不同),保留软件实现的灵活性和灵活性(与NIC卸载不同),同时最大限度地降低保护成本 (与受保护的内核旁路不同)。另外TAS消耗的CPU数量和工作负载成比例,甚至在低负载下还可以应用程序线程共享CPU。

作者量化了一下TCP栈的开销,通过计算CPI(CPU周期和指令数量的比值)来进行量化。
在这里插入图片描述
可以看到传统Linux协议栈的CPI为1.32,即是大量的时间用于CPU周期,而TAS的CPI为0.66,说明作者的这种方式将数据报的处理从较多的CPU周期中解放了出来。

Design

本节介绍TAS的设计,设计目标如下:
1、效率:带宽的增长继续超过处理器性能,TAS需要提供CPU高效的数据包处理,尤其是对于小数据包通信
2、连接可扩展性:需要可扩展到数据中心内的大量服务器,支持越来越多的连接
3、性能可预测性:
4、遵守策略:必须防止来自不同租户的申请拦截和干扰其他租户的网络通信。因此,TAS必须能够实施诸如带宽限制,内存隔离,防火墙和拥塞控制等策略。
5、工作负载成比例:不使用超过所需吞吐量的CPU,即是根据负载能调整CPU使用率

TAS分为三个部分:快路径,慢路径,不可信的各应用单独的用户态协议栈。所有的部件通过一系列的共享存储队列连接,其中快路径只负责常见的数据报的处理。它将有效的接收数据包有效负载直接存入用户空间内存。 在发送路径上,它根据慢速路径动态配置的每个连接速率或窗口限制从用户存储器中获取并封装有效负载。这个用户级协议栈会提供标准的API,所以应用程序不需要修改。 对于连接设置和拆卸,每个用户级堆栈都与慢速路径交互。

快路径
为了简化和提高性能,快路径只处理最低限度的功能。它处理协议包头,发送TCP确认,一些必要的拥塞控制策略,并执行有效的分段。但是如果完全正常运行,它还必须检测异常,例如无序到达,连接控制事件以及未知或异常数据包(例如异常IP和TCP标头选项)。 数据中心应用程序通常预先建立所有必需的连接。 因此,TAS快速路径将连接建立和拆除视为异常。 所有的异常通常会转发到慢速路径。

正常情况下接受包
TAS快路径通过NIC的接收进程的动态号码,从NIC端接收数据数据包。TAS假设数据包是按序到达的,实际上由于连接稳定的多路径路由,如今的数据中心网络确实如此。对于顺序到来的包,快路径直接丢弃所有包头,并且直接将有效负载插入到用户级、每流独自、循环接收的缓冲区中(由rx_start | size字段标识,rx_head | tail标识读/写位置),通过识别连接和接收的字节数来通知适当的接收上下文队列。作者实现了两个接口:recv()和epoll(),其中epoll用于接受通知,recv()用于将数据从缓冲区复制出来,应用程序通过轮询的方式访问。当缓冲区满时,快路径会直接将包丢弃,而这种情况比较少见。快路径由于每个流拥有各自的缓冲区,因此避免了共享缓冲区需要对所有连接进行迭代的开销。
数据正确存入缓冲区时,快路径会生成确认数据包并返回,在快速路径中处理TCP确认对于安全性非常重要。 如果用户空间可以控制确认,就像许多kernel bypass解决方案一样,它可以用它来阻止TCP拥塞控制 快速路径确认还提供正确的显式拥塞通知(ECN)反馈,以及用于往返时间(RTT)估计的准确TCP时间戳。 最后,快速路径更新本地每连接状态(例如,seq,ack和窗口字段)。
在这里插入图片描述

正常情况下发送包
当上层应用调用send()时,用户级协议栈将数据附加到流的循环传输缓冲区。每个流独有的发送缓冲区需要根据拥塞和流控来减轻排头阻塞。用户级协议栈通过在上下文队列中发送TX命令来唤醒等待的快路径线程。快速路径使用要发送的新数据量填充每个流桶(每个流状态的桶字段)。异步地,快速路径消耗这些桶,这取决于每个连接速率限制配置的慢速路径或发送窗口大小和接收器的TCP窗口,以强制拥塞和流量控制。当可以发送数据时,快速路径从发送缓冲区中获取适当的量,为连接产生TCP段和包头,并进行发送。快速路径还使用TCP时间戳为慢速路径提供准确的RTT估计,用于拥塞控制和超时。
在这里插入图片描述
传输有效负载缓冲区空间回收
已发送的任何有效负载都保留在发送缓冲区中,直到接收方确认为止。 快速路径解析传入的确认,更新每个流序列和窗口状态,释放已确认的传输有效负载缓冲区空间,并通过在RX上下文上发出具有相应流的传输字节数的通知来通知用户空间可靠传输的数据包 队列(未在图中显示)。 这个回收工作所需时间恒定。

每个流的状态
为了收发包流程的正常进行,作者在文中列出了一些必须的状态(一共102字节)。当前的商用CPU为每个核提供2M左右的L2/3高速缓存,所以我们能够在快速路径中保持每个核心超过2w个状态,将来的工作可能是减少快速路径的状态。

特殊情况(异常)
未识别的连接,损坏的数据包,无序到达以及具有未处理标志的数据包都被视为异常。这些异常的数据包将会被发送到慢路径进行。为了优化,在快路径上,作者还是实现了处理两个异常:

1、处理传入的确认时,快路径在收到三次重复之后会触发快速恢复,方法是重置发送方状态,就好像这些包尚未发送一样。快速路径还增加每个流重新传输计数器以通知慢速路径以减少流量的速率限制。

2、跟踪接收缓冲区的一个无序数据间隔(从ooo_start开始,长度为ooo_len)。简单来说就是,还是维持了一段长度的buffer,如果无序的包之后填充了间隙,那么就可以达到按序到达的效果,并提交给上层。

慢路径
慢速路径实现所有策略决策和管理机制,这些策略决策和管理机制具有非恒定的每个数据包开销,或者在快速路径中处理过于昂贵或有状态。这包括拥塞控制策略,连接控制,用户空间TCP堆栈注册表,超时和其他异常情况。

拥塞控制
TAS支持基于速率和基于窗口的拥塞控制。快路径在每个控制间隔(默认是2RTT)为每个流运行一个控制循环迭代。慢路径从快路径中检索拥塞的反馈,然后运行拥塞控制算法来计算新的流量发送速率或者窗口大小,并且通过共享内存的方法更新信息。

有许多不同拥塞控制算法的通用框架,作者选用的是DCTCP和TIMELY,并且应用于控制速率而不是窗口。是因为对于多流,基于速率的拥塞控制更加稳定。它可以平滑由于拥塞窗口大小的突然变化而发生的突发,从而在流之间提供更公平的带宽分配。作者实现的基于速率的DCTCP实现与Linux同行兼容。

连接控制
连接控制很复杂。它包括端口分配,TCP选项协商,维护ARP表和IP路由。因此,需要在缓慢的道路上处理它。用户级TCP栈在慢速路径上下文队列上发出new_flow命令,以本地请求新连接(由connect()调用触发)。如果被准许,则慢速路径通过执行TCP握手来建立连接,并且如果成功,则在快速路径中安装已建立的流的状态并分配速率/窗口桶。远程连接控制请求由快速路径检测并转发到慢速路径,然后完成握手。

服务器通过向慢路径调用listen()来侦听端口,带有SYN标志位的包会被当做异常传入慢路径,慢路径通过上下文队列发布通知并传入到用户空间,如果用户程序决定接受连接(通过accept()),则TCP栈可以通过上下文队列返回accept命令,慢路径就会通过分配流状态和存储桶来建立流量,并发送SYNACK数据包。拆除连接也是类似的过程。

超时重传
超时重传也是在慢路径中完成。慢路径会从快路径收集拥塞统计数据,内核还检查未确认的数据(即tx_sent> 0)。 如果流具有多个控制间隔的常量序列号的未确认数据(默认为2),则慢速路径通过向慢速路径上下文队列添加命令来指示快速路径开始重新传输。 响应于该命令,快速路径将重置流并且完全如上所述开始发送以进行快速重传。

TCP栈管理
作者建立的TCP栈需要和TAS相连接需要特殊的系统调用来通知慢路径。做法是,如果请求被准许,那么慢路径会创建一对初始上下文队列,协议栈则会用它来创建连接缓冲区。

用户空间TCP协议栈
用户空间TCP栈需要向应用程序提供编程接口,作者提供的也是标准的POSIX套接字,所以它们的应用程序可以保持不变,但是应用程序的扩展是可行的,因为接口处于用户级。比如说,TAS提供的低级API可以直接将事件通过上下文队列进行交换。

负载成比例分配
由于TAS在专用处理器内核上进行协议处理,所需的内核数量取决于工作负载。所以,TAS理应动态地调整用于处理的处理器数量,使其与当前系统负载成比例。作者采用三种独立的机制来实践以上功能。

  1. 在快速路径上,我们使用硬件和软件数据包控制将数据包定向到正确的内核.
  2. 而慢速路径监视CPU利用率,并根据需要调整转向表以添加或删除内核。
  3. 最后,快速路径在一段时间内没有收到数据包时阻塞线程(在实现中为10 ms)。可以通过内核通知(eventfd)唤醒这些核心。这要求我们在放大/缩小事件期间仔细处理队列之间的数据包重新分配。

快路径中
TAS会配置最大的内核数并创建线程,并为所有内核分配NIC队列和应用程序队列。由于有自适应轮询机制,那些为接收到任何数据包的核心会自动阻止并取消调度。为每个连接设置锁,这样可以方式在增加或者删除核时导致昂贵的协调代价。作者的做法只是改变数据包的流向,所以在核的加减期间数据包的传输并不会有太大影响。

慢路径中
慢路径是直接监视快路径中的CPU利用率来决定何时添加或者减少核心。如果它检测到总共超过1.25个核心处于空闲状态,则会启动核心的删除。另一方面,如果总共少于0.2个核心空闲,则会增加一个核心。具体阈值是可配置参数。

之后的具体实现和实验效果等不做记录。下面是个人的小小总结:
对于TCP占用过多CPU周期导致速度慢的情况,作者的做法并不是舍弃TCP自己写一套协议,而是将常见的快路径传输从繁杂的分支和判断中分离出来,并且通过专用的CPU来为它加速。但是考虑到需要TCP提供的保序、可靠等性质,作者没有舍弃掉其他部分,而是在慢路径实现(快慢路径在原本的TCP中是存在的)。快慢路径之间通过共享内存的方式交互。除此之外,还实现了根据负载的CPU的动态增减;每个流单独维护buffer,避免共享缓存时需要的开销。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值