ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

交换芯片控制通路深度指南:解析、查表、调度与可编程流水线

交换芯片控制通路深度指南:解析、查表、调度与可编程流水线 1. 先界定清楚本文说的“控制通路”是哪条路有一次在机房排查VXLAN网关的转发异常所有带VXLAN头的流量全被丢到CPU数据面一条都不走。查了很久最后落在平时很少关心的一个点交换芯片的Parser解析深度不够数据面根本认不出第二层隧道头部只能“上送CPU”软转发。从那以后我看交换芯片就不只盯着端口密度和吞吐量了真正决定一台设备上限的是报文在芯片内部经过的那条决策路径也就是标题里说的“控制通路”。先说下语义因为“控制通路”在交换芯片这个领域里有两种常见理解。第一种是指管理CPU下发配置、读写寄存器、上报中断和统计的那条通道对应PCIe、SPI、I2C这类接口也有人叫Control Plane Path、慢路径。第二种是指数据包进入芯片后为了决定“怎么办”而经历的逻辑链路解析报文、查找匹配表、执行动作、排队调度再走向出口。这个专栏标题里明确写了“解析、查表、调度与可编程流水线”所以我们这里讲的是第二种——它是规则驱动的转发决策路径规则由控制面软件通过第一种通道下发最终在这条通路上被执行。为什么要单独写一篇因为很多人对交换芯片的理解停留在“线速转发”这个结果上但怎么做到线速靠的是把每个报文的处理拆成一系列确定性步骤每一步在固定时钟周期内完成然后用硬件流水线把这些步骤重叠起来。上篇我们聊了交换结构、Buffer这些数据搬移的部分这篇我们把真正做“决策”的部分拆开Parser怎么认报文Match怎么找规则Action怎么改报文调度怎么决定谁先走以及可编程流水线又是怎么把这些环节串成一条可以改写的装配线。理解这条通路对做网络协议栈、做SDN控制器、做网络设备选型、甚至做网络排障的人都有实际价值。举几个场景你写了一个OpenFlow规则却始终不生效可能是芯片Hash表冲突导致表项没插进去你的VXLAN租户流量总是被上送CPU可能是Parser深度不支持这类封装你配了QoS队列却看不到预期效果可能是调度器权重和Buffer门限不匹配。这些现象都指向同一条控制通路逐段拆开之后很多问题自己就能定位了。2. Parser不是“剥头”而是一段状态机程序2.1 解析的本质一场逐层递归的判定很多刚接触交换芯片的人觉得Parser就是把以太网头、IP头、TCP头一层层剥下来提取五元组。这个印象不算错但会把问题想简单了。真实网络里报文结构不是线性的有VLAN Tag、有MPLS标签栈、有GRE/VXLAN隧道、有IPv6扩展头、有SRv6 SID列表甚至还有一堆二层叠加协议。Parser需要在固定时间内识别出“这个包是什么类型”并把需要的字段提取成整齐的向量供后面查表使用。从实现角度看Parser更像一段状态机代码而不是一个简单的修理工。它从报文头部第一个字节开始根据当前解析位置读取协议类型字段决定下一个节点是什么。举个例子解析完以太网头之后看到EtherType是0x8100就进入VLAN节点解析完VLAN继续回读内层EtherType是0x0800就进IPv4节点是0x86DD就进IPv6节点是0x8847就进MPLS节点。这个过程跟你写一个递归下降解析器解析JSON或者XML没有什么本质区别只不过这里的“语言”是网络协议栈“编译器”是一次性烧进芯片的硬件状态机。2.2 从一次VXLAN排障说起深度和循环回到开头那个VXLAN排障案例。普通的VXLAN报文结构是外层以太网头 外层IP头 UDP头目的端口4789 VXLAN头 内层原始以太网头 内层IP头。Parser要解析到内层五元组意味着要连续识别两层完整网络头。很多老一代交换芯片Parser的“深度预算”是按传统二层三层场景设计的比如只允许解析一层隧道头超过部分一律按unknown上送。结果就是网关设备能收到VXLAN包也能转发出去但是数据面不认识内层IP所有流量都走CPU软转发路径吞吐直接掉一个数量级。另外一个关键点是循环结构。MPLS标签栈可以压很多层QinQ也可以嵌套多层VLANSRv6的SID列表长度不固定这些协议的特点是“重复出现”。硬件Parser不能用软件那样随意递归必须显式地支持计数器和返回机制在一个Node里重复解析N次N达到上限就跳出。这个N就是很多芯片规格书上写的“支持MPLS标签栈深度”或者“支持QinQ双层VLAN”的由来。这里有个常见的认知误区有些芯片标称支持MPLS但如果标签栈深度只有两层在承载网场景里一压标签就废了排障时特别容易被坑。2.3 解析结果怎么交给下游PHV和MetadataParser解析完后提取出来的不是一个个孤立的字段而是被打包成一整块固定宽度的“字段向量”业内最常见的叫法是PHVPacket Header Vector包头部向量或者Field Vector。每个需要的字段在这个向量里占据固定比特位比如外层源MAC、VLAN ID、目的IP、四层端口号各占各的位置。同时Parser还会生成Metadata比如报文从哪个物理端口进来、携带哪个VLAN、时间戳、入口是否做了镜像采样等。这些信息伴随报文走完整条流水线后面的查表、动作和调度都依赖它们。理解PHV有两个实际用途。第一它决定了可编程芯片的“提取预算”芯片能同时提取多少个字段、每个字段多宽是固定的编译器负责把P4程序里的字段映射到PHV槽位上槽位不够就会编译失败。第二排障时经常会说“这个包在内部怎么被看待”本质上就是看PHV里这些字段对不对——如果VLAN字段在解析阶段没被提取后面所有基于VLAN的查表规则都会落空但外面用抓包工具看完全看不出问题因为报文内容一字节都没变。这里说一个实操经验怀疑解析问题时不要先看路由表或者ACL第一步去查芯片的“异常上送统计”——通常所有芯片都会记录因解析失败、深度不足、Checksum错误而被迫上送CPU的报文数量。如果这个计数在持续上涨说明报文结构本身就有芯片不认识的成分再往里查就有方向了。3. 查表与动作执行匹配是规则落地的关键环节3.1 三类匹配方式与芯片代价解析完报文只是第一步芯片要回答的核心问题是这个包下一步做什么。这个答案来自查表。交换芯片里的查表体系可以分成三类精确匹配、最长前缀匹配、通配匹配它们各有各的硬件实现方式也各有各的昂贵之处。匹配类型典型应用硬件结构主要代价精确匹配MAC地址表、流表、会话表Hash Table哈希冲突影响确定性与容量利用率最长前缀匹配IPv4/IPv6路由表LPM Trie、分级Hash多级查找增加时延容量与速度折中通配匹配ACL、流分类、策略路由TCAM面积大、功耗高、按掩码分区管理复杂很多人以为一张大表就能搞定所有查找实际上商用交换芯片内部是“分类做表”一张大路由表用Hash/LPM结构ACL用独立的TCAM区域MAC地址表又用另一组Hash桶。这样做的原因很朴素——不同匹配模式对硬件结构的要求完全不一样。精确匹配适合用哈希函数把关键词映射到桶里一次查找命中而ACL里会有“允许任意源IP访问目的IP段”这种带掩码的规则哈希根本没法处理只能用TCAM并行比较所有表项支持每位“0、1、任意”三态匹配。3.2 Hash查表的残酷细节冲突、种子与确定性精确匹配表的硬件核心是一组哈希函数和一组桶结构。报文五元组通过哈希函数计算出一个索引落到某个桶桶内再串行或者并行检查2到8个条目找到就返回关联的Action指针。这里最容易出问题的是哈希冲突两个不同的流算出来同一个桶位置一个桶装不下就需要溢出链、二次哈希或者换种子重插。商用芯片通常会做一些工程优化来缓解冲突。比如可配置哈希种子让运维在遇到突发冲突时换一套哈希函数比如桶深度可调但调深了会增加查询时延比如用两级近似去重结构先做一个Bloom Filter减少无效桶访问。你在配置流表时如果发现“明明下发成功了但就是匹配不到”可以先怀疑是不是桶溢出导致表项被丢到了溢出区而溢出区在某些芯片上默认不参与快速路径查询。这里要特别注意交换芯片的哈希查表对“流一致性”极敏感。ECMP负载均衡、链路聚合的HASH都要求同一条流的所有报文算出同一个结果所以芯片里的哈希函数通常设计成“对报文字段排序不敏感”——TCP双方向报文只要五元组组合不同就可能算出不同桶。这也是为什么很多交换机在做负载均衡时要专门选对称哈希否则来回路径不一致现网流量的TCP性能会莫名劣化。3.3 TCAM为什么金贵按掩码分管是门手艺TCAM的价值在于“并行全比较”但代价也直接一个三态存储单元大约需要2个SRAM比特来实现面积和功耗比普通SRAM高一个量级。芯片面积就那么点所以TCAM容量是宝贵资源通常只给ACL、QoS分类、策略路由这类必须用掩码的规则。TCAM的另一个管理痛点是优先级和掩码分区。硬件比较结果一般取“最小地址命中”也就是物理地址小的条目优先所以你的规则必须按优先级从高到低插入低地址放高优先级规则。掩码分区更麻烦TCAM按Bank划分每个Bank只能配置一个掩码宽度比如128个条目共享同一套掩码。如果你的规则有的是“匹配源IP目的IP”有的是“匹配五元组”就要把不同宽度的规则分到不同Bank跨Bank级联可能导致资源碎片化。这也是为什么很多设备的ACL资源使用率列表里会显示“已用百分比”但那个百分比不代表你建完所有规则之后一定够用——规则宽度不匹配会把容量瞬间打没。3.4 Action才是真正做事的地方查表命中的结果不只是“允许/丢弃”而是一个动作描述改目的MAC、改写VLAN、设置内部队列号、丢包、上送CPU、镜像到监控口、计数。芯片通过一个Action存储器把匹配结果映射成一组具体的现场操作。拿三层转发举例查LPM表命中下一跳Action就是“重写目的MAC和源MAC把TTL减一重算Checksum设置出端口和队列”。这一整套操作在硬件里由ALU配合立即数完成通常在一个或几个时钟周期内结束。两个和Action相关的内置功能在排障中特别好用。一是Counter每条表项可以带一组计数器包数和字节数查表命中自动累加。怀疑某条ACL没生效先把计数器清零再打流量看计数值变不变就能确认流量到底有没有踩中这条表项。二是Meter本质是令牌桶用于限速和入向监管。TSN里的流过滤、运营商场景里的用户限速都靠它。很多芯片允许Action里同时关联Counter和Meter这样既能算流量又能压流量二者不会互相干扰。3.5 表依赖链为什么查表顺序不能乱实际转发不是查一张表而是按固定顺序查一串表。比如一个典型的入向处理流程先查VLAN转发表确认口是否合法再查MAC表/LPM表得到转发出口再查ACL决定是否放行接着查限速策略最后查镜像规则。这张“表链”的顺序来自协议逻辑本身——你总得先知道这个包要往哪去才能决定后面的策略要不要匹配“去往某处的流量”。固定管线芯片的表链是固定的开发者只能配置“这级挂哪张表”不能改表间顺序。可编程芯片则把顺序问题抛给了编译器P4程序声明表间依赖关系编译器负责把逻辑表分配到物理流水线的各个Stage同时保证依赖顺序和流水线Stage顺序一致。这里有一个常被忽略的优化目标——让无依赖关系的表放到同一个Stage并行查把有依赖关系的表分配到不同的Stage让整条流水线尽量短。所以你在P4里写一个很长的查表链和一个很短的查表链占用的硬件Stage数可能一样也可能差很多关键看编译器能不能把独立表合并。4. 调度器排队、整形、拥塞控制一肩挑4.1 为什么转发引擎必须管“排队”解析和查表决定了每个包“去哪、怎么改”调度器决定“什么时候走”。很多人觉得调度就是队列拥塞时才有的功能其实不对。即使网络没有拥塞一个10GE口满载时每秒要处理约1488万个小包按64字节以太网报文算帧间隙和前导码都要算进去这些包从不同入口涌向同一个出口时必然存在竞争调度器就是那个“分时复用出端口带宽”的裁判。交换芯片内部的调度和报文不同变长报文在进入交换结构前会被切成固定长度的Cell通常以64字节或256字节为单位。这样做的原因和操作系统的页表如出一辙——固定大小的缓冲区单元便于高效管理共享内存池也便于交换结构按Cell调度避免大包长时间霸占内部链路造成队头阻塞。调度器的工作对象实际上是Cell级流量报文在出口侧重新组装回去。理解这一点对调优很重要一个64字节的小包和一个9000字节的Jumbo Frame在调度器眼里不是一个完整报文而是1个Cell和几十个Cell的差别对你配置的调度权重和队列长度的表现完全不一样。4.2 出向调度算法从严格优先级到DWRR出向调度要解决的核心问题是在队列之间按什么策略分配带宽。基本算法就这么几类严格优先级SP、加权轮询WRR、赤字轮询DRR、加权赤字轮询DWRR。实际设备上很少只用一种通常是组合策略——控制面报文用严格优先级队列插队数据流量按DWRR分配权重。把队列调度算法的区别理解透QoS调优会顺手很多。SP最大的问题是饥饿高优先级队列永远有包低优先级队列就一直等所以生产环境里几乎不让普通数据流量独占SP队列。WRR的问题在于变长报文数的不公平如果只是按“每轮转发1个包”一个大包队列可能吃掉不成比例的带宽。DRR引入了赤字计数器每个队列每轮获得一个配额没发完的额度可以累积到下一轮这样按字节加权更公平。DWRR再进一步允许高优先级的“权重”提前充值保证丢包率低的关键流量优先发完。权重参数不是拍脑袋定的。假设出端口带宽10Gbps你希望队列A和队列B按3比1分配那么DWRR里配的权重关系就直接决定最终实际带宽近似比例。不过要提醒一点DWRR只是“尽力按比例分带宽”一旦队列B没有背压流量队列A可以借用所有带宽。这是设计上的特性不是缺陷——带宽闲着也是浪费。4.3 拥塞控制不是协议层的独角戏调度器还承担着一部分拥塞控制职责。当队列深度逼近阈值时芯片有两种处理策略随机丢弃WRED或者显式拥塞通知ECN。WRED是“概率性丢包”队列越深丢包率越高目的是让TCP发送端感知拥塞、退避窗口而不是等队列满了才一刀切。ECN则更温柔把入向报文打上ECT标记出向交换机在拥塞时改为标记CETCP端到端协商后主动降速。这里有个数据中心场景特有的经验开ECN不能只开一面必须是整条链路上的交换芯片全开。如果一台开了ECN标记下一台不支持直接丢弃效果比不开还差。另外ECN和PFC优先级流控要搭配使用PFC靠“暂停帧”防止缓冲区溢出ECN靠“标记”让源端降速两者管的是不同层面的问题很多丢包事故其实是PFC门限配置不当导致的“PFC风暴”扩散这种现象在物理上体现为队列调度在反压中反复切换表现为端口利用率不低但吞吐极差。4.4 TSN让调度器第一次有了“时间维度”常规调度器做的是“带宽分配”TSN时间敏感网络的调度器引入了“时间确定性”。比如IEEE 802.1Qbv通常叫时间感知整形TAS每个出向端口维护一个门控列表GCL把时间轴切成固定周期每个周期内哪些队列的门打开、哪些门关闭用专门的门控组合器去控制。门在时间上的开关序列就是一张“时间表”关键流量比如工业控制报文在为其分配的时隙内独占端口带宽从而获得确定性的最坏时延。TSN对交换芯片控制通路带来的新要求是调度器必须有纳秒级的时钟同步能力基于802.1AS门控状态切换要足够快GCL要支持在线更新且切换过程不能产生错误帧。这几年工业网络、车载网络都在推TSN采购交换芯片时如果规格里只写了“支持802.1Qbu”“支持802.1Qbv”还要再确认一下支持多少条独立的门控队列、GCL容量多大、能否双缓冲切换——这些参数直接决定你能给多少条敏感流做时分调度。另外TSN里还有802.1Qci流过滤和监管它在入口侧按单流做限速并把非合规帧丢弃本质上就是前面说的Meter功能只不过门限粒度细到单条流。5. 可编程流水线把Match-Action做成工厂装配线5.1 为什么固定管线满足不了所有人传统交换芯片的Parser、查表顺序和Action能力都是出厂定死的想支持一种新协议就得换芯片。SDN大火那几年网络团队希望能在交换机上快速支持VXLAN GPE、SRv6、INT网遥测这些新玩意固定管线芯片只能靠“FlexCode”这种有限可编程做局部适配要么就得把流量上送CPU用软件处理性能掉得厉害。可编程流水线芯片就是在这样的背景下进入视野的它的代表架构是PISAProtocol Independent Switch Architecture——协议无关交换架构。PISA可以理解成一条由完全可编程的匹配-动作Match-ActionStage串联起来的装配线。报文先经过可编程Parser被切成一堆PHV字段然后进入一串Match-Action Stage每个Stage内部完成匹配和动作最后经过Deparser把PHV重新组装成报文发出去。每个Stage由SRAM/TCAM组成的匹配单元和一组ALU组成整个Stage由一条指令字VLIW控制因此协议行为可以被“编程”出来而不是焊死在芯片里。5.2 一个Match-Action Stage内部长什么样每个Stage有若干匹配单元SRAM用于精确匹配或LPMTCAM用于通配匹配。查表命中的结果会驱动本Stage自带的ALU对PHV里任意字段进行计算和修改。每个Stage的Action部分支持一组指令比如加一、减一、算术逻辑运算、字段赋值、按位操作指令由编译器生成并固化成VLIW。流水线的关键在于PHV在Stage间传递。每个Stage处理完PHV连同中间生成的Metadata一起通过Stage间的寄存器阵列传给下一Stage类似工厂里每个工位都能读取、修改工件上的标签。整个流水线是“逐级推进”的每级一个时钟周期所以吞吐能维持线速但报文经过的时延会随Stage数量增加。这也是为什么Mellanox现NVIDIA的Spectrum系列强调“浅流水线”——Stage数量少意味着时延低对金融高频交易等场景影响巨大。5.3 Deparser把PHV还原成合法报文Deparser经常被一句话带过但它的逻辑一点儿不简单。PHV在流水线中经过多级查表和动作修改可能改变了MAC地址、改了VLAN、加了隧道头、改了TTL。Deparser要根据解析阶段留下的“协议树”信息把PHV里的字段按原始顺序重新拼接成完整报文再交给内部交换结构。拼接得好不好直接决定报文发出后能不能被别人正常解析。实践中很多可编程芯片的开发问题都出在Deparser配置上Action改了字段但Deparser没把它写回正确偏移报文发出去后协议栈直接不认识。一些高性能芯片的Deparser还承担报文校验更新任务重算IP Checksum、更新UDP校验和。这些运算如果在CPU上跑会非常慢在Deparser里做则是几拍的事。VXLAN封装场景就是典型例子Ingress匹配VTEP表后Action在PHV前面插入新的外层头部Deparser按“先外层后内层”的顺序输出芯片自动重算外层Checksum整个封装在硬件流水线内完成不发一次CPU中断。5.4 可编程的代价与收益选型之前要想清楚可编程的吸引力是明摆着的但它绝不是免费的。第一是面积和功耗每个Stage都把SRAM、TCAM、ALU做全了不管你的表用不用得完硬件冗余都在那儿芯片面积和功耗比同等端口的固定管线芯片高一截。第二是编译和时延P4程序要通过编译器映射到物理Stage编译时间往往以小时计Stage深度增加还会带来额外的固定时延。第三是学习曲线P4和传统ASIC配置是两种思维写一个能跑出线速的程序很容易写一个不浪费Stage、不产生依赖冲突、还能通过时序收敛的程序就难了。选型建议是如果你的网络技术演进明确且快比如数据中心里要做大量定制封装和遥测可编程芯片值回票价如果是传统园区网、接入网的稳定业务固定管线芯片配合厂家提供的ACL/QoS模板性价比高得多。也可以做混合方案转发核心用固定芯片边缘和智能接入节点用可编程芯片这是很多大型云厂商的实际做法。这里补一个和“博通PCIe交换芯片”相关的澄清因为热搜里这个词经常和网络交换芯片混在一起。博通的PCIe交换芯片主要是用于PCIe拓扑扩展比如服务器和NVMe存储阵列的连接它内部没有以太网端口也没有我们前面说的Parser、LPM、ACL这套控制通路只有PCIe协议层面的TLP转发、VC仲裁和链路管理。如果你拿网络交换芯片的思维去选PCIe Switch会完全对不上规格表。做设备方案时先把这两类产品分开能少走很多弯路。6. 实测下来最值得记住的几个坑控制通路的每个环节都可能导致“表里明明有规则但就是不生效”的玄学问题。我自己的排查习惯是严格按链路顺序走先验证Parser有没有把包按预期解析出来再验证查表有没有命中最后才去看调度和转发结构面。后两个环节的问题通常有统计计数器辅助定位Parser阶段的问题则隐蔽得多因为报文在外面看一字节不少芯片却可能认不出某些字段。第一个坑哈希冲突导致的“间歇性失联”。一套流表下发后大部分流量正常偶尔某条流完全不被匹配抓包看报文格式也没问题。这通常是Hash桶溢出后条目被放到溢出区而溢出区的查找路径在某些芯片上不是完整线速。解决办法是换哈希种子、调整桶深度或者把散列冲突大的流用ACL精确匹配单独摘出来。别指望所有表项都能100%被线速命中硬件结构决定了冲突概率是数学上的必然能做的只是把影响降到最低。第二个坑Parser深度和Checksum状态。做隧道封装场景时如果芯片把内层头也纳入Checksum计算而你配置的校验更新不对转发出去的包在外面会被抓包工具标记为Checksum错误。这类问题最容易误判成“下游交换机丢包”实际源头在自己这台设备上。遇到不明丢包先看芯片的Egress丢包原因计数很多芯片会明确告诉你丢在队列丢弃、校验失败还是生命周期超时。第三个坑上送CPU的隐式路径。很多交换芯片对“Parser识别不了的帧”“TTL超时”“MTU超限”“安全异常”有隐式的上送动作这些路径的带宽是受限的。一旦某类流量被误判为异常会持续灌满CPU上行队列表现为CPU利用率高但数据显示面上几乎没有流量经过。运维监控时一定要加上“异常上送计数”这个指标单独报警否则哪天控制面被冲垮你都不清楚源头在哪。第四个坑计数器可信但有方向。芯片计数器通常在Ingress方向和Egress方向各有一组跨设备核对时经常出现“入口有计数、出口没计数”这不是计数器坏了而是包在内部被丢弃或者被交换到别的端口。对比双向计数是判断“包到底死在哪里”的最快手段比在设备外抓包靠谱得多。做性能测试时也建议把Ingress/Egress两边的包计数都打出来看差出来的数量就是芯片内部真实丢包数。最后分享一个我自己的习惯在任何一张大表上线之前先插一条“撒网条目”比如通配全部IP的计数规则确认解析和查表主链路是通的再往细粒度铺表项。这样如果后面出问题至少能明确是具体规则的问题还是整条流水线的问题。交换芯片微架构的内容到这里就完整了——上篇看结构和Buffer这篇看解析、查表、调度与可编程流水线。纸上谈兵容易真正在现网里和芯片的脾气打交道你会发现每一步都有细节值得再抠一抠。
返回列表