1. 先搞清楚这个功能到底解决什么问题
第一次看到“CDF / Extended Payload”这两个词,很多人会以为是某种新的协议格式,其实它不是协议,而是网络测试仪里两种让用户自己造包的能力。CDF 是 Custom Defined Frame 的缩写,直译就是自定义帧;Extended Payload 则可以理解为扩展载荷,允许你在标准帧头之后塞进任意字节的私有内容。两者合在一起,指向的是同一件事:测试仪不再只认标准协议栈,用户可以按自己的规则拼出一帧数据发出去。
这件事在 400G/800G 这个速率档位上特别有意义。为什么?因为在这么高的带宽下,测试仪的主要工作已经从“发几个包看看通不通”变成了“持续打满流量、验证链路和芯片在极限状态下的行为”。而现实中的业务流量早就不是清一色的以太网标准帧了,很多设备厂商会在标准帧基础上做私有封装,比如自有的一层标签、私有的 OAM 信息、设备内部的转发元数据。这些内容用现成的标准协议模板根本造不出来,只能自己定义。
我接触过不少做交换机、网卡、智能网卡验证的团队,他们的痛点非常统一:标准测试仪给的报文模板够用但不够灵活,想做异常帧、想做私有头、想做超长载荷的边界测试,往往要自己写脚本用普通网卡发,速率上不去,时间戳精度也不够。CDF / Extended Payload 这类功能就是冲着这个缺口来的,把“自定义”这件事从软件层搬到了硬件测试仪内部,既保留了自定义的自由度,又保住了线速和精度。
适合读这篇内容的人大概是三类:一是做数通设备验证的测试工程师,需要造各种非标帧;二是做芯片或网卡固件开发的,要用极端报文验证解析逻辑;三是刚接手 800G 测试环境、还在摸清楚测试仪到底能干哪些事的新人。前两类看重的是“能不能造出来”,第三类看重的是“怎么造、参数怎么填”,下面我都会按这个思路展开。
需要说明的是,不同厂商的测试仪在菜单命名和参数组织上差异很大,我下面讲的操作逻辑基于这类设备的常见实现方式来补全,具体字段名称请以你手上的设备为准,但背后的思路是通用的。
1.1 为什么标准协议模板会不够用
标准协议模板的本质是“把常见协议的字段做成表单”,你选一个 IPv4 over Ethernet,它就把目的 MAC、源 MAC、以太类型、IP 头各字段列出来让你填。这种方式对 90% 的常规测试足够了,剩下的 10% 才是真正折磨人的地方。
举个具体的例子。某类设备会在以太网头和内层 IP 之间插入一段 8 字节的私有标识,用来携带设备内部的端口号和优先级信息。这段内容既不是 VLAN,也不是 MPLS,标准模板里压根没有这个位置。你要么放弃测试这个特性,要么就得用自定义能力,把这段字节精确地插进去。
再比如异常帧测试。你要验证对端设备收到一个长度字段和实际长度不一致的帧会不会正确丢弃,或者收到一个校验和错误的帧会不会静默处理。这类测试的核心就是“故意造错”,而标准模板为了保证报文合法,往往会自动帮你算好校验和、自动补全长度。这时候你需要的是能关掉自动计算、手动填任意值的功能,这同样是 CDF 的用武之地。
还有一个经常被忽略的场景:超长载荷。有些设备在处理大于标准 MTU 的帧时会有特殊路径,比如分片重组或者巨帧转发。你要测这条路径,就得发出一帧载荷远超常规的报文。Extended Payload 的价值就在这里,它允许你把载荷区当成一块可以随意填充的内存,长度由你定,内容由你定。
注意:自定义不等于随便填。很多设备在收到长度字段与实际字节数不符的帧时,行为是未定义的,可能丢包也可能崩溃。造异常帧之前,先确认被测设备有没有防护机制,避免把测试变成破坏性操作。
2. 核心机制拆解:一帧数据是怎么被“拼”出来的
理解 CDF 的关键,是把一帧报文看成一条流水线:从最外层的帧头开始,一层层往里叠,每一层都是“类型标识 + 该类型的字段内容”。标准模板做的事是预先准备好常用的几种层,你只能选;CDF 做的事是把每一层的定义权交给你,你可以决定这一层有多长、里面每个字节是什么意思。
2.1 帧结构的三个可编程区域
我把这类功能通常能控制的部分归纳成三个区域,这样理解起来比较清楚。
第一个是帧头区域。这里放的是以太网头以及可能存在的 VLAN 标签、MPLS 标签。可编程的点在于:标签层数可以自定义,标签内容可以自定义,甚至以太类型字段也能填一个非标准值,用来标识“后面跟的是我自己定义的格式”。
第二个是协议头区域。标准情况下这里是 IP 头、TCP/UDP 头。CDF 允许你完全跳过这些,直接放一段自定义字节;也允许你先放标准 IP 头,再在后面接一段私有内容。
第三个是载荷区域,也就是 Extended Payload 主要作用的地方。这段内容对测试仪来说就是一串字节,它不解析、不校验,原样发出去。长度可以从几个字节到几千字节,内容可以是固定模式、递增序列、随机数据,或者从文件里读进来的一段真实抓包内容。
这三个区域组合起来,理论上可以拼出任意格式的帧。实际使用中,难点不在“能不能拼”,而在“拼出来的帧,接收端能不能正确识别”。这就引出下一个话题:校验和与长度字段的处理。
2.2 校验和、长度字段:自动还是手动
这是实操中最容易出错的地方,我单独拿出来讲。一帧报文里有好几处“自描述”字段:以太网帧本身不带长度字段,但 IP 头里有总长度,TCP/UDP 头里有校验和,某些私有协议里还有自己的 CRC。测试仪默认会帮你把这些算好,因为绝大多数测试需要的是合法报文。
但做自定义报文时,你往往需要接管这些字段。常见的配置项一般包括三类:
| 配置项 | 自动模式 | 手动模式 | 适用场景 |
|---|---|---|---|
| IP 总长度 | 按实际字节数填写 | 填入指定值 | 测试长度字段异常的设备行为 |
| TCP/UDP 校验和 | 硬件计算并填入 | 填入固定值或随机值 | 验证对端是否校验和、错误帧是否丢弃 |
| 帧校验序列 FCS | 硬件生成 | 可配置为错误值 | 测试物理层或 MAC 层的错误处理 |
自动模式的底层逻辑是:硬件在发包前扫描整帧内容,按协议规则算出结果再回填。手动模式则是绕过这个计算,直接把你填的值写进去。要注意的是,一旦你把手动模式打开,后续所有依赖这个字段的检查都得你自己负责,测试仪不会再帮你兜底。
我踩过的一个坑是:手动填了 IP 总长度,但忘了同步调整实际载荷长度,结果发出去的帧被对端直接丢弃,排查了半天才发现是自己造的帧自相矛盾。后来养成的习惯是,只要动了长度类字段,就把“实际字节数”和“字段声明值”列在一张纸上对一遍,确认差值符合预期再发。
2.3 硬件拼接与软件拼接的差别
理解这一点,能帮你判断什么需求该用测试仪、什么需求该用脚本。软件拼接(比如用抓包库构造报文再用普通网卡发)的灵活性最高,任何字节都能改,但受限于操作系统协议栈和网卡驱动,速率很难打高,时间戳精度也受调度影响。
硬件拼接是测试仪内部用可编程逻辑实现的,报文模板在发流之前就编译成了硬件能直接执行的描述,发包时按这个描述逐段填充。好处是速率能跑到线速、时间戳精度高、多流之间严格隔离;代价是灵活性有边界,比如某些设备对自定义层的层数有限制,或者对载荷区的最小粒度有要求。
我的经验是:需要大规模、长时间、高精度地发非标帧,用测试仪的自定义功能;需要快速验证一个想法、报文格式还没定型,先用脚本在低速环境跑通,再搬到测试仪上。两条路不冲突,反而是互补的。
3. 实操:从零配一条自定义报文流
下面按实际操作顺序走一遍。再次提醒,不同设备界面不同,但步骤骨架基本一致,你对照着自己设备的菜单往里套就行。
3.1 第一步:确定帧的“骨架”再动手配置
很多人一上来就打开配置界面开始填,填到一半发现结构不对,推倒重来。我的建议是先花五分钟在纸上画出帧结构,标清楚每一段的偏移和长度。
画的时候回答四个问题:
- 外层用什么以太类型?填标准值还是自定义值?
- 中间有几层标签?每层多长?
- 私有头有多少字节?每个字节代表什么?
- 载荷多长?内容从哪来?
举个具体的设计:假设要模拟一种带 4 字节私有头的帧,结构是“以太网头(14 字节)+ 私有头(4 字节)+ 载荷(可变)”。以太类型填一个非标准值比如 0x88B5,表示后面是私有格式。私有头 4 字节里,第 1 字节是版本号,第 2 字节是消息类型,后 2 字节是序号。
这个设计画出来之后,配置界面里怎么填就一目了然了:帧头区域选自定义以太类型,协议头区域选“无标准协议头”,直接进自定义字节编辑,载荷区域设长度和填充模式。
提示:先把结构画清楚,再进界面填,能省掉大量反复调试的时间。我见过太多人因为少算了一个 VLAN 标签的 4 字节,导致后面所有偏移全错,排查了两三个小时。
3.2 第二步:配置帧头与自定义字段
进入帧编辑界面,先处理最外层。以太网头需要填目的 MAC、源 MAC、以太类型。如果被测设备对 MAC 有要求,这里要填对;如果只是打流量,可以随便填,但要保证同一批流里的 MAC 组合有区分度,方便后续按流统计。
以太类型这里有个细节:如果你填的是标准值(比如 0x0800 表示 IPv4),测试仪可能会自动按 IPv4 去解析后面的内容,这就和你的自定义意图冲突了。所以要用自定义格式时,务必选一个不冲突的类型值。常见的做法是用实验性类型段(0x88B5 到 0x88B7 这一类),或者干脆用一个没人用的值。
接下来是自定义字段的编辑。这类设备通常提供一个字节级的编辑器,你可以按偏移填固定值,也可以设成变量。变量是自定义报文的灵魂,因为它让每一帧可以不一样。
常见的变量类型包括:
- 递增序列:每帧加一,用来检测丢包和乱序,是最常用的。
- 固定模式:所有帧同一位置填同一个值,用来做标记。
- 随机值:验证对端在处理随机内容时是否稳定。
- 列表循环:从一组预设值里轮换,模拟多种消息类型交替出现。
我在配私有头的时候,习惯把序号放在私有头里而不是载荷里,原因是:如果对端有解析逻辑,它会先读私有头,序号放在这里能直接验证解析是否正确;如果放在载荷深处,对端可能根本读不到就丢了。
3.3 第三步:Extended Payload 的长度与填充策略
载荷区是 Extended Payload 的主战场。配置时主要有三个参数:长度、填充模式、是否随帧变化。
长度怎么定?看你的测试目标。如果是验证 MTU 边界,就取 1500、1501、9000 这几个关键值分别发一轮。如果是压测转发性能,长度分布要贴近真实业务,常见做法是按 IMIX 模型混合大小包,比如 64 字节占大头、1500 字节占一部分、中间尺寸穿插。如果是验证超长帧处理,就往 9000 以上走,但要注意链路上每个环节的 MTU 是否支持。
填充模式的选择直接影响你能从结果里读出什么信息。固定填充(比如全 0x00 或全 0xFF)最简单,适合做基础连通性验证;递增填充适合做数据完整性校验,接收端如果发现某段内容不连续,就说明中间有重排或损坏;伪随机填充更接近真实流量,适合做压力测试,但排查问题时不如递增模式直观。
这里有个容易忽略的点:载荷内容会影响压缩和去重逻辑。有些被测设备内部有报文去重或压缩机制,如果所有帧的载荷完全一样,可能触发非预期的路径,导致测出来的性能虚高。我的做法是至少让载荷里的某一段随帧号变化,避免出现大量完全相同的帧。
3.4 第四步:速率、流数与发送控制
报文配好之后,接下来是发送参数。400G/800G 环境下,这几个参数需要仔细算。
先算理论线速。以 400G 为例,每秒可以发送的 64 字节小包数量约为 400e9 / (64+20) / 8,其中 20 字节是按前导码加帧间隙的常见估算值,算下来大约是 5.95 亿包每秒。这个数量级意味着,你配的流数如果太多,每条流分到的带宽就很少,统计精度会下降;流数太少又压不满带宽。
再说流数。测试仪通常支持按字段做流区分,比如按目的 MAC、按 IP、按自定义字段的某个字节展开成多条流。做自定义报文时,如果你的私有头里有消息类型字段,可以按这个字段展开,模拟多种消息混合的场景。但要注意展开的基数,几十条流一般足够,上千条流要确认设备的内存和统计能力跟得上。
发送控制上,常见模式有持续发送、定包数发送、定时发送。做异常帧测试时我倾向用定包数,比如只发 100 个错误帧,然后观察对端计数器的变化,发完就停,方便对账。做性能压测则用持续发送,配合流量统计看是否有丢包。
注意:高速率下先从小流量开始验证。我习惯先用 1% 线速发几百个包,确认对端能正确收到、内容符合预期,再逐步提到满线速。直接满速发自定义帧,一旦格式有问题,排查成本会高很多。
4. 典型应用场景:这些能力到底用在哪
光讲配置还不够,得说清楚什么情况下值得动用这套功能。我按实际项目里遇到的频次排个序。
4.1 私有协议与封装格式的验证
这是最主流的用法。很多设备在标准以太网之上有自己的封装层,比如带设备内部转发信息的头、带租户标识的扩展标签、带时间戳的测量头。这些格式只有厂商自己知道,公开标准里查不到,测试仪的标准模板自然造不出来。
用 CDF 的做法是:按厂商给的格式文档,把每一段字节的位置和含义映射到自定义字段编辑器里,造出合法帧发给对端,验证对端能否正确解析、能否按预期转发。更进一步,可以故意改坏其中某几个字节,看对端的容错行为是否符合设计。
这类测试的价值在于,它能覆盖芯片或固件里那些“只有内部人才知道”的代码路径。标准协议测试只能验证公开标准的部分,私有格式的解析逻辑往往是最容易出 bug 的地方,因为没有现成的测试工具。
4.2 异常帧与边界条件测试
异常帧测试的核心思路是“在合法帧的基础上,只改一个地方”。CDF 让这个“改一个地方”变得非常精确,因为每个字节都在你的控制之下。
常见的异常类型包括:
- 长度字段声明值与实际字节数不符。
- 校验和错误。
- 类型字段填了设备不认识的值。
- 私有头里的版本号超出支持范围。
- 载荷长度刚好卡在缓冲区边界上,比如比最大值多一个字节。
这些测试的目的不是把设备搞崩,而是验证它的防御逻辑是否健全。一个设计良好的设备,遇到异常帧应该静默丢弃并计数,而不是复位或者转发出去。用测试仪精确构造这些帧,比用脚本构造更可靠,因为高速率下脚本很难保证每一帧都精确符合预期。
4.3 超长载荷与巨帧路径验证
Extended Payload 在长度上的自由度,让它特别适合验证巨帧相关的能力。比如某设备宣称支持 9000 字节的巨帧,你要验证的不只是“能不能发过去”,还包括“超过 9000 会怎样”“刚好 9000 时转发延迟是多少”“巨帧和小包混合时调度是否公平”。
做这类测试时,长度参数要成组设计。我的习惯是取几个关键点:标准 MTU(1500)、标准 MTU 加一(1501)、常见巨帧值(9000)、巨帧加一(9001),再加一个明显超限的值(比如 12000)。每个长度发一轮,记录对端的接收计数、丢弃计数和转发延迟,就能画出这条路径的行为曲线。
这里有个实操细节:长度加大之后,单帧的发送时间变长,同样包数下的总时长会显著增加。做时间敏感的测试时,要把这个因素算进去,否则可能误判为性能下降。
4.4 与标准协议混合的复杂流量模型
真实网络里不会只有自定义帧,一定是标准流量和私有流量混在一起。测试仪的价值在于,它可以在同一条链路上同时发多种类型的流,验证设备在混合场景下的调度和隔离行为。
常见的混合模型是:大部分带宽走标准 TCP/UDP 流量,小部分带宽走自定义私有帧,观察私有帧是否会影响标准流的转发质量,或者反过来。这类测试能暴露出调度器在优先级处理上的问题,比如私有帧被错误地当成高优先级,挤占了正常业务。
配置上的关键是给不同流打上可区分的标记。自定义流可以用独特的以太类型或者独特的私有头值来标识,这样在统计结果里就能把两类流分开看。如果不做区分,混在一起统计,出了问题根本定位不到是哪类流引起的。
5. 实操中踩过的坑与排查思路
这部分是我觉得最有价值的内容,因为设备手册上不会写这些。
5.1 常见问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 对端完全收不到自定义帧 | 以太类型不被识别,对端直接丢弃 | 先用标准类型验证链路,再换成自定义类型;抓包确认帧确实发出来了 |
| 收到的帧内容与配置不符 | 偏移算错,某个字段覆盖了相邻区域 | 逐字节比对发送内容和抓包结果,重点查标签层数和私有头长度 |
| 高速率下大量丢包 | 流数过多导致统计资源不足,或对端缓冲区溢出 | 降低流数、降低速率分别测试,定位是发送侧还是接收侧问题 |
| 载荷内容出现非预期变化 | 填充模式设成了变量但没意识到 | 检查每个字段的变量配置,确认哪些位置会随帧变化 |
| 校验和错误但配置的是自动模式 | 自定义字段覆盖了校验和位置 | 确认自定义区域没有和协议头的校验和字段重叠 |
这张表里的每一条我都实际遇到过。特别是第一条,曾经花了一个下午排查,最后发现是对端设备只认特定的几个以太类型,其他一律丢弃。这个信息在任何文档里都没写,只能靠抓包对比才发现。
5.2 偏移计算:最容易出错的地方
自定义报文的所有问题里,偏移算错占了至少一半。原因是帧结构是层层叠加的,每加一层,后面所有字段的偏移都要跟着变。人在配置界面里填的时候,很容易只想着“这个字段填什么值”,忘了“它现在在第几个字节”。
我的做法是维护一张偏移表,每加一层就更新一次。比如:
- 以太网头:偏移 0 到 13,共 14 字节。
- VLAN 标签:偏移 14 到 17,共 4 字节。
- 私有头:偏移 18 到 21,共 4 字节。
- 载荷:从偏移 22 开始。
有了这张表,配置的时候逐项对照,出错的概率大幅下降。更进一步,可以在配置完成后,先用低速发几个包抓下来,用抓包工具按十六进制查看,和偏移表逐字节核对,确认无误再提速。
5.3 速率与精度的取舍经验
400G/800G 环境下有一个绕不开的现实:速率越高,能做的精细统计越少。原因是高速率下每秒的包数太多,硬件统计资源有限,某些维度的统计会被合并或抽样。
我的经验是分两阶段做测试。第一阶段用较低速率(比如 10% 到 25% 线速)做功能和格式验证,这个阶段可以开全量统计、逐流分析,把格式问题全部解决掉。第二阶段提到目标速率做性能测试,这个阶段只关注总量指标,比如总收发包数、总丢包数、平均延迟,不再做逐流细查。
这个分阶段的做法能避免一个常见的浪费:在满线速下调试格式问题,改了参数重新发,一轮下来几分钟,效率极低。而在低速率下,一轮只要几秒,调十次也就一分钟。
5.4 自定义程度与可维护性的平衡
最后一个经验是关于“度”的把握。CDF 的灵活度很容易让人上头,什么字段都想做成变量,结果配出来的流复杂到自己都看不懂,过两周回来改都改不动。
我的建议是:只把需要变化的字段做成变量,其余全部填固定值。比如你的测试目标是验证序号处理,那就只把序号字段做成递增,其他字段全固定。这样流配置简单、排查容易、别人接手也能看懂。
另外,配置完成后把帧结构、偏移表、各字段含义写成一份简短的说明,和配置文件放在一起。这个习惯在多人协作的环境里尤其重要,因为自定义报文的知识只存在于配置者的脑子里,人一走就成了黑盒。
5.5 关于设备能力边界的确认
不同设备对自定义能力的支持程度差别很大,动手之前先确认几个关键限制:自定义层数有没有上限、载荷最大长度是多少、变量字段有没有数量限制、按自定义字段展开流是否支持。
这些限制通常在设备的能力说明里有,但写得很隐蔽。我的做法是直接做几个试探性配置:故意配一个超出预期的层数,看设备是报错还是静默截断;配一个很大的载荷长度,看能不能保存。通过这种方式快速摸清边界,比翻文档快得多。
6. 一点个人体会
这套功能我用了挺长时间,最大的感受是:它的价值不在于“能造任意帧”这个能力本身,而在于它把原本需要写代码、调驱动、搭环境才能做的事,压缩到了在测试仪界面上填参数的几分钟里。对于需要反复迭代报文格式的验证工作,这个效率提升是数量级的。
但反过来,自由度越高,对使用者的要求也越高。标准模板模式下,你不太会犯格式错误,因为模板帮你保证了合法性;自定义模式下,每一个字节都是你的责任,一个偏移算错就可能导致整轮测试白做。所以我现在养成的习惯是,任何自定义报文在正式使用之前,先用最低速率发一百个包,抓下来逐字节核对,确认无误再往上提速。这个习惯帮我省掉的时间,远多于它花掉的时间。
最后一个建议给刚接触这类功能的人:先把标准模板用熟,理解一帧报文的标准结构长什么样,再去碰自定义。知道“正常”是什么样,才能准确地造出“不正常”。跳过这一步直接上自定义,很容易造出一堆自己都说不清楚哪里不对的帧,调试起来非常痛苦。