# TsnHub
**Repository Path**: FasterEdge/TsnHub
## Basic Information
- **Project Name**: TsnHub
- **Description**: TSN(时间敏感网络)中间节点 - 基于o6
- **Primary Language**: C++
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-08-31
- **Last Updated**: 2026-08-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
TsnHub
基于 open62541 的 Linux 本地 TSN 仿真中间节点
## 一、项目简介
TsnHub 是 FasterEdge 生态中的 TSN 仿真组件。它在 OPC UA PubSub 数据的接收与重新发布之间加入用户态 TSN 调度器,用于在普通 Linux 主机或 Docker 环境中模拟时间敏感网络的队列、优先级、门控、时延、抖动、丢包与拥塞行为。
目标数据流:
```text
OPC UA Publisher
|
| UDP/UADP
v
open62541 DataSetReader
|
v
User-space TSN Scheduler
- 8 priority queues
- Gate Control List
- delay / jitter / loss
- queue capacity
|
v
open62541 DataSetWriter
|
| UDP/UADP
v
OPC UA Subscriber
```
当前仓库已经实现 Linux 原生 open62541 UDP/UADP DataSetReader/DataSetWriter、用户态 TSN 调度器、Portable PubSub 兼容模式,以及 Publisher → TsnHub → Subscriber 三节点 Docker 仿真环境。
## 二、术语
- **Frame**:进入 TsnHub 的一条待调度消息,包含 sequence、priority、stream 与 payload。
- **Priority Queue**:优先级 0~7 的八个独立队列,7 为最高优先级。
- **Gate Control List(GCL)**:按周期控制哪些优先级队列可以发送的时隙列表。
- **Portable PubSub**:跨平台 UDP 封装,payload 可透明承载 OPC UA PubSub/UADP 网络消息。
- **Native PubSub**:Linux 下由 open62541 原生 DataSetReader/DataSetWriter 完成的 UDP/UADP 收发。
- **SimulatorNode**:连接入口、调度器和出口的中间节点。
## 三、核心能力
| 能力 | 说明 |
|---|---|
| 八级优先级 | 支持优先级 0~7,并优先释放高优先级帧 |
| Gate Control List | 使用重复时隙定义不同优先级队列的开放窗口 |
| 固定时延 | 为所有通过节点的帧增加固定转发延迟 |
| 随机抖动 | 在固定时延基础上增加可配置的对称随机抖动 |
| 丢包仿真 | 按 0~1 的概率随机丢弃输入帧 |
| 队列容量 | 限制每个优先级队列的最大积压帧数 |
| 可复现实验 | 通过固定随机种子复现抖动和丢包结果 |
| 运行统计 | 输出 accepted、released、dropped_loss、dropped_queue |
| UDP 转发 | 支持 Linux/macOS BSD Socket 与 Windows Winsock2 |
| open62541 | 链接 open62541 1.5;Linux 原生 PubSub 模式使用 UDP/UADP |
## 四、目录结构
```text
TsnHub/
├── main.cpp # CLI 与进程入口
├── tsn/
│ ├── Frame.hpp # 调度帧定义
│ ├── Scheduler.hpp/.cpp # 用户态 TSN 调度器
│ └── SimulatorNode.hpp/.cpp # UDP 中间节点
├── transport/
│ ├── UdpSocket.hpp/.cpp # 跨平台 UDP 封装
│ └── PortablePubSub.hpp/.cpp # Portable PubSub Envelope
├── tests/
│ ├── SchedulerTest.cpp
│ ├── PortablePubSubTest.cpp
│ ├── UdpLoopbackTest.cpp
│ └── SimulatorNodeTest.cpp
├── CMakeLists.txt
├── conanfile.py
├── conandata.yml
└── Logo.png
```
原生 PubSub 与 Docker 文件:
```text
├── pubsub/Open62541Bridge.* # open62541 DataSetReader/DataSetWriter
├── docker/PubSubFixture.cpp # Publisher / Subscriber 测试程序
├── Dockerfile # open62541 源码构建与运行镜像
├── docker-compose.yml # 三节点仿真拓扑
└── tests/native_pubsub_integration.sh
```
## 五、构建依赖
- Linux(原生 PubSub 最终运行环境)
- CMake >= 3.23
- Conan 2.x
- C++17 编译器
- CLI11 2.6
- open62541 1.5
Portable PubSub 模式也可以在 macOS 和 Windows 构建。open62541 原生 UDP/UADP PubSub 模式统一以 Linux/Docker 为目标环境。
## 六、本地构建
```bash
conan install . \
--output-folder=build-tsn \
--build=missing \
-s build_type=Debug
cmake -S . -B build-tsn/cmake \
-DCMAKE_TOOLCHAIN_FILE=build-tsn/build/Debug/generators/conan_toolchain.cmake \
-DCMAKE_BUILD_TYPE=Debug
cmake --build build-tsn/cmake -j
ctest --test-dir build-tsn/cmake --output-on-failure
```
查看当前构建能力:
```bash
./build-tsn/cmake/TsnHub --capabilities
```
输出示例:
```text
open62541=1.5.0
native_pubsub=false
portable_pubsub=true
portable_scheduler=true
```
在 Linux 原生 PubSub 构建中,`native_pubsub` 应为 `true`。
## 七、Portable PubSub 运行方式
```bash
./build-tsn/cmake/TsnHub \
--listen 127.0.0.1:4841 \
--forward 127.0.0.1:4842 \
--gate 1000:0x0f \
--gate 1000:0xf0 \
--delay-us 200 \
--jitter-us 50 \
--loss 0.01 \
--queue 1024 \
--seed 42
```
参数说明:
| 参数 | 说明 |
|---|---|
| `--listen host:port` | 输入 UDP 地址 |
| `--forward host:port` | 输出 UDP 地址 |
| `--gate duration_us:mask` | Gate 时隙,可重复指定;mask 的 bit 0~7 对应优先级 0~7 |
| `--delay-us` | 固定转发时延,单位微秒 |
| `--jitter-us` | 随机抖动范围,实际值为 ±jitter |
| `--loss` | 0~1 的随机丢包概率 |
| `--queue` | 每个优先级最大排队帧数 |
| `--seed` | 随机种子 |
| `--capabilities` | 输出构建能力并退出 |
按 `Ctrl+C` 或发送 `SIGTERM` 后,节点停止并输出统计信息。
## 八、Gate 配置示例
```bash
--gate 1000:0x0f --gate 1000:0xf0
```
表示一个 2000 微秒周期:
1. 前 1000 微秒开放优先级 0~3;
2. 后 1000 微秒开放优先级 4~7。
如果不提供 `--gate`,默认每 1000 微秒开放全部优先级:
```text
1000:0xff
```
## 九、Portable PubSub Envelope
```text
magic 4 bytes "TSN1"
priority 1 byte 0..7
sequence 8 bytes big-endian
streamLen 2 bytes big-endian
stream N bytes UTF-8
payload remaining bytes
```
payload 对 TsnHub 保持透明,可以放入 open62541 或其他 OPC UA 实现生成的 UADP 网络消息。
## 十、Linux 原生 open62541 PubSub
Linux 原生模式采用 open62541 的以下组件:
- `UA_PubSubConnectionConfig`
- `UA_ReaderGroupConfig`
- `UA_DataSetReaderConfig`
- `UA_Server_DataSetReader_createTargetVariables`
- `UA_PublishedDataSetConfig`
- `UA_DataSetFieldConfig`
- `UA_WriterGroupConfig`
- `UA_DataSetWriterConfig`
预期处理链路:
```text
DataSetReader subscribed variable
|
v
TSN Scheduler
|
v
DataSetWriter published variable
```
第一版原生 DataSet 使用 `Int32` 字段,便于验证 Publisher → TsnHub → Subscriber 的完整链路。
原生模式运行示例:
```bash
TsnHub --mode native \
--subscribe-url opc.udp://0.0.0.0:4841 \
--publish-url opc.udp://subscriber:4842 \
--input-publisher-id 1 \
--input-writer-group-id 1 \
--input-writer-id 1 \
--output-publisher-id 2 \
--output-writer-group-id 2 \
--output-writer-id 2 \
--publish-interval-ms 1 \
--delay-us 200
```
## 十一、Docker 三节点仿真
Dockerfile 从源码构建 open62541 1.5.0,并开启:
```text
UA_ENABLE_PUBSUB=ON
UA_ENABLE_PUBSUB_INFORMATIONMODEL=ON
```
构建镜像:
```bash
docker build -t tsnhub .
```
启动 Publisher、TsnHub 和 Subscriber:
```bash
docker compose up --build --abort-on-container-exit
```
预期结果包括:
```text
publisher final_value=20
accepted=20 released=20 dropped_loss=0 dropped_queue=0
subscriber final_value=20
```
停止并清理:
```bash
docker compose down --remove-orphans
```
## 十二、测试
| 测试 | 覆盖内容 |
|---|---|
| `scheduler` | Gate、优先级、时延、丢包和队列容量 |
| `portable_pubsub` | Envelope 编解码与畸形包拒绝 |
| `udp_loopback` | 真实 UDP 回环收发与超时 |
| `simulator_node` | UDP 入口 → Scheduler → UDP 出口端到端转发 |
| `native_pubsub_integration` | open62541 Publisher → TsnHub → Subscriber 原生 UDP/UADP 链路 |
运行:
```bash
ctest --test-dir build-tsn/cmake --output-on-failure
```
严格编译检查:
```bash
cmake -S . -B build-tsn/warnings \
-DCMAKE_TOOLCHAIN_FILE=build-tsn/build/Debug/generators/conan_toolchain.cmake \
-DCMAKE_CXX_FLAGS='-Wall -Wextra -Wpedantic -Werror'
cmake --build build-tsn/warnings -j
ctest --test-dir build-tsn/warnings --output-on-failure
```
## 十三、安全与限制
- TsnHub 是仿真工具,不提供真实硬件 TSN 的确定性保证。
- 用户态调度会受到操作系统线程调度、容器调度和普通网卡缓冲影响。
- `--loss` 和 `--jitter-us` 使用伪随机算法;固定 `--seed` 可复现实验。
- UDP 不保证可靠、有序或不重复。
- 当前 Portable PubSub Envelope 不是 OPC UA 标准网络格式;标准 UADP 字节位于 payload 内部。
- Linux 原生模式将直接使用 open62541 的标准 UDP/UADP PubSub。
## 十四、许可证
本项目使用 Apache License 2.0,详见 [LICENSE](./LICENSE)。