包处理的艺术(3)-RTC vs Pipeline
题记:本文主要介绍一些State-of-the-Art的数据面处理方式,例如思科的Silicon One、LightSpeed、QuantumFlow Processor、UADP,同时也会对比介绍一些其它公司的,例如BRCM、Innovium,当然也不会错过智能网卡芯片,Pensando、Fugible. 当然篇幅有限,关于这些演进的历史会放入包处理的艺术<A1>一类的附录中作为补充,而对于多核RTC的调度、DPDK、VPP、BPF或者Pipeline等处理的详细细节可能会在包处理的艺术(4)中出现,因为这个话题涉及到片上网络、AI加速芯片等一系列并行计算的话题。
1. 架构概述
1.1 RTC
1.2 Pipeline
PIC卡接收到报文后, PIC I/O ASIC对报文进行CRC校验, 如果校验失败则丢弃报文并通知JUNOS的相关接口计数器更改. 如果校验成功则进行Layer2解封装, 将Layer 2 PDU发送到FPC上的I/O Manager ASIC.
I/O Manager ASIC检测报文的协议类型, 然后在包标志信息内设置一个可能被用于不同服务的标志.然后将报文分割为64-byte的Cell(被称为jcell). 其主要原因是使得内存使用更加高效, 同时定长交换可以优化转发时延.并将每个jcell传递给位于SCB(or SFM)上的分布式Buffer Manager ASIC.
Buffer Manager ASIC将jcell以轮询(根据PFE进行轮询, 将不同的jcell发送到不同的PFE上的共享缓存中)的方式发送到分布式的共享内存中.
Buffer Manager ASIC同时根据jcell中的相关flags提取信息, 例如对单播IPv4报文提取源目的地址,输入接口, UDP/TCP端口等参数, 对于MPLS查看MPLS标签等. 收集完这些信息后生成一个key cell, 并将其转发到Internet Processor II ASIC
Internet Processor II ASIC对报文进行查询, 并将完成查询的转发决策整理成一个result cell返回给Buffer Manager ASIC
此后Buffer Manager ASIC将result cell中的信息进行解析, 并通告出口PFE的I/O Manager ASIC, 如果是组播流量则通告所有的出口I/O Manager ASIC
出口I/O Manager ASIC 通过分布式的Buffer Manager ASIC从分布式共享内存中读取jcell. 并管理包队列和一些QoS特性等. 最后I/O管理器将这些jcell重组为packet, 并将帧结构转发到出口PIC I/O ASIC
出口PIC I/O ASIC根据出站媒体介质进行编码, 例如POS编码或者HDLC组帧等操作, 最后从端口上发送出去. 离开路由器进入下一跳.
2. RTC vs pipeline
2.1 RTC和Pipeline的交替发展
2.2 流水线空转问题
简单的做法就是随便乱猜一个预先读,万一对了不就省事了么,但是万一错了呢?大不了下一步清了,再读一个,这样流水线里就会有空泡。所以分支预测就是这么个思路,尽力猜对,所以很多代码里都有likely/unlikely的处理来优化分支预测。
另一个流水线空转的问题在于当一个固定的流水线写死了以后,我不要运行某些功能却又必须要走这一级流水线,如下图所示
当入方向不需要ACL的时候,固化的流水线也必然要走这一级没法跳过,自然整机功率就上去了。而RTC做完了就可以释放报文了,相对处理功耗就要小很多,这也是Cisco Silicon One低功耗的原因之一。
2.3 流水线固化问题:串接业务板卡
既然固化的流水线有傻的缺点和快的优点,如下图所示:
于是就有人做起了脑白金的生意:)通常一个ASIC的开发周期为2~5年,那么如何让芯片变得更聪明呢?不因为功能而升级,而只是在三五年后因为性能不够了再换掉,这样对自己和客户都是好事,既有投资得到了充分的发挥。
我现在还在用一个2008年研发的第二代QuantumFlow Processor,十多年过去了,还依旧有Segment Routing、DPI、防火墙、IPSec、VXLAN、SDWAN的功能,这就是可编程的好处,任何硬件都不需要更换,添加新的功能也没有性能的下降。当然这是一个RTC的处理器,我们后面一点的章节和Silicon One一起讲,先来看看交换芯片的可编程演进
UADP项目主要是应对园区网的快速发展,带宽需求基本上满足了,而更多的是一些灵活的策略、终端漫游和寻址而产生的Overlay、TrustSec、无线有线融合,也就是后面出现的软件定义的接入SDA解决方案。
UADP的设计就是将原有的固化包解析器和各种固化的查表引擎及报文重写引擎改为可编程的结构,这样就可以灵活的在ASIC上处理了,这样有个好处,同一个ASIC可以为不同的业务分配灵活的表项:
UADP的流水线也相当长,Ingress 17级,Egress 8级,每级都可以同时执行2次查询:
当然还有一个常见的做法诞生了,也就是Recirculation的处理,以VXLAN报文为例,第一次通过的时候解开隧道头,最后Rewrite阶段重新把内部的内容导入流水线完成报文的处理。
不过这并不是一件高效的事情,虽然在已经固化的ASIC上实现了更长的流水线处理结构和一些包处理结构的复用,但是Recirculation也导致了整机吞吐的下降,毕竟设计这个ASIC的时候还没VXLAN呢,至于后来Nexus9000刚出来的时候也有特殊的芯片来处理。
说到可编程交换芯片不得不提到P4. 网工通常连Python代码写起来都很吃力,更不要说写微码了,好多半道出家的计算机体系结构都没学过,所以P4这样的DSL就诞生了,既然UADP验证了可编程ASIC的成功,那么就再进一步在工具链和底层结构上各自向中间靠拢一步,这就是P4.
和UADP一样,本质上Tofino在初始状态是一个完全协议无关的流水线架构,可以根据您自己的需求定义各种报文处理行为:
用通用处理器写过Parser的都知道,在每次解析报文的时候通常需要消耗大量的指令才能将需要的字段放入到寄存器中,而Barefoot的最大创新就在这里,Parser是一个TCAM和SRAM组合的结构,通过片上的SRAM作为寄存器指定输入的Shift Offset,然后TCAM则用来Match需要的字段,一次性的将结果丢入到SRAM中,最后产生对齐的8b、16b、32b 等等不同长度的值供后续的ALU处理,Barefoot将这样解析好的字段定义为PHV(Packet Header Vector),一个很形象的说法就是From packet to register
稍微补充一下TCAM,传统的CAM是精确匹配每个bit位是否要match或者不match,所以通常用于做一些需要精确匹配(Exactly Match)的场景,例如MAC地址匹配,而TCAM的做法其实就是有些bit位加上了一个Don't Care的处理,对比如下:
所以这也是TCAM为啥叫Ternary Content的原因,其实就是每个bit位有三种状态, 0,1,Don't care,这样不就很容易去做一些匹配了么,特别是路由器那样的Longest Match
所以您会看到这东西还是SRAM构建的,那么SRAM的结构通常是由六个晶体管组成,如下所示:
然后随着SRAM技术的发展,基本上片上SRAM的存储密度每隔2年就缩减一半,因此容量快速增加,所以很多事情都是在一定的时期才能诞生的,这也是为什么Barefoot的时间点可以做这样的事情,而更早的UADP做不了的原因。具体关于SRAM的发展及功耗稳定性的限制可以参考下面这本书的第二章
当然另一个问题是SRAM容量毕竟有限,精确匹配的场景消耗的CAM数量很多,那么还有别的什么优化方式呢,自然就是Hash表查询了:
写这一小段的目的是让网工们了解芯片内部的器件,很多东西并不是简单的一个黑盒,接下来回到正题,相对于UADP做多级的Parser,末级Rewrite报文和产生Action,工艺的进步使得Torfino可以在每一级执行操作,执行操作的ALU相对简单一些,而且比起标准的RTC处理器而言,它没有控制逻辑,没有大量的临时寄存器,没有PC,单级Action只能做简单的一些指令操作。
然后Barefoot就把这一系列MAU并行起来构成了单级同时匹配多个字段的引擎:
同时又把多个这样组合好的引擎构建出一个大型的流水线结构,注意到中间的MAU 0~ MAU n就是这样的流水线结构。
但是问题来了,流水线怎么调度呢?前面讲过流水线空转的问题,也就是说当上一级和下一级的Action没有依赖的时候,工作的很好(下左图),当操作相互依赖时延迟就增加了(中图),而需要做一些分支处理的操作时耗费的时间就更长了,如下右图:
当然Barefoot也有一些Table Prediction的处理方式,如下图所示:
但是这样的处理在很多复杂业务下会存在明显的pipeline消耗过长需要Recirculation的过程,这也是Silicon One需要将它换为RTC的原因,当然我会在包处理的艺术(5)里讲一些报文编码的处理技巧如何避免在协议设计的时候出现if-then-else这样的处理,这也是G-SRv6编码的一个硬伤,很多协议的编码需要同时考虑如何让硬件做的舒服才是最重要的。
另一方面你需要注意的是,这类芯片通常将片上的存储用于了灵活的报文处理,因此并没有预留大量的空间来承载转发表,因此通常这样的芯片是以交换机的形式存在,因为简单的Exactly Match好做,但没有大量的片上TCAM资源无法支撑数百万级路由的LPM(Longest Prefix Match)。
后续Jericho和Silicon One的介绍中你就会明白另一种取舍了。
while (1)
{
block for wakeup
Fetch a new packet descriptor
Process this packet
{
feature-1... feature-N
}
Dispatch the packet to QFP traffic Manager Queue
Notify traffic manager
}
开始新的一章前对于RTC和Pipeline做一个总结,如下图所示:
最左边是思科的路由处理芯片系列产品线,芯片上的资源主要用于包转发引起PPE和相应的Cache,同时也分配了大量的资源用于转发表FIB查询,当然路由器相对于交换机通常还有大量的广域网和局域网侧带宽不匹配的情况,因此需要Buffer去吸收来自于LAN侧的报文burst以及QoS在广域网侧做多队列调度,这些都是我们在设计一颗广域网路由器芯片时要考虑的问题,当然更细节的设计是企业网比运营商可能因为一些Stateful的软件特性还需要更多的内存访问优化和更大的cache设计。这样的缺点也是很明显的,就是功耗特别大同时也不够快,很多feature可能需要通过片上网络多次访问memory也会带来一些瓶颈。
中间这个图为固定流水线的交换机芯片,通常功能很死但是特别快,所有的资源都用于报文查询的流水线,当网络协议栈创新没那么快的时候它有它的价值,特别是配合智能网卡构建SmartEdge&DummyCore的架构时,这样的芯片很适合作为DummyCore使用。
最右边为Cisco UADP或者Barefoot Torfino一类的可编程交换机芯片,它把片上的资源再一次划分给了一系列灵活的Match-Action引擎,但是相对来说速度就降下来了一些。
您可以注意到在中图和右图中,QoS、Buffer、FIB这些都是交换芯片常常不需要考虑的,因为在LAN侧传输延迟相对较低,带宽上行通常大于下行并不需要太多的QoS设计,转发表规模也没那么大(当然云数据中心做ToR overlay时还是有很多需求的,所以后面Host overlay的诞生也有其内在的原因)。
有一种做法就是把固定流水线的做FastPath,而灵活的业务处理丢到SlowPath上让RTC的处理器来做,例如阿里的XGW FastPath采用了Barefoot,而SlowPath采用了Intel Xeon处理器做RTC
FastPath/SlowPath的架构也有一些内在的限制,例如流表的更新速度,FastPath的TCAM容量和SlowPath不匹配的问题。以前我测过某厂的类似架构的路由器,号称100Gbps的吞吐就由于这个不匹配的问题在源目的端口随机的测试下构建一个64K*64K的fullmesh 测试流连1Gbps都打不到,直接被甲方废标。
FastPath和SlowPath的处理通常会采用统计学模型,把经常性的5%~20%的条目放入到FastPath处理,而剩下的放入RTC。Google以前有一篇论文讲到5%的ACL可以匹配接近95%的流量也就是这个原因。
另一个问题是FastPath+SlowPath的架构并不适合很多安全性的feature采用,因为这些通常需要每包都有状态的进行复杂处理。
另一种做法就是平衡流水线,相对于Barefoot不那么的可编程,又相对于固定交换机提升路由表的容量和QoS、Buffer。Jericho便是这样的处理方式,早期使用片外TCAM、DRAM和片内配合的方式,然后报文处理采用了ElasticPipe的处理方式。
当我们意识到这一系列问题后,自然又有很多好玩的想法冒出来,那么又拿起RTC的微核如何?这样Jericho的pipeline的问题似乎也可以解决了,然后片上网络随着7nm的工艺似乎也可以得到很好的提升?这一次的取舍是什么呢?通常Silicon One作为核心路由器存在,并不需要太多的QoS和Buffer支持,这些留给边缘的多业务PE(ASR9900/ASR1000)来做,另一方面Stats的功能也不需要在核心做太多,这一块功能也可以节省一些,即使要也可以Sflow采样好了丢给一个FPGA在片外去做。
消除了Off-Chip内存(DDR4/GDDR5/TCAM)
采用了片上的HBM做FIB和Buffer,但是更多的用于FIB
灵活的RTC引擎支持6B pps,想想第一台路由器AGS只有7000pps,30年一百万倍。
高级的数据结构和查表算法。这也是得益于HBM巨大的内存带宽和容量,然后查表的过程中如果还使用TBM的方式需要3次DRAM访问,在延迟和容量间取舍,自然新的查表算法有了容量肯定要消除延迟一次查完了呀~具体怎么一次查完的保密,但是就是简单粗暴就好。这个技术也用到了LightSpeed+上。
可扩展的灵活的多Slice结构,其实也是现代芯片技术发展的一个趋势chiplet,一个大的芯片可以有大量的chiplet构成,当然这里面也用到了同构的思想。
5.3.2 RTC
网络界通常针对分布式系统复杂性的另一种思路就是边缘智能和简单的核心。所以你会看到云计算发展到一定程度后也逐渐开始往边缘计算靠拢,这些都需要科学的发展观来看待。
如果说路由器芯片我最喜欢的是QFP(吃饭的家伙能不爱么...)那么最喜欢的交换芯片就是Innovium了,当然最喜欢的路由交换芯片是Silicon One(甲方爸爸要跪舔~)
在新一代的架构演进过程中,随着虚拟化和容器技术的出现,TOR overlay逐渐变成了Host Overlay,而传统的TOR交换机也面临复杂的ZeroTrust规则下ACL/TCAM不够用的窘境,那么干脆就把TOR做到网卡上,也就是智能网卡DPU这样的场景。
Pensando的做法其实类似于一个FastPath/SlowPath on Chip的处理方式,下方是一些P4的Slice然后通过片上网络和ARM核心及其它加速协处理器互联。
P4和Barefoot类似的做法,就是一系列SRAM、TCAM构建的Parser以PHV的形式存放header fields、指令和一些metadata,最多可以到8kb,然后它的流水线为8级,Lookup engine可以做到2048bit的查询,Hash或者TCAM查询都可以支持,而相对于Barefoot也有了一些动态指令的处理能力,可以注意到Pensando也在上面放置了Icache和Dcache用于做一些更复杂的操作,并可以在该级支持RTC。
针对存储和网卡访问的一些特性,它添加了一些压缩和数据完整性校验的功能,同时还配合ARM做控制面实现了TOE(TCP offload Engine)。但是出其不意的是在它7nm的平台Elba上直接把HBM换成了Off-chip的DDR4、5,可能是考虑的主机PCIe侧只有200Gbps的带宽,所以整个chip也没必要用那么高带宽的内存了
pensando的DSA架构本质上就是在边缘做所有的事情,但是它们没有选择RTC,而是采用了在P4 engine上扩展一系列I-Cache和D-Cache的方法来做,这都是趋势所向,在RTC和Pipeline之间取得平衡。
当然除此之外类似的架构还有Netronome采用以前Intel IXP的微码技术演化而来的智能网卡,然后直接兼容eBPF的方式来做并行处理,有机会再跟大家介绍。
当然还有继续走RTC路线的fungible或者AWS的nitro,Fungible构建了一个有192个RTC线程的处理器,并且和一些加速硬件紧耦合,单芯片800Gbps的吞吐,同时也采用了HBM。
单个Data Cluster采用6核4线程的结构,并且配合专门的加速协处理器,例如Lookup engine、Security engine等:
整个编程结构相对干净,因为是RTC的所以完全兼容C代码程序:
但是Fungible的问题和juniper很类似,就是不太会做Marketing,一开始老早就吼DPU,最后却是被nvdia的老黄发扬光大的,真是可惜。你看下面这个ppt,真是不知道它想要干什么,但是这东西本身还是不错的,当然任何架构都有软肋,得用了的人才知道
后面似乎有人点拨了一下,ppt写的好了点,它是以网络为中心的第三个Sockets
也就是我去年说的:
如何把数据包编码使得转发模型能够更好适应异构的硬件平台,编码上降低RTC-Pipeline-RTC这样的复杂切换流程,设计一种完备的DSL并且可以同时支持流量的RTC/Pipeline offload,这才是关键 |
解决方法就是,别扯什么PCIe了,也别扯RTC、Pipeline了,我直接把RISC-V粘到P4上,是不是又想到了当年7600插各种业务板卡呢,不同的是人家把这玩意堆到一个芯片上了。
当你看到这么多的技术发展时,还有一些传输上的变化,例如56Gbps PAM4和Co-Packaged技术,光技术的发展逐渐也会小型化,然后最终芯片光互连和芯片内光通信也会逐渐出现。
技术的本身没有优劣,你会看到不同的场景又不同的取舍,可以通过pipeline固化加速,也可以通过RTC获得灵活的业务。保持开放的心态去评判,找到适合自己的方式组件整个平台才是一个架构师真正需要的。