3. TSN核心机制(下):信用整形(CBS 802.1Qav)、帧抢占(802.1Qbu)、流过滤与监管(PSFP 802.1Qci)
好,我们接着聊TSN剩下的几个核心机制。上一节讲了时间感知整形(TAS),那玩意儿适合控制类流量,但有个问题——它太“死板”了。你想想看,如果某个门控窗口没被占满,剩下的带宽就白白浪费了。所以,这一节我们要聊的CBS、帧抢占和PSFP,就是来解决这些“灵活性问题”的。
3.1 信用整形(CBS 802.1Qav)
CBS,全称Credit-Based Shaper,中文叫“信用整形”。我第一次听到这个名字时,还以为跟银行征信有关系(笑)。其实它很简单——每个流都有一个“信用值”,能发数据就扣信用,不能发就攒信用。
核心思想: 用信用值来控制发送速率,避免突发流量把网络堵死。
3.1.1 工作原理
每个AVB(Audio Video Bridging)流都有一个信用值。信用值随时间线性增加,发送数据时线性减少。只有信用值大于等于0时,才能发送数据。
我个人习惯把CBS比作“水桶”:
- 信用增加: 就像水龙头往桶里滴水,速率是固定的(idleSlope)
- 信用减少: 发送数据时,桶里的水被抽走,速率也是固定的(sendSlope)
- 信用上限: 桶不能无限大,有个上限(hiCredit)
- 信用下限: 桶也不能空到负数太多,有个下限(loCredit)
嗯,这里要注意:信用值可以为负。当信用值为负时,即使链路空闲,也不能发送数据,必须等到信用值恢复到0以上。
关键参数:
- idleSlope: 信用增加速率(单位:bits/s),等于预留带宽
- sendSlope: 信用减少速率(单位:bits/s),等于发送速率减去预留带宽
- hiCredit: 最大信用值,等于最大突发大小
- loCredit: 最小信用值,等于最小突发大小
3.1.2 我在项目中遇到的CBS坑
我曾经在一个车载以太网项目中,用CBS来整形摄像头数据流。摄像头输出是典型的“帧突发”——一帧图像数据在短时间内全部涌出。结果呢?CBS的信用值瞬间被打到负数,后续数据被阻塞,导致端到端延迟超标。
后来怎么解决的?我调整了hiCredit参数,让它能容纳一个完整帧的突发。说白了,就是给“水桶”加粗一点,让它能装下更多的“水”。
避坑指南: CBS的hiCredit参数一定要根据最大帧长来设置。我建议你留出20%的余量,防止多个流同时突发。
3.1.3 代码示例:CBS参数计算
/* CBS参数计算示例 */
/* 假设:预留带宽 = 100Mbps,链路速率 = 1000Mbps,最大帧长 = 1500字节 */
#define IDLE_SLOPE 100000000 /* 100 Mbps */
#define SEND_SLOPE 900000000 /* 1000 - 100 = 900 Mbps */
#define MAX_FRAME_SIZE 1500 /* 字节 */
/* 计算最大信用值 */
uint32_t hiCredit = (MAX_FRAME_SIZE * 8 * IDLE_SLOPE) / SEND_SLOPE;
/* hiCredit = (1500 * 8 * 100000000) / 900000000 ≈ 1333 bits */
/* 计算最小信用值 */
uint32_t loCredit = 0; /* 通常设为0 */
printf("hiCredit = %u bits\n", hiCredit);
printf("loCredit = %u bits\n", loCredit);
3.2 帧抢占(802.1Qbu)
帧抢占,英文叫Frame Preemption。说白了,就是允许一个“高优先级”的帧打断“低优先级”帧的传输。
你可能会问:“以太网不是CSMA/CD吗?怎么还能打断?” 嗯,传统以太网确实不行。但802.1Qbu引入了一个新概念——可抢占MAC(Preemptable MAC)。
3.2.1 工作原理
帧抢占的核心是“分片”。当一个长帧正在传输时,如果来了一个高优先级帧(比如控制指令),发送方会把当前帧“切”成两段:
- 第一段: 已经发送的部分,加上一个特殊的“分片结束”标记
- 第二段: 剩余部分,等抢占帧发送完后再继续发送
接收方会把这两个分片重新组装成完整的帧。整个过程对上层协议是透明的——应用程序根本不知道发生了抢占。
重要限制: 帧抢占只适用于“可抢占”的帧。802.1Qbu定义了两种帧类型:
- 可抢占帧(preamptable): 可以被中断,通常是音视频数据
- 不可抢占帧(express): 不能被中断,通常是控制指令
我个人建议:把时间敏感的控制帧设为“不可抢占”,把音视频数据帧设为“可抢占”。
3.2.2 帧抢占的延迟收益
我记得有一次做车载网络仿真,对比了开启和关闭帧抢占的延迟表现。结果很有意思:
| 场景 | 无帧抢占(微秒) | 有帧抢占(微秒) | 改善比例 |
|---|---|---|---|
| 控制帧被1500字节视频帧阻塞 | 12.0 | 0.5 | 96% |
| 控制帧被500字节音频帧阻塞 | 4.0 | 0.5 | 87.5% |
| 多个控制帧同时到达 | 15.0 | 1.0 | 93.3% |
你看,帧抢占对控制帧的延迟改善非常明显。但要注意,它不能完全消除延迟——抢占本身也有开销(分片和重组的时间)。
3.2.3 实现注意事项
我曾经在一个项目中,因为帧抢占配置不当,导致接收方频繁丢包。排查了半天才发现问题:
- 问题: 发送方开启了帧抢占,但接收方没开启
- 结果: 接收方收到分片后,无法识别,直接丢弃
- 教训: 帧抢占必须端到端支持,中间交换机也要配置正确
避坑指南: 如果你在项目中用帧抢占,一定要检查所有网络节点的配置。我曾经吃过这个亏,现在每次都会写一个自动化测试脚本,验证所有节点的帧抢占能力。
3.3 流过滤与监管(PSFP 802.1Qci)
PSFP,全称Per-Stream Filtering and Policing。这个名字有点绕,说白了就是“给每个流设个门禁”。
你想想看,在车载网络中,如果某个ECU(电子控制单元)出了故障,疯狂发送数据,会发生什么?整个网络都会被它堵死。PSFP就是用来防止这种“流氓流”的。
3.3.1 核心功能
PSFP有三个主要功能:
- 流过滤(Filtering): 根据流ID(Stream ID)过滤数据帧,只允许合法的流通过
- 流监管(Policing): 监控每个流的速率,超过限制的帧被丢弃或标记
- 流门控(Gating): 类似TAS的门控,但PSFP是针对单个流的
PSFP的关键参数:
- committedInformationRate (CIR): 承诺信息速率,即流正常情况下的平均速率
- committedBurstSize (CBS): 承诺突发大小,即流允许的最大突发量
- excessInformationRate (EIR): 超额信息速率,超过CIR但允许的速率
- excessBurstSize (EBS): 超额突发大小,超过CBS但允许的突发量
3.3.2 我在项目中遇到的PSFP案例
我记得有一次做ADAS(高级驾驶辅助系统)的网络设计。摄像头和雷达的数据流都需要经过一个中央网关。如果不加PSFP,一旦摄像头故障,疯狂发送数据,雷达的控制指令就会被延迟,后果不堪设想。
我当时的做法是:
- 给每个摄像头流设置CIR=100Mbps,CBS=1500字节
- 给雷达流设置CIR=10Mbps,CBS=500字节
- 超过限制的帧直接丢弃(也可以选择标记为“黄色”,但车载场景我建议直接丢弃)
结果呢?有一次测试中,一个摄像头真的出了故障,发送速率飙到了500Mbps。PSFP直接把它的大部分帧都丢弃了,雷达流完全不受影响。嗯,这就是PSFP的价值。
3.3.3 代码示例:PSFP配置
/* PSFP流监管配置示例 */
/* 假设:摄像头流ID = 0x1001,CIR = 100Mbps,CBS = 1500字节 */
typedef struct {
uint32_t stream_id;
uint32_t cir; /* 单位:bps */
uint32_t cbs; /* 单位:字节 */
uint32_t eir; /* 单位:bps */
uint32_t ebs; /* 单位:字节 */
uint8_t drop_excess; /* 1=丢弃超额帧,0=标记为黄色 */
} psfp_stream_config_t;
psfp_stream_config_t camera_stream = {
.stream_id = 0x1001,
.cir = 100000000, /* 100 Mbps */
.cbs = 1500, /* 1500 字节 */
.eir = 0, /* 不允许超额 */
.ebs = 0,
.drop_excess = 1 /* 直接丢弃 */
};
/* 配置PSFP硬件 */
void psfp_configure_stream(psfp_stream_config_t *config) {
/* 写入硬件寄存器 */
write_reg(PSFP_STREAM_ID_REG, config->stream_id);
write_reg(PSFP_CIR_REG, config->cir);
write_reg(PSFP_CBS_REG, config->cbs);
write_reg(PSFP_EIR_REG, config->eir);
write_reg(PSFP_EBS_REG, config->ebs);
write_reg(PSFP_DROP_REG, config->drop_excess);
printf("PSFP configured for stream 0x%04X\n", config->stream_id);
}
3.3.4 PSFP与CBS的区别
很多初学者会把PSFP和CBS搞混。我简单说一下区别:
- CBS: 是“整形器”,它让流的发送速率变得平滑,避免突发
- PSFP: 是“监管器”,它检查流是否遵守约定,违规就处罚
说白了,CBS是“事前控制”,PSFP是“事后监管”。两者可以配合使用:先用CBS把流整形好,再用PSFP检查是否合规。
个人建议: 在车载网络中,我建议对每个关键流都配置PSFP。即使你认为某个ECU不会出问题,也要防一手。我曾经见过一个案例,ECU固件升级后,网络驱动出了bug,导致疯狂发包。如果没有PSFP,整个车机系统都会瘫痪。
3.4 三种机制的协同工作
最后,我简单说一下CBS、帧抢占和PSFP如何协同工作。在实际的车载网络中,它们不是孤立的:
- PSFP在入口处: 数据流进入交换机时,先用PSFP检查是否合规
- CBS在队列中: 合规的流进入队列,用CBS进行整形,控制发送速率
- 帧抢占在发送时: 当高优先级帧需要发送时,可以抢占正在发送的低优先级帧
嗯,这个流程我建议你画个图理解一下。我在项目中就是这么做的,效果很好。
重要提醒: 这三种机制都需要硬件支持。不是所有的以太网交换机都支持802.1Qbu和802.1Qci。选型时一定要确认芯片的能力。我曾经在一个项目中,因为选了一款不支持帧抢占的交换机,导致整个架构重新设计,教训深刻。
好了,这一节的内容就到这里。下一节我们会聊TSN的时钟同步机制(802.1AS),那是所有时间敏感应用的基础。到时候见。