DDS通信中间件——DDS-TSN规范

DDS通信中间件------DDS-TSN规范

做了十年DDS通信中间件产品的程序员和大家分享一下对DDS这套规范的个人理解。预期本系列文章将包括以下内容陆续更新:

  1. DDS规范概述
  2. DCPS规范解读 & QoS策略
  3. XTypes规范解读
  4. RTPS规范解读
  5. DDS安全规范解读
  6. DDS-RPC规范解读( 请求响应模式 & 函数调用模式
  7. DDS-TSN规范解读
  8. DDS-XRCE规范解读

1. 概述

1.1. TSN是什么?

TSN(时间敏感网络,Time-Sensitive Networking)是以太网技术的重要演进,旨在通过标准化协议解决传统以太网在确定性时延高可靠性时间同步等方面的局限性,从而满足工业自动化、车载网络、智能电网等对实时性要求严苛的场景需求。下图(侵删)展示了TSN的重要协议及功能TSN的核心功能及协议可归纳为以下四大类:

  • 时钟同步(Timing and Synchronization) , TSN通过高精度时钟同步协议确保网络中所有设备的时间一致性,这是实现低时延调度的基础。
    • IEEE 1588(PTP,精确时间协议):提供亚微秒级同步。
    • IEEE 802.1AS:基于PTP优化,专为TSN设计。
    • IEEE 802.1AS-REV:增强版,支持更复杂的网络拓扑。
  • 数据调度及流量整形(Traffic Shaping) ,通过智能调度机制,TSN可优先处理关键数据流,避免网络拥塞。
    • IEEE 802.1Qbv(时间感知整形,TAS):为时间敏感流量分配固定时间窗口。
    • IEEE 802.1Qav(基于信用的整形):适用于音视频等流媒体数据。
    • IEEE 802.1Qcr(异步流量整形):动态调整非实时流量。
  • 可靠性(Ultra Reliability) ,TSN通过冗余和错误检测机制保障数据传输的确定性。
    • IEEE 802.1CB(帧复制与消除):通过冗余路径提升容错能力。
    • IEEE 802.1Qci(帧检测过滤):拦截错误或恶意数据包。
    • IEEE 802.1Qca(路径控制):优化冗余路径选择。
  • 资源管理(Resource Management) ,TSN支持动态资源分配,确保关键任务始终获得所需带宽。
    • IEEE 802.1Qat(流预留协议,SRP):预先分配带宽资源。
    • IEEE 802.1Qcc(集中式配置):简化网络管理,支持动态配置。

1.2. DDS与TSN结合

那么基于何种考虑会想要结合DDS和TSN这两种技术,我们从以下几个方面来描述。

1.2.1. 为什么DDS需要TSN?
  • 增强主题数据可靠传输,DDS中间件作为应用层协议配置可靠传输时是通过反馈重传的方式进行可靠性保证,当链路发生中断时,只能等待或者传输失败,此时如果能够利用TSN的链路可靠能力即可增强主题数据可靠传输能力;

  • 实现端到端有界时延(确定性)数据传输,虽然DDS中有诸如Deadline、LatencyBudget的QoS策略来配置主题数据的时延,但是如果没有TSN基础设施来保证协议栈传输确定性是没有办法实现的。以下图为例,为了实现应用到应用的端到端确定性传输,需要传输的每个环节都具备确定性包括:

    • 应用程序到DDS中间件调用,接口调用通常都具备确定性;
    • DDS中间件处理逻辑,从接收到应用程序的数据到提交给协议栈的时间,这一部分需要各家的DDS中间件优化实现来保证;
    • 协议栈的端到端传输确定性,这一点就需要TSN规范来保证,包括:端节点处理以及交换设备的处理,涉及流量整形相关的规范。
1.2.2. 为什么TSN需要DDS?

TSN是二层规范,但是业务系统一般都是利用应用层协议,而采用DDS作为TSN规范的应用层"封装"有以下好处:

  • 提供更高级别的抽象,提供以数据为中心的发布/订阅通信模型(包括其他通信模式);
  • 多语言支持;
  • 更加简单的方式使用TSN能力,包括抽象为QoS配置,易于理解,统一配置方式屏蔽不同厂家TSN产品的使用区别。
1.2.3. 为什么DDS和TSN结合
  • DDS和TSN都实现了混合承载的通信能力,即都支持为需要传输的数据进行分级传输,体现为不同的QoS;
  • DDS的发布订阅和TSN的流定义都是1对多模式,非常适合结合。

2. DDS-TSN规范

回到DDS-TSN规范本身,协议涵盖的内容如下图所示,可以看出DDS-TSN的重点是在DDS系统如何部署在TSN网络上。

3. DDS-TSN部署模型

3.1. 应用配置(DDS实体配置)

这一部分是原本DDS系统就包含的,其结构如下图所示:

  • ApplicationLibrary,配置系统中包含的DDS应用,一个应用引用关联DomainParticiapntLibrary中一个或者多个域参与者;
  • DomainParticipantLibrary,配置系统中包含的域参与者的定义,包括子实体(主题、发布者、订阅者、数据写者、数据读者);
  • TypeLibrary,类型库,系统中DDS主题所关联的类型结构,通过主题的属性引用关联;
  • QosLibrary,Qos库,系统中所有实体的QoS集中存储的位置,通过各个实体的属性引用关联;

3.2. 部署配置

本身DDS系统在通常情况下是不需要部署方案的,因为本身DDS应用是具备位置无关性的,(在所有节点都是同构的前提下)应用程序运行在不同的节点上对系统的功能、性能不会产生影响。但是当需要部署在TSN上时,由于TSN需要事先规划流量才能达到预想的可靠性、时间确定性,所以在TSN上部署DDS系统时需要增加部署配置,这个配置也是这份规范的核心,只有在确定了部署方案的基础上,才能根据部署方案计算出底层TSN基础设施的配置,从而上下配合达到预想的可靠性、确定性。

部署配置的结构如下图所示:

  • 节点库,定义硬件环境,包括节点的IP地址、Mac地址(注意:实际实现时取决于底层DDS与TSN的适配形式,这些字段可能仅需要一部分);
  • 部署库,定义部署方案:
    • 哪个节点上运行哪些应用,节点引用节点库中的定义,应用引用上面应用配置中ApplicationLibrary的定义;
    • TSN相关的部署配置,在下面章节中具体介绍;

3.3. TSN配置

TSN配置隶属于部署配置,用于描述详细DDS的主题如何映射到TSN的流,这个配置主要有两个方面的作用:

  • DDS中间件使用这个配置来把主题数据打上特定的标签,TSN基础设施通过这些标签来识别流,注意:打标签的方式可以有多种,例如:二层的VLAN Tag、三层的dscp、或者6元组,具体的方式需要结合实际的TSN硬件来设计;
  • 这些配置交给TSN基础设施配置管理员,配置管理员根据这个配置来配置TSN基础设施(TSN终端或者TSN交换机);

TSN配置的结构如下图所示:

  • NetworkRequirements,基础网络的需求,包括冗余路径数量、允许的最大时延;
  • TrafficSpecification,流量规范,即该主题数据的周期、数据大小、所需要的流量整形算法等;
  • DataFrameSpecification,数据帧规范,即该主题数据将打上何种标签;

4. DDSI-RTPS适配TSN

4.1. 消息模块

为保障确定的行为以及确定的消息大小,TSN相关的DataWriter仅保留,协议认为其他的报文是不受规划的或者不必要的,会破坏TSN已经规划的流量:

  • Info_ts
  • data
  • data_frag

4.2. 发现模块

  • 所有的发现信息都只使用best-effort流量;
  • 使用静态发现,屏蔽所有可能的发现信息;

4.3. QoS策略

仅考虑以下配置:

  • BEST-EFFORT
  • VOLATILE
  • KEEP_LAST & depth=1

5. 配置示例

5.1. 示例概述

协议提供了两个在TSN上部署DDS系统的示例,分别是基于UDP/IP上通信的示例以及直接基于Ethernet上通信的示例。这里我们专注看UDP/IP作为底层通信的示例。应用部署以及主题发布/订阅图如下图所示。每个节点都安装了TSN网卡,通过以下配置可以完成:无论背景流量如何,Square、Triangle主题数据都能在2ms内提交给接收端。

为了增加配置的灵活性,配置分为两个部分:

假设系统中存在一个实体(一个程序、工具软件)有以下的功能,后面我们把这个实体称为DDS-TSN工具:

  • 读取上面的配置文件,按照部署策略部署应用;
  • 能够与CNC(或是工具链/任何能够配置底层网络的实体)通信;

5.2. 应用配置

定义了5个应用,和上图描述的一致,不赘述。

xml 复制代码
<!-- App1发布Square主题 -->
<application name="Application_1">
	<domain_participant name="DomainParticipant_1" domain_id="32" >
		<register_type name="ShapeType" type_ref="ShapeType" />
		<topic name="Square" register_type_ref="ShapeType" />
		<publisher name="Publisher_1">
			<data_writer name="SquareWriter_1" topic_ref="Square" />
		</publisher>
	</domain_participant>
</application>
<!-- App2发布Triangle主题 -->
<application name="Application_2">
	<domain_participant name="DomainParticipant_2" domain_id="32" >
		<register_type name="ShapeType" type_ref="ShapeType" />
		<topic name="Triangle" register_type_ref="ShapeType" />
		<publisher name="Publisher_2">
			<data_writer name="TriangleWriter_2" topic_ref="Triangle" />
		</publisher>
	</domain_participant>
</application>
<!-- App3订阅Square主题 -->
<application name="Application_3">
	<domain_participant name="DomainParticipant_3" domain_id="32" >
		<register_type name="ShapeType" type_ref="ShapeType" />
		<topic name="Square" register_type_ref="ShapeType" />
		<subscriber name="Subscriber_3">
			<data_reader name="SquareReader_3" topic_ref="Square" />
		</subscriber>
	</domain_participant>
</application>
<!-- App4订阅Triangle主题 -->
<application name="Application_4">
	<domain_participant name="DomainParticipant_4" domain_id="32" >
		<register_type name="ShapeType" type_ref="ShapeType" />
		<topic name="Triangle" register_type_ref="ShapeType" />
		<subscriber name="Subscriber_4">
			<data_reader name="TriangleReader_4" topic_ref="Triangle" />
		</subscriber>
	</domain_participant>
</application>
<!-- App5订阅Square、Triangle主题 -->
<application name="Application_5">
	<domain_participant name="DomainParticipant_5" domain_id="32" >
		<register_type name="ShapeType" type_ref="ShapeType" />
		<topic name="Square" register_type_ref="ShapeType" />
		<topic name="Triangle" register_type_ref="ShapeType" />
		<subscriber name="Subscriber_5">
			<data_reader name="SquareReader_5" topic_ref="Square" />
			<data_reader name="TriangleReader_5" topic_ref="Triangle" />
		</subscriber>
	</domain_participant>
</application>

5.3. 部署配置

5.3.1. 节点配置

定义了5个节点,以及ip/mac地址,很清晰,不赘述。

json 复制代码
"node_libraries": [
    {
        "name": "MyNodeLibrary",
        "nodes": [
            {
                "name": "Host_1",
                "hostname": "Host1",
                "ipv4_address": "192.168.1.1",
                "mac_address": "AA:AA:AA:AA:AA:AA"
            },
            {
                "name": "Host_2",
                "hostname": "Host2",
                "ipv4_address": "192.168.1.2",
                "mac_address": "BB:BB:BB:BB:BB:BB"
            },
            {
                "name": "Host_3",
                "hostname": "Host3",
                "ipv4_address": "192.168.1.3",
                "mac_address": "CC:CC:CC:CC:CC:CC"
            },
            {
                "name": "Host_4",
                "hostname": "Host4",
                "ipv4_address": "192.168.1.4",
                "mac_address": "DD:DD:DD:DD:DD:DD"
            },
            {
                "name": "Host_5",
                "hostname": "Host5",
                "ipv4_address": "192.168.1.5",
                "mac_address": "EE:EE:EE:EE:EE:EE"
            }
        ]
    }
]
5.3.2. 部署配置

这里选一个Talker一个Listener详细讲解,Talker示例如下

xml 复制代码
<deployment name="Deployment_Host_1">
	<!-- App1部署在Host1上  -->
	<node node_ref="MyNodeLibrary::Host_1" />
	<application_list>
		<application application_ref="MyApplicationLibrary::Application_1" />
	</application_list>
	<configuration>
		<tsn>
			<!-- Square主题映射为Square流 -->
			<tsn_talker name="SquareWriterTalker_1"
						stream_name="SquareStream"
						datawriter_ref="MyApplicationLibrary::Application_1::DomainParticipant_1::Publisher_1::SquareWriter_1">
				<!-- 该主题数据的标识如下,目标IP、DSCP、UDP、目标端口 -->
				<data_frame_specification>
					<ipv4_tuple>
						<source_ip_address>0.0.0.0</source_ip_address>
						<destination_ip_address>239.255.255.1</destination_ip_address>
						<dscp>0</dscp>
						<protocol>17</protocol>
						<source_port>0</source_port>
						<destination_port>7421</destination_port>
					</ipv4_tuple>
				</data_frame_specification>
				<!-- 该主题数据将以2000000ns为周期发送,每包不超过1000字节,提交到协议栈的偏移范围为[0, 2000000],抖动为5000ns -->
				<traffic_specification>
					<periodicity>
						<sec>0</sec>
						<nanosec>2000000</nanosec>
					</periodicity>
					<samples_per_period>1</samples_per_period>
					<max_bytes_per_sample>1000</max_bytes_per_sample>
					<transmission_selection>0</transmission_selection>
					<time_aware>
						<earliest_transmit_offset>0</earliest_transmit_offset>
						<latest_transmit_offset>2000000</latest_transmit_offset>
						<jitter>5000</jitter>
					</time_aware>
				</traffic_specification>
				<!-- 不需要额外的冗余路径,最大时延不应该超过2000000ns -->
				<network_requirements>
					<num_seamless_trees>1</num_seamless_trees>
					<max_latency>2000000</max_latency>
				</network_requirements>
			</tsn_talker>
		</tsn>
	</configuration>
</deployment>

Listener的配置示例如下:

xml 复制代码
<deployment name="Deployment_Host_3">
	<!-- App3部署在Host3上 -->
	<node node_ref="MyNodeLibrary::Host_3" />
	<application_list>
		<application application_ref="MyApplicationLibrary::Application_3" />
	</application_list>
	<configuration>
		<tsn>
			<!-- 流标识为SquareStream -->
			<tsn_listener name="SquareReaderListener_3"
						  stream_name="SquareStream"
						  datareader_ref="MyApplicationLibrary::Application_3::DomainParticipant_3::Subscriber_3::SquareReader_3">
				<!-- 传输需求为最大时延2000000ns -->
				<network_requirements>
					<num_seamless_trees>1</num_seamless_trees>
					<max_latency>2000000</max_latency>
				</network_requirements>
			</tsn_listener>
		</tsn>
	</configuration>
</deployment>

5.4. 部署过程

5.4.1. 流配置

以Square流配置为例,根据构造规则,将DDS-TSN配置中的TSNTalker转化为YANG的Talker Group请求,如下:

json 复制代码
{
    "stream-id": "AA-AA-AA-AA-AA-AA-00-01",
    "stream-rank": {
        "rank": 1
    },
    "end-station-interfaces": [
        {
            "mac-address": "AA-AA-AA-AA-AA-AA"
        }
    ],
    "data-frame-specification": [
        {
            "ipv4-tuple": {
                "source-ip-address": "0.0.0.0",
                "destination-ip-address": "239.255.255.1",
                "dscp": 0,
                "protocol": 17,
                "source-port": 0,
                "destination-Port": 7421
            }
        }
    ],
    "traffic-specification": {
        "interval": {
            "numerator": 2,
            "denominator": 1000
        },
        "max-frames-per-interval": 1,
        "max-frame-size": 1000,
        "transmission-selection": 0,
        "time-aware": {
            "earliest-transmit-offset": 0,
            "latest-transmit-offset": 2000000,
            "jitter": 5000
        }
    },
    "user-to-network-requirements": {
        "num-seamless-trees": 1,
        "max-latency": 2000000
    },
    "interface-capabilities": {
        "vlan-tag-capable": true,
        "cb-stream-iden-type-list": [],
        "cb-sequence-type-list": []
    }
}

同理将DDS-TSN配置中的TSNListetner转化为YANG的Listener Group请求,如下:

json 复制代码
{
    "stream-id": "AA-AA-AA-AA-AA-AA-00-01",
    "end-station-interfaces": [
        {
            "mac-address": "CC-CC-CC-CC-CC-CC"
        }
    ],
    "user-to-network-requirements": {
        "num-seamless-trees": 1,
        "max-latency": 2000000
    },
    "interface-capabilities": {
        "vlan-tag-capable": true,
        "cb-stream-iden-type-list": [],
        "cb-sequence-type-list": []
    }
}

CNC将会返回Status响应,响应中包含SquareStream的调度结果,内容如下:

json 复制代码
{
    "stream-id": "AA-AA-AA-AA-AA-AA-00-01",
    "status-info": {
        "talker-status": "ready",
        "listener-status": "ready",
        "failure-code": 0
    },
    "accumulated-latency": 150000,
    "interface-configuration": {
        "interface-list": [
            {
                "ieee802-mac-addresses": {
                    "destination-mac-address": "EE-DD-CC-BB-AA-00",
                    "source-mac-address": "AA-AA-AA-AA-AA-AA"
                },
                "ieee802-vlan-tag": {
                    "priority-code-point": 3,
                    "vlan-id": 4500
                },
                "ipv4-tuple": {
                    "source-ip-address": "0.0.0.0",
                    "destination-ip-address": "239.255.255.1",
                    "dscp": 0,
                    "protocol": 17,
                    "source-port": 0,
                    "destination-port": 7421
                },
                "time-aware-offset": 25000
            }
        ]
    }
}

Triangel流配置同理,这里不一一展示。

5.4.2. 节点配置

计算出Stream配置后,每个主机需要为不同应⽤程序的执⾏做好准备。在完全集中的配置模型中,这将由 CUC 负责。在其他模型中,可以是应用或者系统集成商(System integrator)负责这项配置。

如果主机需要配置为执⾏流转换(Stream Transformation),则配置 IEEE 802.1CB 中与流标识相关的函数来执行以下转换:

  • 在Host1上,将IP报文信息与Status.interface-configuration.interface-list0.ipv4-tuple信息相符的以太网头中的DestinationMacAddress以及VlanTag域替换为Status.interface-configurationinterface-list0.ieee802-mac-addresses.destination-mac-address以及Status.interface-configurationinterface-list0.ieee802-vlan-tag.vlan-id,由于Host1与SquareStream关联,所以上面提到的Status为SquareStream关联的Status响应。
  • 在Host5上,将IP报文信息与Status.interface-configuration.interface-list0.ipv4-tuple相符的以太网头中的DestinationMacAddress以及VlanTag域还原到原有的值,由于Host5与SquareStream以及TriangleStream都关联,所以上面提到的Status需要分别对SquareStream与TriangleStream关联的Status响应。
  • Host2/Host3/Host4同理。

注意:如果**流转换(Stream Transformation)**在临近的网桥上执行,以上的配置则无需执行,Status响应中的interface-configuration节点也不会存在。

经过流转换配置,主机被配置为发出的每个样本数据都根据Status响应中的 interface-configuration.interfacelist0.time-aware-offset

5.4.3. DDS应用配置以及执行Schedule

配置主机后,可以开始发布周期。DDS 应⽤程序可能需要调整以符合流时间表,包括:

  • 将QoS调整为8.2.3中规定的值;
  • 使用分区QoS(分区名为stream_name)来限制与TSN流不相关的匹配连接;
  • 配置必须通过其发送时间敏感流量的接⼝。如果需要执行流转换,应用还需要配置IP报文头中的地址为Status响应中的interface-configuration。

根据示例配置,Talker将会以2ms为周期,意味着以2ms的周期调用DataWriter::write操作,底层的DDS库拷贝、序列化并从适当的网络接口上发送报文,所选的时间间隔必须⾜以适应 在指定时间段内执⾏上⾯列出的所有步骤。计算序列化和执⾏时间的机制超出了本规范的范围。

相关推荐
半夜修仙18 小时前
延迟队列的介绍及常见问题
java·数据库·中间件·rabbitmq
手握风云-18 小时前
一条消息的旅程:RabbitMQ 学习与实践(一)
中间件·rabbitmq
RH2312112 天前
2026.6.8Linux
java·数据库·中间件
理人综艺好会2 天前
双Token机制在实际项目中的应用与实践
中间件·token
番茄去哪了3 天前
神领物流面试题(一)
java·大数据·中间件
念何架构之路3 天前
消息中间件
中间件
都说名字长不会被发现3 天前
Spring Boot Starter 中间件账号密码加密方案设计与实现
java·spring boot·后端·中间件
瀚高PG实验室3 天前
java中间件无法连接数据库
java·数据库·中间件·瀚高数据库
之歆4 天前
Day11_Express 深入解析:从中间件到项目实战
中间件·express
码农飞哥4 天前
RocketMQ消费接口设计实战:为什么HTTP回调接口必须吞掉所有异常,始终返回成功?
网络协议·http·中间件·消息队列·rocketmq